lockss-pybasic 0.3.0.dev3__py3-none-any.whl → 0.3.0.dev4__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.
- lockss/pybasic/__init__.py +1 -1
- lockss/pybasic/nodeutil.py +68 -19
- {lockss_pybasic-0.3.0.dev3.dist-info → lockss_pybasic-0.3.0.dev4.dist-info}/METADATA +2 -2
- lockss_pybasic-0.3.0.dev4.dist-info/RECORD +10 -0
- lockss_pybasic-0.3.0.dev3.dist-info/RECORD +0 -10
- {lockss_pybasic-0.3.0.dev3.dist-info → lockss_pybasic-0.3.0.dev4.dist-info}/WHEEL +0 -0
- {lockss_pybasic-0.3.0.dev3.dist-info → lockss_pybasic-0.3.0.dev4.dist-info}/licenses/LICENSE +0 -0
lockss/pybasic/__init__.py
CHANGED
lockss/pybasic/nodeutil.py
CHANGED
|
@@ -35,33 +35,35 @@ LOCKSS node utilities.
|
|
|
35
35
|
from enum import Enum
|
|
36
36
|
from re import Match, Pattern
|
|
37
37
|
import re
|
|
38
|
-
from typing import Annotated, ClassVar, Literal, Optional, Union
|
|
38
|
+
from typing import Annotated, Any, ClassVar, Literal, Optional, Union
|
|
39
39
|
|
|
40
40
|
from annotated_types import Ge, Le
|
|
41
|
-
from pydantic import BaseModel, Field, TypeAdapter
|
|
42
|
-
|
|
43
|
-
from .errorutil import InternalError
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
RE_NODE_REFERENCE: Pattern[str] = re.compile(r'((?P<protocol>https?)://)?(?P<host>[^:]+)(:(?P<repository>\d+|(?=:))(:(?P<configuration>\d+|(?=:))(:(?P<poller>\d+|(?=:))(:(?P<crawler>\d+|(?=:))(:(?P<metadata>\d+|(?=:))(:(?P<soap>\d+))?)?)?)?)?)?')
|
|
41
|
+
from pydantic import BaseModel, BeforeValidator, Field, TypeAdapter, model_validator
|
|
47
42
|
|
|
48
43
|
|
|
44
|
+
#: An annotated type for port numbers (0-65535)
|
|
49
45
|
PortNumber = Annotated[int, Ge(0), Le(65535)]
|
|
50
46
|
|
|
51
47
|
|
|
52
48
|
class NodeTypeEnum(Enum):
|
|
49
|
+
"""An enumerated type representing LOCKSS node types."""
|
|
50
|
+
#: An enumerated constant representing LOCKSS 1.x nodes.
|
|
53
51
|
V1 = 'v1'
|
|
52
|
+
#: An enumerated constant representing LOCKSS 2.x nodes.
|
|
54
53
|
V2 = 'v2'
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
class NodeProtocolEnum(Enum):
|
|
57
|
+
"""An enumerated type representing protocols for reaching LOCKSS nodes."""
|
|
58
|
+
#: An enumerated constant representing HTTP.
|
|
58
59
|
HTTP = 'http'
|
|
60
|
+
#: An enumerated constant representing HTTPS.
|
|
59
61
|
HTTPS = 'https'
|
|
60
62
|
|
|
61
63
|
|
|
62
64
|
class BaseNodeSpec(BaseModel):
|
|
63
65
|
|
|
64
|
-
DEFAULT_PROTOCOL: ClassVar[NodeProtocolEnum] = NodeProtocolEnum.
|
|
66
|
+
DEFAULT_PROTOCOL: ClassVar[NodeProtocolEnum] = NodeProtocolEnum.HTTP
|
|
65
67
|
|
|
66
68
|
TYPE_FIELD: ClassVar[dict[str, str]] = dict(title='Type',
|
|
67
69
|
description="The node's type")
|
|
@@ -126,21 +128,15 @@ class NodeSpec2(BaseNodeSpec):
|
|
|
126
128
|
description="The node's SOAP Compatibility Service REST API Port")
|
|
127
129
|
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
_node_spec_adapter: TypeAdapter[NodeSpec] = TypeAdapter(NodeSpec)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def get_node_spec_adapter() -> TypeAdapter[NodeSpec]:
|
|
136
|
-
return _node_spec_adapter
|
|
131
|
+
_RE_NODE_REFERENCE: Pattern[str] = re.compile(r'((?P<protocol>https?)://)?(?P<host>[^:]+)(:(?P<repository>\d+|(?=:))(:(?P<configuration>\d+|(?=:))(:(?P<poller>\d+|(?=:))(:(?P<crawler>\d+|(?=:))(:(?P<metadata>\d+|(?=:))(:(?P<soap>\d+))?)?)?)?)?)?')
|
|
137
132
|
|
|
138
133
|
|
|
134
|
+
#: A type for LOCKSS node specification strings.
|
|
139
135
|
NodeSpecStr = str
|
|
140
136
|
|
|
141
137
|
|
|
142
|
-
def
|
|
143
|
-
mat: Optional[Match[str]] =
|
|
138
|
+
def _parse_node_spec_string(node_spec_string: NodeSpecStr) -> dict[str, str]:
|
|
139
|
+
mat: Optional[Match[str]] = _RE_NODE_REFERENCE.fullmatch(node_spec_string)
|
|
144
140
|
if mat is None:
|
|
145
141
|
raise ValueError(f'Invalid node specification string: {node_spec_string}')
|
|
146
142
|
d = dict(host=mat.group('host'))
|
|
@@ -164,4 +160,57 @@ def make_node_spec(node_spec_string: NodeSpecStr) -> NodeSpec:
|
|
|
164
160
|
for k in five:
|
|
165
161
|
if p := mat.group(k):
|
|
166
162
|
d[k] = p # string okay, will be coerced to int
|
|
167
|
-
return
|
|
163
|
+
return d
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _maybe_deserialize_node_spec_string(value: Any) -> Any:
|
|
167
|
+
if isinstance(value, NodeSpecStr) and not value.startswith('{'):
|
|
168
|
+
return _parse_node_spec_string(value)
|
|
169
|
+
return value
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
#: A type for LOCKSS node specifications, that also accepts a compact LOCKSS
|
|
173
|
+
#: node specification string.
|
|
174
|
+
NodeSpec = Annotated[
|
|
175
|
+
Annotated[Union[NodeSpec1, NodeSpec2], Field(discriminator='type')],
|
|
176
|
+
BeforeValidator(_maybe_deserialize_node_spec_string)
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
#: A type adapter for the NodeSpec type.
|
|
181
|
+
_node_spec_adapter: TypeAdapter[NodeSpec] = TypeAdapter(NodeSpec)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def get_node_spec_adapter() -> TypeAdapter[NodeSpec]:
|
|
185
|
+
"""
|
|
186
|
+
Gets a type adapter for the NodeSpec type, which is a union type and cannot
|
|
187
|
+
be instantiated directly.
|
|
188
|
+
|
|
189
|
+
:return: A type adapter for the NodeSpec type.
|
|
190
|
+
"""
|
|
191
|
+
return _node_spec_adapter
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
NodeSetKind = Literal['NodeSet']
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
NodeSetIdentifier = str
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
NodeIdentifier = str
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class NodeSet(BaseModel):
|
|
204
|
+
|
|
205
|
+
kind: NodeSetKind = Field(title='Kind',
|
|
206
|
+
description="This object's kind")
|
|
207
|
+
|
|
208
|
+
id: NodeSetIdentifier = Field(title='Node Set Identifier',
|
|
209
|
+
description='An identifier for the node set')
|
|
210
|
+
|
|
211
|
+
name: str = Field(title='Node Set Name',
|
|
212
|
+
description='A name for the node set')
|
|
213
|
+
|
|
214
|
+
nodes: dict[NodeIdentifier, NodeSpec] = Field(min_length=1,
|
|
215
|
+
title='Nodes',
|
|
216
|
+
description='A non-empty list of nodes')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lockss-pybasic
|
|
3
|
-
Version: 0.3.0.
|
|
3
|
+
Version: 0.3.0.dev4
|
|
4
4
|
Summary: Basic Python utilities
|
|
5
5
|
License: BSD-3-Clause
|
|
6
6
|
License-File: LICENSE
|
|
@@ -26,7 +26,7 @@ Description-Content-Type: text/x-rst
|
|
|
26
26
|
lockss-pybasic
|
|
27
27
|
==============
|
|
28
28
|
|
|
29
|
-
.. |RELEASE| replace:: 0.3.0-
|
|
29
|
+
.. |RELEASE| replace:: 0.3.0-dev4
|
|
30
30
|
.. |RELEASE_DATE| replace:: NOT YET RELEASED
|
|
31
31
|
|
|
32
32
|
**Latest release:** |RELEASE| (|RELEASE_DATE|)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
lockss/pybasic/__init__.py,sha256=NWFBmNQ6XEuQOYE0WVIYhe0Ci5wIxmzBewZ_oY8u-G8,1678
|
|
2
|
+
lockss/pybasic/auidutil.py,sha256=Q4vjjGfymiXVwPu35RyyLZBnViv8mDJKCjOyJb-sbS8,13921
|
|
3
|
+
lockss/pybasic/cliutil.py,sha256=F970MhLcQCYS3INLQT1Ij8nKt_ICmttiS3nSnuWuN7s,8106
|
|
4
|
+
lockss/pybasic/errorutil.py,sha256=4EaO0a1yIG1DbWltASeT15bg1bGg5kOYspsW0iJdVLc,1951
|
|
5
|
+
lockss/pybasic/fileutil.py,sha256=IIS2AFDgYtmBLPVHqQi1AkIFj6da04b6NQtjX9bIVqQ,2958
|
|
6
|
+
lockss/pybasic/nodeutil.py,sha256=snBT7OPttThBJXVxgLC6Onmuoa8Z-jOOM1LWdhIb-js,7928
|
|
7
|
+
lockss_pybasic-0.3.0.dev4.dist-info/METADATA,sha256=eZ1B2T-R5rn4u2ZXTkcWZFEGChVqOxbbV5FT-pusIpw,2338
|
|
8
|
+
lockss_pybasic-0.3.0.dev4.dist-info/WHEEL,sha256=eY7nduwzv-ldUxpzbRlxwvC693Hg6PX8bWDjEHjZ_dk,88
|
|
9
|
+
lockss_pybasic-0.3.0.dev4.dist-info/licenses/LICENSE,sha256=EOxPunNz3XP6AjgbPFolu-d9BS_AF9TtKn1WXgeYPsE,1506
|
|
10
|
+
lockss_pybasic-0.3.0.dev4.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
lockss/pybasic/__init__.py,sha256=wBkseM3G1zUhxYaKUdsw7FygMFNiaPmwpPmDRGCEIsA,1678
|
|
2
|
-
lockss/pybasic/auidutil.py,sha256=Q4vjjGfymiXVwPu35RyyLZBnViv8mDJKCjOyJb-sbS8,13921
|
|
3
|
-
lockss/pybasic/cliutil.py,sha256=F970MhLcQCYS3INLQT1Ij8nKt_ICmttiS3nSnuWuN7s,8106
|
|
4
|
-
lockss/pybasic/errorutil.py,sha256=4EaO0a1yIG1DbWltASeT15bg1bGg5kOYspsW0iJdVLc,1951
|
|
5
|
-
lockss/pybasic/fileutil.py,sha256=IIS2AFDgYtmBLPVHqQi1AkIFj6da04b6NQtjX9bIVqQ,2958
|
|
6
|
-
lockss/pybasic/nodeutil.py,sha256=MUd8JoJmn_cZSN8iwG5KOLSRorIfHIEySeYhojm5rlw,6206
|
|
7
|
-
lockss_pybasic-0.3.0.dev3.dist-info/METADATA,sha256=aTqzPE7mJFwwc8oZtYtZGdp4JVuEpBKHk-1K0Rn1BpU,2338
|
|
8
|
-
lockss_pybasic-0.3.0.dev3.dist-info/WHEEL,sha256=eY7nduwzv-ldUxpzbRlxwvC693Hg6PX8bWDjEHjZ_dk,88
|
|
9
|
-
lockss_pybasic-0.3.0.dev3.dist-info/licenses/LICENSE,sha256=EOxPunNz3XP6AjgbPFolu-d9BS_AF9TtKn1WXgeYPsE,1506
|
|
10
|
-
lockss_pybasic-0.3.0.dev3.dist-info/RECORD,,
|
|
File without changes
|
{lockss_pybasic-0.3.0.dev3.dist-info → lockss_pybasic-0.3.0.dev4.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|