xcore-protocol 0.5.2__tar.gz → 0.6.0__tar.gz

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.
Files changed (41) hide show
  1. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/PKG-INFO +1 -1
  2. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/pyproject.toml +1 -1
  3. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/__init__.py +20 -0
  4. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/routes.py +81 -0
  5. xcore_protocol-0.6.0/python/xcore_protocol/generated/sentinel.py +531 -0
  6. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol.egg-info/PKG-INFO +1 -1
  7. xcore_protocol-0.5.2/python/xcore_protocol/generated/sentinel.py +0 -208
  8. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/README.md +0 -0
  9. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_canonical_protocol_fixtures.py +0 -0
  10. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_chat_fixtures.py +0 -0
  11. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_discord_fixtures.py +0 -0
  12. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_envelope_schemas.py +0 -0
  13. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_chat_models.py +0 -0
  14. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_discord_models.py +0 -0
  15. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_maps_models.py +0 -0
  16. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_moderation_models.py +0 -0
  17. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_sentinel_models.py +0 -0
  18. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generated_telemetry_models.py +0 -0
  19. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_generator_bootstrap.py +0 -0
  20. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_java_python_route_compatibility.py +0 -0
  21. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_java_python_serialized_compatibility.py +0 -0
  22. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_maps_fixtures.py +0 -0
  23. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_moderation_fixtures.py +0 -0
  24. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_normalized_route_model.py +0 -0
  25. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/tests/test_telemetry_fixtures.py +0 -0
  26. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/__init__.py +0 -0
  27. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/chat.py +0 -0
  28. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/discord.py +0 -0
  29. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/envelopes.py +0 -0
  30. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/maps.py +0 -0
  31. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/moderation.py +0 -0
  32. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/shared.py +0 -0
  33. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/generated/telemetry.py +0 -0
  34. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/models/__init__.py +0 -0
  35. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/paths.py +0 -0
  36. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol/schema_validation.py +0 -0
  37. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol.egg-info/SOURCES.txt +0 -0
  38. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol.egg-info/dependency_links.txt +0 -0
  39. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol.egg-info/requires.txt +0 -0
  40. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/python/xcore_protocol.egg-info/top_level.txt +0 -0
  41. {xcore_protocol-0.5.2 → xcore_protocol-0.6.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xcore-protocol
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Canonical cross-service protocol for the XCore ecosystem
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xcore-protocol"
7
- version = "0.5.2"
7
+ version = "0.6.0"
8
8
  description = "Canonical cross-service protocol for the XCore ecosystem"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -44,8 +44,15 @@ from .telemetry import (
44
44
  MetricsSnapshotV1,
45
45
  )
46
46
  from .sentinel import (
47
+ SentinelSubnetRulesCheckRequestV1,
48
+ SentinelSubnetRulesCheckResponseV1,
49
+ SentinelSubnetRulesCommandV1,
47
50
  SentinelSubnetRulesInvalidatedV1,
51
+ SentinelSubnetRulesListRequestV1,
52
+ SentinelSubnetRulesListResponseV1,
53
+ SentinelSubnetRulesResponseV1,
48
54
  SentinelSubnetSweepCommandV1,
55
+ SentinelSubnetRulesCommandV1Operation,
49
56
  )
50
57
  from .envelopes import (
51
58
  EnvelopeBaseV1,
@@ -88,6 +95,9 @@ from .routes import (
88
95
  MODERATION_AUDIT_APPENDED_V1,
89
96
  SENTINEL_SUBNET_RULES_INVALIDATED_V1,
90
97
  SENTINEL_SUBNET_SWEEP_COMMAND_V1,
98
+ SENTINEL_SUBNET_RULES_COMMAND_V1,
99
+ SENTINEL_SUBNET_RULES_LIST_REQUEST_V1,
100
+ SENTINEL_SUBNET_RULES_CHECK_REQUEST_V1,
91
101
  RouteDescriptor,
92
102
  RouteResponseDescriptor,
93
103
  ROUTES_BY_MESSAGE,
@@ -162,10 +172,17 @@ __all__ = [
162
172
  "ModerationPardonCommandV1",
163
173
  "ModerationVoteKickCreatedV1",
164
174
  "MetricsSnapshotV1",
175
+ "SentinelSubnetRulesCheckRequestV1",
176
+ "SentinelSubnetRulesCheckResponseV1",
177
+ "SentinelSubnetRulesCommandV1",
165
178
  "SentinelSubnetRulesInvalidatedV1",
179
+ "SentinelSubnetRulesListRequestV1",
180
+ "SentinelSubnetRulesListResponseV1",
181
+ "SentinelSubnetRulesResponseV1",
166
182
  "SentinelSubnetSweepCommandV1",
167
183
  "DiscordLinkStatusChangedV1Action",
168
184
  "ModerationAuditAppendedV1EntryType",
185
+ "SentinelSubnetRulesCommandV1Operation",
169
186
  "MAPS_LIST_REQUEST_V1",
170
187
  "MAPS_REMOVE_REQUEST_V1",
171
188
  "MAPS_LOAD_COMMAND_V1",
@@ -196,6 +213,9 @@ __all__ = [
196
213
  "MODERATION_AUDIT_APPENDED_V1",
197
214
  "SENTINEL_SUBNET_RULES_INVALIDATED_V1",
198
215
  "SENTINEL_SUBNET_SWEEP_COMMAND_V1",
216
+ "SENTINEL_SUBNET_RULES_COMMAND_V1",
217
+ "SENTINEL_SUBNET_RULES_LIST_REQUEST_V1",
218
+ "SENTINEL_SUBNET_RULES_CHECK_REQUEST_V1",
199
219
  "RouteDescriptor",
200
220
  "RouteResponseDescriptor",
201
221
  "ROUTES_BY_MESSAGE",
@@ -50,6 +50,12 @@ from .moderation import (
50
50
  from .sentinel import (
51
51
  SentinelSubnetRulesInvalidatedV1,
52
52
  SentinelSubnetSweepCommandV1,
53
+ SentinelSubnetRulesCommandV1,
54
+ SentinelSubnetRulesResponseV1,
55
+ SentinelSubnetRulesListRequestV1,
56
+ SentinelSubnetRulesListResponseV1,
57
+ SentinelSubnetRulesCheckRequestV1,
58
+ SentinelSubnetRulesCheckResponseV1,
53
59
  )
54
60
 
55
61
  @dataclass(frozen=True, slots=True)
@@ -600,6 +606,75 @@ SENTINEL_SUBNET_SWEEP_COMMAND_V1 = RouteDescriptor(
600
606
  response=None,
601
607
  )
602
608
 
609
+ SENTINEL_SUBNET_RULES_COMMAND_V1 = RouteDescriptor(
610
+ family='sentinel',
611
+ methodName='sentinelSubnetRulesCommandV1Route',
612
+ messageType='sentinel.subnet-rules.command',
613
+ messageVersion=1,
614
+ payloadType=SentinelSubnetRulesCommandV1,
615
+ kind='rpc-request',
616
+ stream='xcore:rpc:req:{targetServer}',
617
+ bindings={'targetServer': 'payload.targetServer'},
618
+ targetScope='server',
619
+ ttlMs=10000,
620
+ replayable=False,
621
+ idempotentConsumerRecommended=True,
622
+ owner='sentinel',
623
+ response=RouteResponseDescriptor(
624
+ messageType='sentinel.subnet-rules.response',
625
+ messageVersion=1,
626
+ payloadType=SentinelSubnetRulesResponseV1,
627
+ stream='xcore:rpc:resp:{requester}',
628
+ bindings={'requester': 'rpc.requester'},
629
+ ),
630
+ )
631
+
632
+ SENTINEL_SUBNET_RULES_LIST_REQUEST_V1 = RouteDescriptor(
633
+ family='sentinel',
634
+ methodName='sentinelSubnetRulesListRequestV1Route',
635
+ messageType='sentinel.subnet-rules.list.request',
636
+ messageVersion=1,
637
+ payloadType=SentinelSubnetRulesListRequestV1,
638
+ kind='rpc-request',
639
+ stream='xcore:rpc:req:{targetServer}',
640
+ bindings={'targetServer': 'payload.targetServer'},
641
+ targetScope='server',
642
+ ttlMs=10000,
643
+ replayable=False,
644
+ idempotentConsumerRecommended=False,
645
+ owner='sentinel',
646
+ response=RouteResponseDescriptor(
647
+ messageType='sentinel.subnet-rules.list.response',
648
+ messageVersion=1,
649
+ payloadType=SentinelSubnetRulesListResponseV1,
650
+ stream='xcore:rpc:resp:{requester}',
651
+ bindings={'requester': 'rpc.requester'},
652
+ ),
653
+ )
654
+
655
+ SENTINEL_SUBNET_RULES_CHECK_REQUEST_V1 = RouteDescriptor(
656
+ family='sentinel',
657
+ methodName='sentinelSubnetRulesCheckRequestV1Route',
658
+ messageType='sentinel.subnet-rules.check.request',
659
+ messageVersion=1,
660
+ payloadType=SentinelSubnetRulesCheckRequestV1,
661
+ kind='rpc-request',
662
+ stream='xcore:rpc:req:{targetServer}',
663
+ bindings={'targetServer': 'payload.targetServer'},
664
+ targetScope='server',
665
+ ttlMs=10000,
666
+ replayable=False,
667
+ idempotentConsumerRecommended=False,
668
+ owner='sentinel',
669
+ response=RouteResponseDescriptor(
670
+ messageType='sentinel.subnet-rules.check.response',
671
+ messageVersion=1,
672
+ payloadType=SentinelSubnetRulesCheckResponseV1,
673
+ stream='xcore:rpc:resp:{requester}',
674
+ bindings={'requester': 'rpc.requester'},
675
+ ),
676
+ )
677
+
603
678
  ROUTES_BY_MESSAGE: dict[tuple[str, int], RouteDescriptor] = {
604
679
  ('maps.list.request', 1): MAPS_LIST_REQUEST_V1,
605
680
  ('maps.remove.request', 1): MAPS_REMOVE_REQUEST_V1,
@@ -631,6 +706,9 @@ ROUTES_BY_MESSAGE: dict[tuple[str, int], RouteDescriptor] = {
631
706
  ('moderation.audit.appended', 1): MODERATION_AUDIT_APPENDED_V1,
632
707
  ('sentinel.subnet-rules.invalidated', 1): SENTINEL_SUBNET_RULES_INVALIDATED_V1,
633
708
  ('sentinel.subnet-sweep.command', 1): SENTINEL_SUBNET_SWEEP_COMMAND_V1,
709
+ ('sentinel.subnet-rules.command', 1): SENTINEL_SUBNET_RULES_COMMAND_V1,
710
+ ('sentinel.subnet-rules.list.request', 1): SENTINEL_SUBNET_RULES_LIST_REQUEST_V1,
711
+ ('sentinel.subnet-rules.check.request', 1): SENTINEL_SUBNET_RULES_CHECK_REQUEST_V1,
634
712
  }
635
713
 
636
714
  MapsRouteResponseDescriptor = RouteResponseDescriptor
@@ -668,6 +746,9 @@ __all__ = [
668
746
  "MODERATION_AUDIT_APPENDED_V1",
669
747
  "SENTINEL_SUBNET_RULES_INVALIDATED_V1",
670
748
  "SENTINEL_SUBNET_SWEEP_COMMAND_V1",
749
+ "SENTINEL_SUBNET_RULES_COMMAND_V1",
750
+ "SENTINEL_SUBNET_RULES_LIST_REQUEST_V1",
751
+ "SENTINEL_SUBNET_RULES_CHECK_REQUEST_V1",
671
752
  "RouteDescriptor",
672
753
  "RouteResponseDescriptor",
673
754
  "ROUTES_BY_MESSAGE",
@@ -0,0 +1,531 @@
1
+ """Generated canonical sentinel protocol models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from dataclasses import dataclass
7
+ from enum import StrEnum
8
+ from typing import Any, ClassVar
9
+
10
+ from .shared import (
11
+ ActorRefV1,
12
+ ActorRefV1ActorType,
13
+ )
14
+
15
+ def _expect_mapping(value: Any, field_name: str) -> Mapping[str, Any]:
16
+ if not isinstance(value, Mapping):
17
+ raise TypeError(f"{field_name} must be an object")
18
+ invalid_keys = [key for key in value.keys() if not isinstance(key, str)]
19
+ if invalid_keys:
20
+ raise TypeError(f"{field_name} keys must be strings")
21
+ return value
22
+
23
+
24
+ def _expect_list(value: Any, field_name: str) -> list[Any]:
25
+ if not isinstance(value, list):
26
+ raise TypeError(f"{field_name} must be a list")
27
+ return value
28
+
29
+
30
+ def _expect_json_object(
31
+ value: Any,
32
+ field_name: str,
33
+ *,
34
+ allowed_types: tuple[str, ...],
35
+ allow_null: bool,
36
+ ) -> dict[str, Any]:
37
+ mapping = _expect_mapping(value, field_name)
38
+ for key, item in mapping.items():
39
+ if item is None:
40
+ if allow_null:
41
+ continue
42
+ raise TypeError(f"{field_name}.{key} must not be null")
43
+ if isinstance(item, bool):
44
+ allowed = "boolean" in allowed_types
45
+ elif isinstance(item, str):
46
+ allowed = "string" in allowed_types
47
+ elif isinstance(item, int):
48
+ allowed = "integer" in allowed_types or "number" in allowed_types
49
+ elif isinstance(item, float):
50
+ allowed = "number" in allowed_types
51
+ else:
52
+ raise TypeError(f"{field_name}.{key} has unsupported value type")
53
+ if not allowed:
54
+ raise TypeError(
55
+ f"{field_name}.{key} must be one of: {', '.join(allowed_types)}"
56
+ )
57
+ return dict(mapping)
58
+
59
+
60
+ def _expect_exact_keys(
61
+ payload: Mapping[str, Any],
62
+ *,
63
+ required: frozenset[str],
64
+ allowed: frozenset[str],
65
+ model_name: str,
66
+ ) -> None:
67
+ actual = frozenset(payload.keys())
68
+ missing = sorted(required - actual)
69
+ unexpected = sorted(actual - allowed)
70
+ if missing:
71
+ raise ValueError(f"{model_name} is missing required fields: {', '.join(missing)}")
72
+ if unexpected:
73
+ raise ValueError(f"{model_name} has unexpected fields: {', '.join(unexpected)}")
74
+
75
+
76
+ def _expect_str(value: Any, field_name: str) -> str:
77
+ if not isinstance(value, str):
78
+ raise TypeError(f"{field_name} must be a string")
79
+ return value
80
+
81
+
82
+ def _expect_int(value: Any, field_name: str) -> int:
83
+ if isinstance(value, bool) or not isinstance(value, int):
84
+ raise TypeError(f"{field_name} must be an integer")
85
+ return value
86
+
87
+
88
+ def _expect_number(value: Any, field_name: str) -> float:
89
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
90
+ raise TypeError(f"{field_name} must be a number")
91
+ return float(value)
92
+
93
+
94
+ def _expect_bool(value: Any, field_name: str) -> bool:
95
+ if not isinstance(value, bool):
96
+ raise TypeError(f"{field_name} must be a boolean")
97
+ return value
98
+
99
+
100
+ def _expect_enum(value: Any, field_name: str, enum_type: type[StrEnum]) -> StrEnum:
101
+ if not isinstance(value, str):
102
+ raise TypeError(f"{field_name} must be a string")
103
+ try:
104
+ return enum_type(value)
105
+ except ValueError as error:
106
+ allowed = ", ".join(member.value for member in enum_type)
107
+ raise ValueError(f"{field_name} must be one of: {allowed}") from error
108
+
109
+
110
+ def _expect_instance(value: Any, field_name: str, expected_type: type[Any]) -> None:
111
+ if not isinstance(value, expected_type):
112
+ raise TypeError(f"{field_name} must be a {expected_type.__name__}")
113
+
114
+ @dataclass(frozen=True, slots=True)
115
+ class SentinelSubnetRulesCheckRequestV1:
116
+ request: str
117
+ targetServer: str
118
+ ip: str
119
+
120
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.check.request'
121
+ MESSAGE_VERSION: ClassVar[int] = 1
122
+ def __post_init__(self) -> None:
123
+ _expect_str(self.request, 'request')
124
+ _expect_str(self.targetServer, 'targetServer')
125
+ _expect_str(self.ip, 'ip')
126
+
127
+ @classmethod
128
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesCheckRequestV1":
129
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesCheckRequestV1")
130
+ _expect_exact_keys(
131
+ mapping,
132
+ required=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'ip')),
133
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'ip')),
134
+ model_name="SentinelSubnetRulesCheckRequestV1",
135
+ )
136
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
137
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
138
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
139
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
140
+ return cls(
141
+ request=_expect_str(mapping['request'], 'request'),
142
+ targetServer=_expect_str(mapping['targetServer'], 'targetServer'),
143
+ ip=_expect_str(mapping['ip'], 'ip'),
144
+ )
145
+
146
+ def to_payload(self) -> dict[str, Any]:
147
+ payload: dict[str, Any] = {
148
+ 'messageType': self.MESSAGE_TYPE,
149
+ 'messageVersion': self.MESSAGE_VERSION,
150
+ }
151
+ payload['request'] = self.request
152
+ payload['targetServer'] = self.targetServer
153
+ payload['ip'] = self.ip
154
+ return payload
155
+
156
+ @dataclass(frozen=True, slots=True)
157
+ class SentinelSubnetRulesCheckResponseV1:
158
+ request: str
159
+ targetServer: str
160
+ allowed: bool
161
+ matchedRules: tuple[str, ...]
162
+
163
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.check.response'
164
+ MESSAGE_VERSION: ClassVar[int] = 1
165
+ def __post_init__(self) -> None:
166
+ _expect_str(self.request, 'request')
167
+ _expect_str(self.targetServer, 'targetServer')
168
+ _expect_bool(self.allowed, 'allowed')
169
+ if not isinstance(self.matchedRules, tuple):
170
+ raise TypeError("matchedRules must be a tuple")
171
+ for item in self.matchedRules:
172
+ _expect_str(item, 'matchedRules[]')
173
+
174
+ @classmethod
175
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesCheckResponseV1":
176
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesCheckResponseV1")
177
+ _expect_exact_keys(
178
+ mapping,
179
+ required=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'allowed', 'matchedRules')),
180
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'allowed', 'matchedRules')),
181
+ model_name="SentinelSubnetRulesCheckResponseV1",
182
+ )
183
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
184
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
185
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
186
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
187
+ return cls(
188
+ request=_expect_str(mapping['request'], 'request'),
189
+ targetServer=_expect_str(mapping['targetServer'], 'targetServer'),
190
+ allowed=_expect_bool(mapping['allowed'], 'allowed'),
191
+ matchedRules=tuple(_expect_str(item, 'matchedRules[]') for item in _expect_list(mapping['matchedRules'], 'matchedRules')),
192
+ )
193
+
194
+ def to_payload(self) -> dict[str, Any]:
195
+ payload: dict[str, Any] = {
196
+ 'messageType': self.MESSAGE_TYPE,
197
+ 'messageVersion': self.MESSAGE_VERSION,
198
+ }
199
+ payload['request'] = self.request
200
+ payload['targetServer'] = self.targetServer
201
+ payload['allowed'] = self.allowed
202
+ payload['matchedRules'] = [item for item in self.matchedRules]
203
+ return payload
204
+
205
+ class SentinelSubnetRulesCommandV1Operation(StrEnum):
206
+ ALLOW = 'ALLOW'
207
+ DENY = 'DENY'
208
+ REMOVE = 'REMOVE'
209
+ IMPORT = 'IMPORT'
210
+ RELOAD = 'RELOAD'
211
+
212
+ @dataclass(frozen=True, slots=True)
213
+ class SentinelSubnetRulesCommandV1:
214
+ request: str
215
+ idempotency: str
216
+ actor: ActorRefV1
217
+ operation: SentinelSubnetRulesCommandV1Operation
218
+ rules: tuple[str, ...]
219
+ targetServer: str | None = None
220
+ source: str | None = None
221
+ reason: str | None = None
222
+
223
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.command'
224
+ MESSAGE_VERSION: ClassVar[int] = 1
225
+ def __post_init__(self) -> None:
226
+ _expect_str(self.request, 'request')
227
+ _expect_str(self.idempotency, 'idempotency')
228
+ _expect_instance(self.actor, 'actor', ActorRefV1)
229
+ _expect_instance(self.operation, 'operation', SentinelSubnetRulesCommandV1Operation)
230
+ if self.targetServer is not None:
231
+ _expect_str(self.targetServer, 'targetServer')
232
+ if not isinstance(self.rules, tuple):
233
+ raise TypeError("rules must be a tuple")
234
+ for item in self.rules:
235
+ _expect_str(item, 'rules[]')
236
+ if self.source is not None:
237
+ _expect_str(self.source, 'source')
238
+ if self.reason is not None:
239
+ _expect_str(self.reason, 'reason')
240
+
241
+ @classmethod
242
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesCommandV1":
243
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesCommandV1")
244
+ _expect_exact_keys(
245
+ mapping,
246
+ required=frozenset(('messageType', 'messageVersion', 'request', 'idempotency', 'actor', 'operation', 'rules')),
247
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'idempotency', 'actor', 'operation', 'targetServer', 'rules', 'source', 'reason')),
248
+ model_name="SentinelSubnetRulesCommandV1",
249
+ )
250
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
251
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
252
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
253
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
254
+ return cls(
255
+ request=_expect_str(mapping['request'], 'request'),
256
+ idempotency=_expect_str(mapping['idempotency'], 'idempotency'),
257
+ actor=ActorRefV1.from_payload(_expect_mapping(mapping['actor'], 'actor')),
258
+ operation=_expect_enum(mapping['operation'], 'operation', SentinelSubnetRulesCommandV1Operation),
259
+ targetServer=(_expect_str(mapping['targetServer'], 'targetServer') if 'targetServer' in mapping else None),
260
+ rules=tuple(_expect_str(item, 'rules[]') for item in _expect_list(mapping['rules'], 'rules')),
261
+ source=(_expect_str(mapping['source'], 'source') if 'source' in mapping else None),
262
+ reason=(_expect_str(mapping['reason'], 'reason') if 'reason' in mapping else None),
263
+ )
264
+
265
+ def to_payload(self) -> dict[str, Any]:
266
+ payload: dict[str, Any] = {
267
+ 'messageType': self.MESSAGE_TYPE,
268
+ 'messageVersion': self.MESSAGE_VERSION,
269
+ }
270
+ payload['request'] = self.request
271
+ payload['idempotency'] = self.idempotency
272
+ payload['actor'] = self.actor.to_payload()
273
+ payload['operation'] = str(self.operation)
274
+ if self.targetServer is not None:
275
+ payload['targetServer'] = self.targetServer
276
+ payload['rules'] = [item for item in self.rules]
277
+ if self.source is not None:
278
+ payload['source'] = self.source
279
+ if self.reason is not None:
280
+ payload['reason'] = self.reason
281
+ return payload
282
+
283
+ @dataclass(frozen=True, slots=True)
284
+ class SentinelSubnetRulesInvalidatedV1:
285
+ reason: str | None = None
286
+ sourceServer: str | None = None
287
+ occurredAt: str | None = None
288
+
289
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.invalidated'
290
+ MESSAGE_VERSION: ClassVar[int] = 1
291
+ def __post_init__(self) -> None:
292
+ if self.reason is not None:
293
+ _expect_str(self.reason, 'reason')
294
+ if self.sourceServer is not None:
295
+ _expect_str(self.sourceServer, 'sourceServer')
296
+ if self.occurredAt is not None:
297
+ _expect_str(self.occurredAt, 'occurredAt')
298
+
299
+ @classmethod
300
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesInvalidatedV1":
301
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesInvalidatedV1")
302
+ _expect_exact_keys(
303
+ mapping,
304
+ required=frozenset(('messageType', 'messageVersion')),
305
+ allowed=frozenset(('messageType', 'messageVersion', 'reason', 'sourceServer', 'occurredAt')),
306
+ model_name="SentinelSubnetRulesInvalidatedV1",
307
+ )
308
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
309
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
310
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
311
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
312
+ return cls(
313
+ reason=(_expect_str(mapping['reason'], 'reason') if 'reason' in mapping else None),
314
+ sourceServer=(_expect_str(mapping['sourceServer'], 'sourceServer') if 'sourceServer' in mapping else None),
315
+ occurredAt=(_expect_str(mapping['occurredAt'], 'occurredAt') if 'occurredAt' in mapping else None),
316
+ )
317
+
318
+ def to_payload(self) -> dict[str, Any]:
319
+ payload: dict[str, Any] = {
320
+ 'messageType': self.MESSAGE_TYPE,
321
+ 'messageVersion': self.MESSAGE_VERSION,
322
+ }
323
+ if self.reason is not None:
324
+ payload['reason'] = self.reason
325
+ if self.sourceServer is not None:
326
+ payload['sourceServer'] = self.sourceServer
327
+ if self.occurredAt is not None:
328
+ payload['occurredAt'] = self.occurredAt
329
+ return payload
330
+
331
+ @dataclass(frozen=True, slots=True)
332
+ class SentinelSubnetRulesListRequestV1:
333
+ request: str
334
+ targetServer: str
335
+
336
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.list.request'
337
+ MESSAGE_VERSION: ClassVar[int] = 1
338
+ def __post_init__(self) -> None:
339
+ _expect_str(self.request, 'request')
340
+ _expect_str(self.targetServer, 'targetServer')
341
+
342
+ @classmethod
343
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesListRequestV1":
344
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesListRequestV1")
345
+ _expect_exact_keys(
346
+ mapping,
347
+ required=frozenset(('messageType', 'messageVersion', 'request', 'targetServer')),
348
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'targetServer')),
349
+ model_name="SentinelSubnetRulesListRequestV1",
350
+ )
351
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
352
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
353
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
354
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
355
+ return cls(
356
+ request=_expect_str(mapping['request'], 'request'),
357
+ targetServer=_expect_str(mapping['targetServer'], 'targetServer'),
358
+ )
359
+
360
+ def to_payload(self) -> dict[str, Any]:
361
+ payload: dict[str, Any] = {
362
+ 'messageType': self.MESSAGE_TYPE,
363
+ 'messageVersion': self.MESSAGE_VERSION,
364
+ }
365
+ payload['request'] = self.request
366
+ payload['targetServer'] = self.targetServer
367
+ return payload
368
+
369
+ @dataclass(frozen=True, slots=True)
370
+ class SentinelSubnetRulesListResponseV1:
371
+ request: str
372
+ targetServer: str
373
+ rules: tuple[str, ...]
374
+
375
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.list.response'
376
+ MESSAGE_VERSION: ClassVar[int] = 1
377
+ def __post_init__(self) -> None:
378
+ _expect_str(self.request, 'request')
379
+ _expect_str(self.targetServer, 'targetServer')
380
+ if not isinstance(self.rules, tuple):
381
+ raise TypeError("rules must be a tuple")
382
+ for item in self.rules:
383
+ _expect_str(item, 'rules[]')
384
+
385
+ @classmethod
386
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesListResponseV1":
387
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesListResponseV1")
388
+ _expect_exact_keys(
389
+ mapping,
390
+ required=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'rules')),
391
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'targetServer', 'rules')),
392
+ model_name="SentinelSubnetRulesListResponseV1",
393
+ )
394
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
395
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
396
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
397
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
398
+ return cls(
399
+ request=_expect_str(mapping['request'], 'request'),
400
+ targetServer=_expect_str(mapping['targetServer'], 'targetServer'),
401
+ rules=tuple(_expect_str(item, 'rules[]') for item in _expect_list(mapping['rules'], 'rules')),
402
+ )
403
+
404
+ def to_payload(self) -> dict[str, Any]:
405
+ payload: dict[str, Any] = {
406
+ 'messageType': self.MESSAGE_TYPE,
407
+ 'messageVersion': self.MESSAGE_VERSION,
408
+ }
409
+ payload['request'] = self.request
410
+ payload['targetServer'] = self.targetServer
411
+ payload['rules'] = [item for item in self.rules]
412
+ return payload
413
+
414
+ @dataclass(frozen=True, slots=True)
415
+ class SentinelSubnetRulesResponseV1:
416
+ request: str
417
+ success: bool
418
+ targetServer: str | None = None
419
+ error: str | None = None
420
+ rules: tuple[str, ...] | None = None
421
+
422
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.response'
423
+ MESSAGE_VERSION: ClassVar[int] = 1
424
+ def __post_init__(self) -> None:
425
+ _expect_str(self.request, 'request')
426
+ _expect_bool(self.success, 'success')
427
+ if self.targetServer is not None:
428
+ _expect_str(self.targetServer, 'targetServer')
429
+ if self.error is not None:
430
+ _expect_str(self.error, 'error')
431
+ if self.rules is not None:
432
+ if not isinstance(self.rules, tuple):
433
+ raise TypeError("rules must be a tuple")
434
+ for item in self.rules:
435
+ _expect_str(item, 'rules[]')
436
+
437
+ @classmethod
438
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesResponseV1":
439
+ mapping = _expect_mapping(payload, "SentinelSubnetRulesResponseV1")
440
+ _expect_exact_keys(
441
+ mapping,
442
+ required=frozenset(('messageType', 'messageVersion', 'request', 'success')),
443
+ allowed=frozenset(('messageType', 'messageVersion', 'request', 'success', 'targetServer', 'error', 'rules')),
444
+ model_name="SentinelSubnetRulesResponseV1",
445
+ )
446
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
447
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
448
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
449
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
450
+ return cls(
451
+ request=_expect_str(mapping['request'], 'request'),
452
+ success=_expect_bool(mapping['success'], 'success'),
453
+ targetServer=(_expect_str(mapping['targetServer'], 'targetServer') if 'targetServer' in mapping else None),
454
+ error=(_expect_str(mapping['error'], 'error') if 'error' in mapping else None),
455
+ rules=(tuple(_expect_str(item, 'rules[]') for item in _expect_list(mapping['rules'], 'rules')) if 'rules' in mapping else None),
456
+ )
457
+
458
+ def to_payload(self) -> dict[str, Any]:
459
+ payload: dict[str, Any] = {
460
+ 'messageType': self.MESSAGE_TYPE,
461
+ 'messageVersion': self.MESSAGE_VERSION,
462
+ }
463
+ payload['request'] = self.request
464
+ payload['success'] = self.success
465
+ if self.targetServer is not None:
466
+ payload['targetServer'] = self.targetServer
467
+ if self.error is not None:
468
+ payload['error'] = self.error
469
+ if self.rules is not None:
470
+ payload['rules'] = [item for item in self.rules]
471
+ return payload
472
+
473
+ @dataclass(frozen=True, slots=True)
474
+ class SentinelSubnetSweepCommandV1:
475
+ actor: str | None = None
476
+ reason: str | None = None
477
+ occurredAt: str | None = None
478
+
479
+ MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-sweep.command'
480
+ MESSAGE_VERSION: ClassVar[int] = 1
481
+ def __post_init__(self) -> None:
482
+ if self.actor is not None:
483
+ _expect_str(self.actor, 'actor')
484
+ if self.reason is not None:
485
+ _expect_str(self.reason, 'reason')
486
+ if self.occurredAt is not None:
487
+ _expect_str(self.occurredAt, 'occurredAt')
488
+
489
+ @classmethod
490
+ def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetSweepCommandV1":
491
+ mapping = _expect_mapping(payload, "SentinelSubnetSweepCommandV1")
492
+ _expect_exact_keys(
493
+ mapping,
494
+ required=frozenset(('messageType', 'messageVersion')),
495
+ allowed=frozenset(('messageType', 'messageVersion', 'actor', 'reason', 'occurredAt')),
496
+ model_name="SentinelSubnetSweepCommandV1",
497
+ )
498
+ if mapping['messageType'] != cls.MESSAGE_TYPE:
499
+ raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
500
+ if mapping['messageVersion'] != cls.MESSAGE_VERSION:
501
+ raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
502
+ return cls(
503
+ actor=(_expect_str(mapping['actor'], 'actor') if 'actor' in mapping else None),
504
+ reason=(_expect_str(mapping['reason'], 'reason') if 'reason' in mapping else None),
505
+ occurredAt=(_expect_str(mapping['occurredAt'], 'occurredAt') if 'occurredAt' in mapping else None),
506
+ )
507
+
508
+ def to_payload(self) -> dict[str, Any]:
509
+ payload: dict[str, Any] = {
510
+ 'messageType': self.MESSAGE_TYPE,
511
+ 'messageVersion': self.MESSAGE_VERSION,
512
+ }
513
+ if self.actor is not None:
514
+ payload['actor'] = self.actor
515
+ if self.reason is not None:
516
+ payload['reason'] = self.reason
517
+ if self.occurredAt is not None:
518
+ payload['occurredAt'] = self.occurredAt
519
+ return payload
520
+
521
+ __all__ = [
522
+ "SentinelSubnetRulesCheckRequestV1",
523
+ "SentinelSubnetRulesCheckResponseV1",
524
+ "SentinelSubnetRulesCommandV1",
525
+ "SentinelSubnetRulesInvalidatedV1",
526
+ "SentinelSubnetRulesListRequestV1",
527
+ "SentinelSubnetRulesListResponseV1",
528
+ "SentinelSubnetRulesResponseV1",
529
+ "SentinelSubnetSweepCommandV1",
530
+ "SentinelSubnetRulesCommandV1Operation",
531
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xcore-protocol
3
- Version: 0.5.2
3
+ Version: 0.6.0
4
4
  Summary: Canonical cross-service protocol for the XCore ecosystem
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,208 +0,0 @@
1
- """Generated canonical sentinel protocol models."""
2
-
3
- from __future__ import annotations
4
-
5
- from collections.abc import Mapping
6
- from dataclasses import dataclass
7
- from enum import StrEnum
8
- from typing import Any, ClassVar
9
-
10
- def _expect_mapping(value: Any, field_name: str) -> Mapping[str, Any]:
11
- if not isinstance(value, Mapping):
12
- raise TypeError(f"{field_name} must be an object")
13
- invalid_keys = [key for key in value.keys() if not isinstance(key, str)]
14
- if invalid_keys:
15
- raise TypeError(f"{field_name} keys must be strings")
16
- return value
17
-
18
-
19
- def _expect_list(value: Any, field_name: str) -> list[Any]:
20
- if not isinstance(value, list):
21
- raise TypeError(f"{field_name} must be a list")
22
- return value
23
-
24
-
25
- def _expect_json_object(
26
- value: Any,
27
- field_name: str,
28
- *,
29
- allowed_types: tuple[str, ...],
30
- allow_null: bool,
31
- ) -> dict[str, Any]:
32
- mapping = _expect_mapping(value, field_name)
33
- for key, item in mapping.items():
34
- if item is None:
35
- if allow_null:
36
- continue
37
- raise TypeError(f"{field_name}.{key} must not be null")
38
- if isinstance(item, bool):
39
- allowed = "boolean" in allowed_types
40
- elif isinstance(item, str):
41
- allowed = "string" in allowed_types
42
- elif isinstance(item, int):
43
- allowed = "integer" in allowed_types or "number" in allowed_types
44
- elif isinstance(item, float):
45
- allowed = "number" in allowed_types
46
- else:
47
- raise TypeError(f"{field_name}.{key} has unsupported value type")
48
- if not allowed:
49
- raise TypeError(
50
- f"{field_name}.{key} must be one of: {', '.join(allowed_types)}"
51
- )
52
- return dict(mapping)
53
-
54
-
55
- def _expect_exact_keys(
56
- payload: Mapping[str, Any],
57
- *,
58
- required: frozenset[str],
59
- allowed: frozenset[str],
60
- model_name: str,
61
- ) -> None:
62
- actual = frozenset(payload.keys())
63
- missing = sorted(required - actual)
64
- unexpected = sorted(actual - allowed)
65
- if missing:
66
- raise ValueError(f"{model_name} is missing required fields: {', '.join(missing)}")
67
- if unexpected:
68
- raise ValueError(f"{model_name} has unexpected fields: {', '.join(unexpected)}")
69
-
70
-
71
- def _expect_str(value: Any, field_name: str) -> str:
72
- if not isinstance(value, str):
73
- raise TypeError(f"{field_name} must be a string")
74
- return value
75
-
76
-
77
- def _expect_int(value: Any, field_name: str) -> int:
78
- if isinstance(value, bool) or not isinstance(value, int):
79
- raise TypeError(f"{field_name} must be an integer")
80
- return value
81
-
82
-
83
- def _expect_number(value: Any, field_name: str) -> float:
84
- if isinstance(value, bool) or not isinstance(value, (int, float)):
85
- raise TypeError(f"{field_name} must be a number")
86
- return float(value)
87
-
88
-
89
- def _expect_bool(value: Any, field_name: str) -> bool:
90
- if not isinstance(value, bool):
91
- raise TypeError(f"{field_name} must be a boolean")
92
- return value
93
-
94
-
95
- def _expect_enum(value: Any, field_name: str, enum_type: type[StrEnum]) -> StrEnum:
96
- if not isinstance(value, str):
97
- raise TypeError(f"{field_name} must be a string")
98
- try:
99
- return enum_type(value)
100
- except ValueError as error:
101
- allowed = ", ".join(member.value for member in enum_type)
102
- raise ValueError(f"{field_name} must be one of: {allowed}") from error
103
-
104
-
105
- def _expect_instance(value: Any, field_name: str, expected_type: type[Any]) -> None:
106
- if not isinstance(value, expected_type):
107
- raise TypeError(f"{field_name} must be a {expected_type.__name__}")
108
-
109
- @dataclass(frozen=True, slots=True)
110
- class SentinelSubnetRulesInvalidatedV1:
111
- reason: str | None = None
112
- sourceServer: str | None = None
113
- occurredAt: str | None = None
114
-
115
- MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-rules.invalidated'
116
- MESSAGE_VERSION: ClassVar[int] = 1
117
- def __post_init__(self) -> None:
118
- if self.reason is not None:
119
- _expect_str(self.reason, 'reason')
120
- if self.sourceServer is not None:
121
- _expect_str(self.sourceServer, 'sourceServer')
122
- if self.occurredAt is not None:
123
- _expect_str(self.occurredAt, 'occurredAt')
124
-
125
- @classmethod
126
- def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetRulesInvalidatedV1":
127
- mapping = _expect_mapping(payload, "SentinelSubnetRulesInvalidatedV1")
128
- _expect_exact_keys(
129
- mapping,
130
- required=frozenset(('messageType', 'messageVersion')),
131
- allowed=frozenset(('messageType', 'messageVersion', 'reason', 'sourceServer', 'occurredAt')),
132
- model_name="SentinelSubnetRulesInvalidatedV1",
133
- )
134
- if mapping['messageType'] != cls.MESSAGE_TYPE:
135
- raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
136
- if mapping['messageVersion'] != cls.MESSAGE_VERSION:
137
- raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
138
- return cls(
139
- reason=(_expect_str(mapping['reason'], 'reason') if 'reason' in mapping else None),
140
- sourceServer=(_expect_str(mapping['sourceServer'], 'sourceServer') if 'sourceServer' in mapping else None),
141
- occurredAt=(_expect_str(mapping['occurredAt'], 'occurredAt') if 'occurredAt' in mapping else None),
142
- )
143
-
144
- def to_payload(self) -> dict[str, Any]:
145
- payload: dict[str, Any] = {
146
- 'messageType': self.MESSAGE_TYPE,
147
- 'messageVersion': self.MESSAGE_VERSION,
148
- }
149
- if self.reason is not None:
150
- payload['reason'] = self.reason
151
- if self.sourceServer is not None:
152
- payload['sourceServer'] = self.sourceServer
153
- if self.occurredAt is not None:
154
- payload['occurredAt'] = self.occurredAt
155
- return payload
156
-
157
- @dataclass(frozen=True, slots=True)
158
- class SentinelSubnetSweepCommandV1:
159
- actor: str | None = None
160
- reason: str | None = None
161
- occurredAt: str | None = None
162
-
163
- MESSAGE_TYPE: ClassVar[str] = 'sentinel.subnet-sweep.command'
164
- MESSAGE_VERSION: ClassVar[int] = 1
165
- def __post_init__(self) -> None:
166
- if self.actor is not None:
167
- _expect_str(self.actor, 'actor')
168
- if self.reason is not None:
169
- _expect_str(self.reason, 'reason')
170
- if self.occurredAt is not None:
171
- _expect_str(self.occurredAt, 'occurredAt')
172
-
173
- @classmethod
174
- def from_payload(cls, payload: Mapping[str, Any]) -> "SentinelSubnetSweepCommandV1":
175
- mapping = _expect_mapping(payload, "SentinelSubnetSweepCommandV1")
176
- _expect_exact_keys(
177
- mapping,
178
- required=frozenset(('messageType', 'messageVersion')),
179
- allowed=frozenset(('messageType', 'messageVersion', 'actor', 'reason', 'occurredAt')),
180
- model_name="SentinelSubnetSweepCommandV1",
181
- )
182
- if mapping['messageType'] != cls.MESSAGE_TYPE:
183
- raise ValueError('messageType' + " must equal " + repr(cls.MESSAGE_TYPE))
184
- if mapping['messageVersion'] != cls.MESSAGE_VERSION:
185
- raise ValueError('messageVersion' + " must equal " + repr(cls.MESSAGE_VERSION))
186
- return cls(
187
- actor=(_expect_str(mapping['actor'], 'actor') if 'actor' in mapping else None),
188
- reason=(_expect_str(mapping['reason'], 'reason') if 'reason' in mapping else None),
189
- occurredAt=(_expect_str(mapping['occurredAt'], 'occurredAt') if 'occurredAt' in mapping else None),
190
- )
191
-
192
- def to_payload(self) -> dict[str, Any]:
193
- payload: dict[str, Any] = {
194
- 'messageType': self.MESSAGE_TYPE,
195
- 'messageVersion': self.MESSAGE_VERSION,
196
- }
197
- if self.actor is not None:
198
- payload['actor'] = self.actor
199
- if self.reason is not None:
200
- payload['reason'] = self.reason
201
- if self.occurredAt is not None:
202
- payload['occurredAt'] = self.occurredAt
203
- return payload
204
-
205
- __all__ = [
206
- "SentinelSubnetRulesInvalidatedV1",
207
- "SentinelSubnetSweepCommandV1",
208
- ]
File without changes
File without changes