meerschaum 2.9.5__py3-none-any.whl → 3.0.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.
- meerschaum/__init__.py +5 -2
- meerschaum/_internal/__init__.py +1 -0
- meerschaum/_internal/arguments/_parse_arguments.py +4 -4
- meerschaum/_internal/arguments/_parser.py +33 -4
- meerschaum/_internal/cli/__init__.py +6 -0
- meerschaum/_internal/cli/daemons.py +103 -0
- meerschaum/_internal/cli/entry.py +220 -0
- meerschaum/_internal/cli/workers.py +435 -0
- meerschaum/_internal/docs/index.py +48 -2
- meerschaum/_internal/entry.py +50 -14
- meerschaum/_internal/shell/Shell.py +121 -29
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +359 -0
- meerschaum/_internal/term/TermPageHandler.py +1 -2
- meerschaum/_internal/term/__init__.py +40 -6
- meerschaum/_internal/term/tools.py +33 -8
- meerschaum/actions/__init__.py +6 -4
- meerschaum/actions/api.py +53 -13
- meerschaum/actions/attach.py +1 -0
- meerschaum/actions/bootstrap.py +8 -8
- meerschaum/actions/delete.py +4 -2
- meerschaum/actions/edit.py +171 -25
- meerschaum/actions/login.py +8 -8
- meerschaum/actions/register.py +143 -6
- meerschaum/actions/reload.py +22 -5
- meerschaum/actions/restart.py +14 -0
- meerschaum/actions/show.py +184 -31
- meerschaum/actions/start.py +166 -17
- meerschaum/actions/stop.py +38 -2
- meerschaum/actions/sync.py +7 -2
- meerschaum/actions/tag.py +9 -8
- meerschaum/actions/verify.py +5 -8
- meerschaum/api/__init__.py +45 -15
- meerschaum/api/_events.py +46 -4
- meerschaum/api/_oauth2.py +162 -9
- meerschaum/api/_tokens.py +102 -0
- meerschaum/api/dash/__init__.py +0 -3
- meerschaum/api/dash/callbacks/__init__.py +1 -0
- meerschaum/api/dash/callbacks/custom.py +4 -3
- meerschaum/api/dash/callbacks/dashboard.py +198 -118
- meerschaum/api/dash/callbacks/jobs.py +14 -7
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/pipes.py +194 -14
- meerschaum/api/dash/callbacks/plugins.py +0 -1
- meerschaum/api/dash/callbacks/register.py +10 -3
- meerschaum/api/dash/callbacks/settings/password_reset.py +2 -2
- meerschaum/api/dash/callbacks/tokens.py +389 -0
- meerschaum/api/dash/components.py +36 -15
- meerschaum/api/dash/jobs.py +1 -1
- meerschaum/api/dash/keys.py +35 -93
- meerschaum/api/dash/pages/__init__.py +2 -1
- meerschaum/api/dash/pages/dashboard.py +1 -20
- meerschaum/api/dash/pages/{job.py → jobs.py} +10 -7
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pages/pipes.py +16 -5
- meerschaum/api/dash/pages/settings/password_reset.py +1 -1
- meerschaum/api/dash/pages/tokens.py +53 -0
- meerschaum/api/dash/pipes.py +382 -95
- meerschaum/api/dash/sessions.py +12 -0
- meerschaum/api/dash/tokens.py +603 -0
- meerschaum/api/dash/websockets.py +1 -1
- meerschaum/api/dash/webterm.py +18 -6
- meerschaum/api/models/__init__.py +23 -3
- meerschaum/api/models/_actions.py +22 -0
- meerschaum/api/models/_pipes.py +91 -7
- meerschaum/api/models/_tokens.py +81 -0
- meerschaum/api/resources/static/js/terminado.js +3 -0
- meerschaum/api/resources/static/js/xterm-addon-unicode11.js +2 -0
- meerschaum/api/resources/templates/termpage.html +13 -0
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +3 -4
- meerschaum/api/routes/_connectors.py +3 -7
- meerschaum/api/routes/_jobs.py +26 -35
- meerschaum/api/routes/_login.py +120 -15
- meerschaum/api/routes/_misc.py +5 -10
- meerschaum/api/routes/_pipes.py +178 -143
- meerschaum/api/routes/_plugins.py +38 -28
- meerschaum/api/routes/_tokens.py +236 -0
- meerschaum/api/routes/_users.py +47 -35
- meerschaum/api/routes/_version.py +3 -3
- meerschaum/api/routes/_webterm.py +3 -3
- meerschaum/config/__init__.py +100 -30
- meerschaum/config/_default.py +132 -64
- meerschaum/config/_edit.py +38 -32
- meerschaum/config/_formatting.py +2 -0
- meerschaum/config/_patch.py +10 -8
- meerschaum/config/_paths.py +133 -13
- meerschaum/config/_read_config.py +87 -36
- meerschaum/config/_sync.py +6 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/environment.py +262 -0
- meerschaum/config/stack/__init__.py +37 -15
- meerschaum/config/static.py +18 -0
- meerschaum/connectors/_Connector.py +11 -6
- meerschaum/connectors/__init__.py +41 -22
- meerschaum/connectors/api/_APIConnector.py +34 -6
- meerschaum/connectors/api/_actions.py +2 -2
- meerschaum/connectors/api/_jobs.py +12 -1
- meerschaum/connectors/api/_login.py +33 -7
- meerschaum/connectors/api/_misc.py +2 -2
- meerschaum/connectors/api/_pipes.py +23 -32
- meerschaum/connectors/api/_plugins.py +2 -2
- meerschaum/connectors/api/_request.py +1 -1
- meerschaum/connectors/api/_tokens.py +146 -0
- meerschaum/connectors/api/_users.py +70 -58
- meerschaum/connectors/instance/_InstanceConnector.py +83 -0
- meerschaum/connectors/instance/__init__.py +10 -0
- meerschaum/connectors/instance/_pipes.py +442 -0
- meerschaum/connectors/instance/_plugins.py +159 -0
- meerschaum/connectors/instance/_tokens.py +317 -0
- meerschaum/connectors/instance/_users.py +188 -0
- meerschaum/connectors/parse.py +5 -2
- meerschaum/connectors/sql/_SQLConnector.py +22 -5
- meerschaum/connectors/sql/_cli.py +12 -11
- meerschaum/connectors/sql/_create_engine.py +12 -168
- meerschaum/connectors/sql/_fetch.py +2 -18
- meerschaum/connectors/sql/_pipes.py +295 -278
- meerschaum/connectors/sql/_plugins.py +29 -0
- meerschaum/connectors/sql/_sql.py +46 -21
- meerschaum/connectors/sql/_users.py +36 -2
- meerschaum/connectors/sql/tables/__init__.py +254 -122
- meerschaum/connectors/valkey/_ValkeyConnector.py +5 -7
- meerschaum/connectors/valkey/_pipes.py +60 -31
- meerschaum/connectors/valkey/_plugins.py +2 -26
- meerschaum/core/Pipe/__init__.py +115 -85
- meerschaum/core/Pipe/_attributes.py +425 -124
- meerschaum/core/Pipe/_bootstrap.py +54 -24
- meerschaum/core/Pipe/_cache.py +555 -0
- meerschaum/core/Pipe/_clear.py +0 -11
- meerschaum/core/Pipe/_data.py +96 -68
- meerschaum/core/Pipe/_deduplicate.py +0 -13
- meerschaum/core/Pipe/_delete.py +12 -21
- meerschaum/core/Pipe/_drop.py +11 -23
- meerschaum/core/Pipe/_dtypes.py +49 -19
- meerschaum/core/Pipe/_edit.py +14 -4
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_index.py +8 -14
- meerschaum/core/Pipe/_show.py +5 -5
- meerschaum/core/Pipe/_sync.py +123 -204
- meerschaum/core/Pipe/_verify.py +4 -4
- meerschaum/{plugins → core/Plugin}/_Plugin.py +16 -12
- meerschaum/core/Plugin/__init__.py +1 -1
- meerschaum/core/Token/_Token.py +220 -0
- meerschaum/core/Token/__init__.py +12 -0
- meerschaum/core/User/_User.py +35 -10
- meerschaum/core/User/__init__.py +9 -1
- meerschaum/core/__init__.py +1 -0
- meerschaum/jobs/_Executor.py +88 -4
- meerschaum/jobs/_Job.py +149 -38
- meerschaum/jobs/__init__.py +3 -2
- meerschaum/jobs/systemd.py +8 -3
- meerschaum/models/__init__.py +35 -0
- meerschaum/models/pipes.py +247 -0
- meerschaum/models/tokens.py +38 -0
- meerschaum/models/users.py +26 -0
- meerschaum/plugins/__init__.py +301 -88
- meerschaum/plugins/bootstrap.py +510 -4
- meerschaum/utils/_get_pipes.py +97 -30
- meerschaum/utils/daemon/Daemon.py +199 -43
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +0 -1
- meerschaum/utils/daemon/RotatingFile.py +63 -36
- meerschaum/utils/daemon/StdinFile.py +53 -13
- meerschaum/utils/daemon/__init__.py +47 -6
- meerschaum/utils/daemon/_names.py +6 -3
- meerschaum/utils/dataframe.py +479 -81
- meerschaum/utils/debug.py +49 -19
- meerschaum/utils/dtypes/__init__.py +476 -34
- meerschaum/utils/dtypes/sql.py +369 -29
- meerschaum/utils/formatting/__init__.py +5 -2
- meerschaum/utils/formatting/_jobs.py +1 -1
- meerschaum/utils/formatting/_pipes.py +52 -50
- meerschaum/utils/formatting/_pprint.py +1 -0
- meerschaum/utils/formatting/_shell.py +44 -18
- meerschaum/utils/misc.py +268 -186
- meerschaum/utils/packages/__init__.py +25 -40
- meerschaum/utils/packages/_packages.py +42 -34
- meerschaum/utils/pipes.py +213 -0
- meerschaum/utils/process.py +2 -2
- meerschaum/utils/prompt.py +175 -144
- meerschaum/utils/schedule.py +2 -1
- meerschaum/utils/sql.py +134 -47
- meerschaum/utils/threading.py +42 -0
- meerschaum/utils/typing.py +1 -4
- meerschaum/utils/venv/_Venv.py +2 -2
- meerschaum/utils/venv/__init__.py +7 -7
- meerschaum/utils/warnings.py +19 -13
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/METADATA +94 -96
- meerschaum-3.0.0.dist-info/RECORD +289 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/WHEEL +1 -1
- meerschaum-3.0.0.dist-info/licenses/NOTICE +2 -0
- meerschaum/api/models/_interfaces.py +0 -15
- meerschaum/api/models/_locations.py +0 -15
- meerschaum/api/models/_metrics.py +0 -15
- meerschaum/config/_environment.py +0 -145
- meerschaum/config/static/__init__.py +0 -186
- meerschaum-2.9.5.dist-info/RECORD +0 -263
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/top_level.txt +0 -0
- {meerschaum-2.9.5.dist-info → meerschaum-3.0.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
#! /usr/bin/env python
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# vim:fenc=utf-8
|
4
|
+
|
5
|
+
"""
|
6
|
+
Pydantic model for a pipe's keys.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from __future__ import annotations
|
10
|
+
|
11
|
+
from typing import Optional, List, Tuple, Dict, Any
|
12
|
+
|
13
|
+
import meerschaum as mrsm
|
14
|
+
|
15
|
+
pydantic = mrsm.attempt_import('pydantic', lazy=False)
|
16
|
+
from pydantic import (
|
17
|
+
BaseModel,
|
18
|
+
RootModel,
|
19
|
+
field_validator,
|
20
|
+
ValidationInfo,
|
21
|
+
ConfigDict,
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
class ConnectorKeysModel(RootModel[str]):
|
26
|
+
"""
|
27
|
+
Validate the connector keys:
|
28
|
+
- May not begin with an underscore (_).
|
29
|
+
- Must be at least one character long.
|
30
|
+
- May contain one or zero colons (:).
|
31
|
+
"""
|
32
|
+
model_config = ConfigDict(
|
33
|
+
frozen=True,
|
34
|
+
json_schema_extra={
|
35
|
+
'example': 'sql:main',
|
36
|
+
},
|
37
|
+
)
|
38
|
+
@field_validator('root')
|
39
|
+
@classmethod
|
40
|
+
def validate_connector_keys(cls, v: str, info: ValidationInfo) -> str:
|
41
|
+
"""Validate the connector keys."""
|
42
|
+
if not v:
|
43
|
+
raise ValueError("Connector keys must be at least one character long.")
|
44
|
+
if v.startswith('_'):
|
45
|
+
raise ValueError("Connector keys may not begin with an underscore.")
|
46
|
+
if v.count(':') > 1:
|
47
|
+
raise ValueError("Connector keys may contain at most one colon.")
|
48
|
+
return v
|
49
|
+
|
50
|
+
|
51
|
+
class MetricKeyModel(RootModel[str]):
|
52
|
+
"""
|
53
|
+
Validate the metric key:
|
54
|
+
|
55
|
+
- May not begin with an underscore (_).
|
56
|
+
- Must be at least one character long.
|
57
|
+
"""
|
58
|
+
model_config = ConfigDict(
|
59
|
+
frozen=True,
|
60
|
+
json_schema_extra={
|
61
|
+
'example': 'weather',
|
62
|
+
},
|
63
|
+
)
|
64
|
+
@field_validator('root')
|
65
|
+
@classmethod
|
66
|
+
def validate_metric_key(cls, v: str, info: ValidationInfo) -> str:
|
67
|
+
"""Validate the metric key."""
|
68
|
+
if not v:
|
69
|
+
raise ValueError("Metric key must be at least one character long.")
|
70
|
+
if v.startswith('_'):
|
71
|
+
raise ValueError("Metric key may not begin with an underscore.")
|
72
|
+
return v
|
73
|
+
|
74
|
+
|
75
|
+
class LocationKeyModel(RootModel[Optional[str]]):
|
76
|
+
"""
|
77
|
+
Validate the location key:
|
78
|
+
|
79
|
+
- May not begin with an underscore (_).
|
80
|
+
- May be null (`None`).
|
81
|
+
- If not null, must be at least one character long.
|
82
|
+
"""
|
83
|
+
model_config = ConfigDict(
|
84
|
+
frozen=True,
|
85
|
+
json_schema_extra={
|
86
|
+
'example': 'us.co.denver',
|
87
|
+
},
|
88
|
+
)
|
89
|
+
@field_validator('root')
|
90
|
+
@classmethod
|
91
|
+
def validate_location_key(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]:
|
92
|
+
"""Validate the location key."""
|
93
|
+
if v is None:
|
94
|
+
return v
|
95
|
+
if not v:
|
96
|
+
raise ValueError("Location key must be at least one character long if not null.")
|
97
|
+
if v.startswith('_'):
|
98
|
+
raise ValueError("Location key may not begin with an underscore.")
|
99
|
+
return v
|
100
|
+
|
101
|
+
|
102
|
+
class InstanceKeysModel(RootModel[str]):
|
103
|
+
"""
|
104
|
+
Validate the instance keys. The instance keys are connector keys which must have one colon
|
105
|
+
(e.g. `'sql:main'`).
|
106
|
+
"""
|
107
|
+
model_config = ConfigDict(
|
108
|
+
frozen=True,
|
109
|
+
json_schema_extra={
|
110
|
+
'example': 'sql:main',
|
111
|
+
},
|
112
|
+
)
|
113
|
+
@field_validator('root')
|
114
|
+
@classmethod
|
115
|
+
def validate_instance_keys(cls, v: str, info: ValidationInfo) -> str:
|
116
|
+
"""Validate the instance keys."""
|
117
|
+
if not v:
|
118
|
+
raise ValueError("Instance keys must be at least one character long.")
|
119
|
+
if v.startswith('_'):
|
120
|
+
raise ValueError("Instance keys may not begin with an underscore.")
|
121
|
+
if v.count(':') != 1:
|
122
|
+
raise ValueError("Instance keys must contain exactly one colon.")
|
123
|
+
return v
|
124
|
+
|
125
|
+
|
126
|
+
class PipeModel(BaseModel):
|
127
|
+
"""
|
128
|
+
Define the four components to uniquely identify a pipe.
|
129
|
+
"""
|
130
|
+
connector_keys: ConnectorKeysModel
|
131
|
+
metric_key: MetricKeyModel
|
132
|
+
location_key: Optional[LocationKeyModel] = None
|
133
|
+
instance_keys: Optional[InstanceKeysModel] = None
|
134
|
+
model_config = ConfigDict(
|
135
|
+
json_schema_extra={
|
136
|
+
'example': {
|
137
|
+
'connector_keys': 'sql:main',
|
138
|
+
'metric_key': 'weather',
|
139
|
+
'location_key': 'atl',
|
140
|
+
'instance_keys': 'sql:main',
|
141
|
+
},
|
142
|
+
},
|
143
|
+
)
|
144
|
+
|
145
|
+
|
146
|
+
class PipeWithParametersModel(PipeModel):
|
147
|
+
"""
|
148
|
+
A Pipe's model including its parameters dictionary.
|
149
|
+
"""
|
150
|
+
parameters: Dict[str, Any]
|
151
|
+
model_config = ConfigDict(
|
152
|
+
json_schema_extra={
|
153
|
+
'example': {
|
154
|
+
'connector_keys': 'sql:main',
|
155
|
+
'metric_key': 'weather',
|
156
|
+
'location_key': 'atl',
|
157
|
+
'instance_keys': 'sql:main',
|
158
|
+
'parameters': {
|
159
|
+
'columns': {
|
160
|
+
'datetime': 'dt',
|
161
|
+
'id': 'id',
|
162
|
+
},
|
163
|
+
},
|
164
|
+
},
|
165
|
+
},
|
166
|
+
)
|
167
|
+
|
168
|
+
class PipesWithParametersDictModel(
|
169
|
+
RootModel[
|
170
|
+
Dict[
|
171
|
+
str,
|
172
|
+
Dict[
|
173
|
+
str,
|
174
|
+
Dict[
|
175
|
+
str,
|
176
|
+
PipeWithParametersModel
|
177
|
+
]
|
178
|
+
]
|
179
|
+
]
|
180
|
+
]
|
181
|
+
):
|
182
|
+
"""
|
183
|
+
A dictionary of pipes' parameters, nested by connector, metric, and location keys.
|
184
|
+
"""
|
185
|
+
@field_validator('root')
|
186
|
+
@classmethod
|
187
|
+
def validate_keys(cls, v: dict, info: ValidationInfo) -> dict:
|
188
|
+
"""
|
189
|
+
Validate the dictionary keys.
|
190
|
+
"""
|
191
|
+
for c_key, metrics in v.items():
|
192
|
+
ConnectorKeysModel(root=c_key)
|
193
|
+
for m_key, locations in metrics.items():
|
194
|
+
MetricKeyModel(root=m_key)
|
195
|
+
for l_key in locations:
|
196
|
+
LocationKeyModel(root=l_key if l_key not in ('None', 'null', '[None]') else None)
|
197
|
+
return v
|
198
|
+
|
199
|
+
model_config = ConfigDict(
|
200
|
+
json_schema_extra={
|
201
|
+
'example': {
|
202
|
+
"plugin:noaa": {
|
203
|
+
"weather": {
|
204
|
+
"None": {
|
205
|
+
"pipe_id": 1,
|
206
|
+
"connector_keys": "plugin:noaa",
|
207
|
+
"metric_key": "weather",
|
208
|
+
"location_key": "clemson",
|
209
|
+
"parameters": {
|
210
|
+
"columns": {
|
211
|
+
"datetime": "timestamp",
|
212
|
+
"id": "station"
|
213
|
+
},
|
214
|
+
"noaa": {
|
215
|
+
"stations": {
|
216
|
+
"KCEU": {
|
217
|
+
"name": "Clemson, Clemson-Oconee County Airport",
|
218
|
+
"geometry": {
|
219
|
+
"type": "Point",
|
220
|
+
"coordinates": [
|
221
|
+
-82.88139,
|
222
|
+
34.67222
|
223
|
+
]
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
},
|
228
|
+
"verify": {
|
229
|
+
"chunk_minutes": 20160
|
230
|
+
},
|
231
|
+
"target": "plugin_noaa_weather",
|
232
|
+
"tags": [],
|
233
|
+
"dtypes": {
|
234
|
+
"timestamp": "datetime",
|
235
|
+
"geometry": "json",
|
236
|
+
"cloudLayers": "json",
|
237
|
+
"presentWeather": "json"
|
238
|
+
},
|
239
|
+
"static": False,
|
240
|
+
"enforce": True
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
}
|
245
|
+
},
|
246
|
+
},
|
247
|
+
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define Pydantic models for tokens.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import uuid
|
9
|
+
from typing import Optional, List, Union
|
10
|
+
from datetime import datetime
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
13
|
+
|
14
|
+
pydantic = mrsm.attempt_import('pydantic', lazy=False)
|
15
|
+
from pydantic import (
|
16
|
+
BaseModel,
|
17
|
+
RootModel,
|
18
|
+
field_validator,
|
19
|
+
ValidationInfo,
|
20
|
+
ConfigDict,
|
21
|
+
Field,
|
22
|
+
)
|
23
|
+
from meerschaum.models.users import UserModel
|
24
|
+
from meerschaum._internal.static import STATIC_CONFIG
|
25
|
+
|
26
|
+
|
27
|
+
class TokenModel(BaseModel):
|
28
|
+
"""Pydantic model for a Meerschaum token."""
|
29
|
+
model_config = ConfigDict(from_attributes=True)
|
30
|
+
|
31
|
+
id: Optional[uuid.UUID] = Field(default=None)
|
32
|
+
creation: Optional[datetime] = Field(default=None)
|
33
|
+
expiration: Optional[datetime] = Field(default=None)
|
34
|
+
label: Optional[str] = Field(default=None)
|
35
|
+
user_id: Optional[Union[int, uuid.UUID]] = Field(default=None)
|
36
|
+
secret_hash: Optional[str] = Field(default=None)
|
37
|
+
scopes: Optional[List[str]] = Field(default=list(STATIC_CONFIG['tokens']['scopes']))
|
38
|
+
is_valid: bool = Field(default=True)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#! /usr/bin/env python3
|
2
|
+
# vim:fenc=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
Define Pydantic models for users.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from __future__ import annotations
|
9
|
+
from typing import Optional, Dict, Any, Union
|
10
|
+
import uuid
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
13
|
+
|
14
|
+
pydantic = mrsm.attempt_import('pydantic', lazy=False)
|
15
|
+
from pydantic import BaseModel, Field, ConfigDict
|
16
|
+
|
17
|
+
|
18
|
+
class UserModel(BaseModel):
|
19
|
+
"""Pydantic model for a Meerschaum User."""
|
20
|
+
model_config = ConfigDict(from_attributes=True)
|
21
|
+
|
22
|
+
user_id: Optional[Union[int, uuid.UUID]] = Field(default=None)
|
23
|
+
username: str
|
24
|
+
email: Optional[str] = Field(default=None)
|
25
|
+
type: Optional[str] = Field(default=None)
|
26
|
+
attributes: Optional[Dict[str, Any]] = Field(default=None)
|