reyserver 1.1.46__py3-none-any.whl → 1.1.47__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.
- reyserver/__init__.py +1 -0
- reyserver/rall.py +1 -0
- reyserver/rauth.py +11 -0
- reyserver/rbase.py +134 -64
- reyserver/rclient.py +89 -6
- reyserver/rfile.py +45 -25
- reyserver/rserver.py +98 -15
- {reyserver-1.1.46.dist-info → reyserver-1.1.47.dist-info}/METADATA +2 -1
- reyserver-1.1.47.dist-info/RECORD +11 -0
- reyserver-1.1.46.dist-info/RECORD +0 -10
- {reyserver-1.1.46.dist-info → reyserver-1.1.47.dist-info}/WHEEL +0 -0
- {reyserver-1.1.46.dist-info → reyserver-1.1.47.dist-info}/licenses/LICENSE +0 -0
reyserver/__init__.py
CHANGED
reyserver/rall.py
CHANGED
reyserver/rauth.py
ADDED
reyserver/rbase.py
CHANGED
@@ -11,9 +11,22 @@
|
|
11
11
|
|
12
12
|
from typing import Sequence, Literal
|
13
13
|
from inspect import iscoroutinefunction
|
14
|
-
from contextlib import asynccontextmanager
|
15
|
-
from fastapi import FastAPI, HTTPException, status
|
16
|
-
from
|
14
|
+
from contextlib import asynccontextmanager, _AsyncGeneratorContextManager
|
15
|
+
from fastapi import FastAPI, HTTPException, status, UploadFile as File
|
16
|
+
from fastapi.params import (
|
17
|
+
Depends,
|
18
|
+
Path,
|
19
|
+
Query,
|
20
|
+
Header,
|
21
|
+
Cookie,
|
22
|
+
Body,
|
23
|
+
Form,
|
24
|
+
File as Forms
|
25
|
+
)
|
26
|
+
from reydb.rconn import DatabaseConnectionAsync
|
27
|
+
from reydb.rorm import DatabaseORMModel, DatabaseORMSessionAsync
|
28
|
+
from reykit.rwrap import wrap_cache
|
29
|
+
from reykit.rbase import CoroutineFunctionSimple, Base, Exit, StaticMeta, ConfigMeta
|
17
30
|
|
18
31
|
from . import rserver
|
19
32
|
|
@@ -79,85 +92,142 @@ class ServerExitHTTP404(ServerExitHTTP):
|
|
79
92
|
status_code = status.HTTP_404_NOT_FOUND
|
80
93
|
|
81
94
|
|
82
|
-
|
83
|
-
before: CoroutineFunctionSimple | Sequence[CoroutineFunctionSimple] | None = None,
|
84
|
-
after: CoroutineFunctionSimple | Sequence[CoroutineFunctionSimple] | None = None,
|
85
|
-
):
|
95
|
+
class ServerBind(ServerBase, metaclass=StaticMeta):
|
86
96
|
"""
|
87
|
-
|
88
|
-
|
89
|
-
Parameters
|
90
|
-
----------
|
91
|
-
before : Execute before server start.
|
92
|
-
after : Execute after server end.
|
97
|
+
Server API bind parameter type.
|
93
98
|
"""
|
94
99
|
|
95
|
-
# Parameter.
|
96
|
-
if before is None:
|
97
|
-
before = ()
|
98
|
-
elif iscoroutinefunction(before):
|
99
|
-
before = (before,)
|
100
|
-
if after is None:
|
101
|
-
after = ()
|
102
|
-
elif iscoroutinefunction(after):
|
103
|
-
after = (after,)
|
104
100
|
|
105
|
-
|
106
|
-
|
107
|
-
|
101
|
+
def create_lifespan(
|
102
|
+
before: CoroutineFunctionSimple | Sequence[CoroutineFunctionSimple] | None = None,
|
103
|
+
after: CoroutineFunctionSimple | Sequence[CoroutineFunctionSimple] | None = None,
|
104
|
+
) -> _AsyncGeneratorContextManager[None, None]:
|
108
105
|
"""
|
109
|
-
|
106
|
+
Create asynchronous function of lifespan manager.
|
110
107
|
|
111
108
|
Parameters
|
112
109
|
----------
|
113
|
-
|
110
|
+
before : Execute before server start.
|
111
|
+
after : Execute after server end.
|
112
|
+
|
113
|
+
Returns
|
114
|
+
-------
|
115
|
+
Asynchronous function.
|
114
116
|
"""
|
115
117
|
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
# Parameter.
|
119
|
+
if before is None:
|
120
|
+
before = ()
|
121
|
+
elif iscoroutinefunction(before):
|
122
|
+
before = (before,)
|
123
|
+
if after is None:
|
124
|
+
after = ()
|
125
|
+
elif iscoroutinefunction(after):
|
126
|
+
after = (after,)
|
120
127
|
|
121
|
-
# After.
|
122
|
-
for task in after:
|
123
|
-
await after()
|
124
128
|
|
129
|
+
@asynccontextmanager
|
130
|
+
async def lifespan(app: FastAPI):
|
131
|
+
"""
|
132
|
+
Server lifespan manager.
|
125
133
|
|
126
|
-
|
134
|
+
Parameters
|
135
|
+
----------
|
136
|
+
app : Server APP.
|
137
|
+
"""
|
127
138
|
|
139
|
+
# Before.
|
140
|
+
for task in before:
|
141
|
+
await task()
|
142
|
+
yield
|
128
143
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
Parameters
|
134
|
-
----------
|
135
|
-
database : Database name.
|
136
|
-
mode : Mode.
|
137
|
-
- `Literl['sess']`: Create ORM session instance.
|
138
|
-
- `Literl['conn']`: Create connection instance.
|
139
|
-
|
140
|
-
Returns
|
141
|
-
-------
|
142
|
-
Dependencie function.
|
143
|
-
"""
|
144
|
+
# After.
|
145
|
+
for task in after:
|
146
|
+
await after()
|
144
147
|
|
145
148
|
|
146
|
-
|
147
|
-
"""
|
148
|
-
Dependencie function of asynchronous database.
|
149
|
-
"""
|
149
|
+
return lifespan
|
150
150
|
|
151
|
-
# Parameter.
|
152
|
-
engine = ServerConfig.server.db[database]
|
153
151
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
152
|
+
@wrap_cache
|
153
|
+
def create_depend_db(database: str, mode: Literal['sess', 'conn']) -> Depends:
|
154
|
+
"""
|
155
|
+
Create dependencie type of asynchronous database.
|
156
|
+
|
157
|
+
Parameters
|
158
|
+
----------
|
159
|
+
database : Database name.
|
160
|
+
mode : Mode.
|
161
|
+
- `Literl['sess']`: Create ORM session instance.
|
162
|
+
- `Literl['conn']`: Create connection instance.
|
163
|
+
|
164
|
+
Returns
|
165
|
+
-------
|
166
|
+
Dependencie type.
|
167
|
+
"""
|
161
168
|
|
162
169
|
|
163
|
-
|
170
|
+
async def depend_db():
|
171
|
+
"""
|
172
|
+
Dependencie function of asynchronous database.
|
173
|
+
"""
|
174
|
+
|
175
|
+
# Parameter.
|
176
|
+
engine = ServerConfig.server.db[database]
|
177
|
+
|
178
|
+
# Context.
|
179
|
+
if mode == 'sess':
|
180
|
+
async with engine.orm.session() as sess:
|
181
|
+
yield sess
|
182
|
+
elif mode == 'conn':
|
183
|
+
async with engine.connect() as conn:
|
184
|
+
yield conn
|
185
|
+
|
186
|
+
|
187
|
+
# Create.
|
188
|
+
depend = Depends(depend_db)
|
189
|
+
|
190
|
+
return depend
|
191
|
+
|
192
|
+
|
193
|
+
Depend = Depends
|
194
|
+
Path = Path
|
195
|
+
Query = Query
|
196
|
+
Header = Header
|
197
|
+
Cookie = Cookie
|
198
|
+
Body = Body
|
199
|
+
Form = Form
|
200
|
+
Forms = Forms
|
201
|
+
File = File
|
202
|
+
JSON = DatabaseORMModel
|
203
|
+
Conn = DatabaseConnectionAsync
|
204
|
+
Sess = DatabaseORMSessionAsync
|
205
|
+
path = Path()
|
206
|
+
'Path instance.'
|
207
|
+
query = Query()
|
208
|
+
'Query instance.'
|
209
|
+
header = Header()
|
210
|
+
'Header instance.'
|
211
|
+
cookie = Cookie()
|
212
|
+
'Cookie instance.'
|
213
|
+
body = Body()
|
214
|
+
'Body instance.'
|
215
|
+
form = Form()
|
216
|
+
'Form instance.'
|
217
|
+
forms = Forms()
|
218
|
+
'Forms instance.'
|
219
|
+
query_n = Query(None)
|
220
|
+
'Query instance, default `None`.'
|
221
|
+
header_n = Header(None)
|
222
|
+
'Header instance, default `None`.'
|
223
|
+
cookie_n = Cookie(None)
|
224
|
+
'Cookie instance, default `None`.'
|
225
|
+
body_n = Body(None)
|
226
|
+
'Body instance, default `None`.'
|
227
|
+
form_n = Form(None)
|
228
|
+
'Form instance, default `None`.'
|
229
|
+
forms_n = Forms(None)
|
230
|
+
'Forms instance, default `None`.'
|
231
|
+
|
232
|
+
|
233
|
+
Bind = ServerBind
|
reyserver/rclient.py
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
|
12
|
-
from
|
13
|
-
from
|
12
|
+
from typing import TypedDict
|
13
|
+
from datetime import datetime as Datetime
|
14
|
+
from reykit.ros import File, Folder, overload
|
15
|
+
from reykit.rnet import join_url, request, get_response_file_name
|
14
16
|
|
15
17
|
from .rbase import ServerBase
|
16
18
|
|
@@ -20,6 +22,9 @@ __all__ = (
|
|
20
22
|
)
|
21
23
|
|
22
24
|
|
25
|
+
FileInfo = TypedDict('FileInfo', {'create_time': Datetime, 'md5': str, 'name': str | None, 'size': int, 'note': str | None})
|
26
|
+
|
27
|
+
|
23
28
|
class ServerClient(ServerBase):
|
24
29
|
"""
|
25
30
|
Server client type.
|
@@ -64,7 +69,7 @@ class ServerClient(ServerBase):
|
|
64
69
|
"""
|
65
70
|
|
66
71
|
# Handle parameter.
|
67
|
-
url = join_url(self.url, '
|
72
|
+
url = join_url(self.url, 'files')
|
68
73
|
match source:
|
69
74
|
|
70
75
|
## File path.
|
@@ -84,7 +89,7 @@ class ServerClient(ServerBase):
|
|
84
89
|
if name is not None:
|
85
90
|
file_name = name
|
86
91
|
|
87
|
-
#
|
92
|
+
# Request.
|
88
93
|
data = {'name': file_name, 'note': note}
|
89
94
|
files = {'file': file_bytes}
|
90
95
|
response = request(url, data=data, files=files, check=True)
|
@@ -96,7 +101,85 @@ class ServerClient(ServerBase):
|
|
96
101
|
return file_id
|
97
102
|
|
98
103
|
|
99
|
-
|
104
|
+
@overload
|
105
|
+
def download_file(
|
106
|
+
self,
|
107
|
+
file_id: int,
|
108
|
+
path: None = None
|
109
|
+
) -> bytes: ...
|
110
|
+
|
111
|
+
@overload
|
112
|
+
def download_file(
|
113
|
+
self,
|
114
|
+
file_id: int,
|
115
|
+
path: str
|
116
|
+
) -> str: ...
|
117
|
+
|
118
|
+
def download_file(
|
119
|
+
self,
|
120
|
+
file_id: int,
|
121
|
+
path: str | None = None
|
122
|
+
) -> bytes | str:
|
123
|
+
"""
|
124
|
+
Download file.
|
125
|
+
|
126
|
+
Parameters
|
127
|
+
----------
|
128
|
+
file_id : File ID.
|
129
|
+
path : File save path.
|
130
|
+
- `None`: Not save and return file bytes.
|
131
|
+
- `str`: Save and return file path.
|
132
|
+
`File path`: Use this file path.
|
133
|
+
`Folder path`: Use this folder path and original name.
|
134
|
+
|
135
|
+
Returns
|
136
|
+
-------
|
137
|
+
File bytes or file path.
|
138
|
+
"""
|
139
|
+
|
140
|
+
# Parameter.
|
141
|
+
url = join_url(self.url, 'files', file_id, 'download')
|
142
|
+
|
143
|
+
# Request.
|
144
|
+
response = request(url, check=True)
|
145
|
+
file_bytes = response.content
|
146
|
+
|
147
|
+
# Not save.
|
148
|
+
if path is None:
|
149
|
+
return file_bytes
|
150
|
+
|
151
|
+
# Save.
|
152
|
+
else:
|
153
|
+
folder = Folder(path)
|
154
|
+
if folder:
|
155
|
+
file_name = get_response_file_name(response)
|
156
|
+
path = folder + file_name
|
157
|
+
file = File(path)
|
158
|
+
file(file_bytes)
|
159
|
+
return file.path
|
160
|
+
|
161
|
+
|
162
|
+
def get_file_info(
|
163
|
+
self,
|
164
|
+
file_id: int
|
165
|
+
) -> FileInfo:
|
166
|
+
"""
|
167
|
+
Query file information.
|
168
|
+
|
169
|
+
Parameters
|
170
|
+
----------
|
171
|
+
file_id : File ID.
|
172
|
+
|
173
|
+
Returns
|
174
|
+
-------
|
175
|
+
File information.
|
176
|
+
"""
|
177
|
+
|
178
|
+
# Parameter.
|
179
|
+
url = join_url(self.url, 'files', file_id)
|
100
180
|
|
181
|
+
# Request.
|
182
|
+
response = request(url, check=True)
|
183
|
+
response_dict = response.json()
|
101
184
|
|
102
|
-
|
185
|
+
return response_dict
|
reyserver/rfile.py
CHANGED
@@ -9,21 +9,14 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
|
12
|
-
from fastapi import
|
13
|
-
APIRouter,
|
14
|
-
Depends,
|
15
|
-
Path,
|
16
|
-
Form,
|
17
|
-
File,
|
18
|
-
UploadFile
|
19
|
-
)
|
12
|
+
from fastapi import APIRouter
|
20
13
|
from fastapi.responses import FileResponse
|
21
14
|
from reydb import rorm
|
22
15
|
from reydb.rorm import DatabaseORMSessionAsync
|
23
16
|
from reydb.rconn import DatabaseConnectionAsync
|
24
17
|
from reykit.ros import FileStore, get_md5
|
25
18
|
|
26
|
-
from .rbase import ServerConfig, ServerExitHTTP404,
|
19
|
+
from .rbase import ServerConfig, ServerExitHTTP404, Bind
|
27
20
|
|
28
21
|
|
29
22
|
__all__ = (
|
@@ -184,24 +177,29 @@ def build_file_db() -> None:
|
|
184
177
|
|
185
178
|
|
186
179
|
file_router = APIRouter()
|
187
|
-
depend_file_sess = create_depend_db('file', 'sess')
|
188
|
-
depend_file_conn = create_depend_db('file', 'conn')
|
180
|
+
depend_file_sess = Bind.create_depend_db('file', 'sess')
|
181
|
+
depend_file_conn = Bind.create_depend_db('file', 'conn')
|
189
182
|
|
190
183
|
|
191
184
|
@file_router.post('/')
|
192
185
|
async def upload_file(
|
193
|
-
file:
|
194
|
-
name: str =
|
195
|
-
note: str =
|
196
|
-
sess:
|
197
|
-
) ->
|
186
|
+
file: Bind.File = Bind.forms,
|
187
|
+
name: str = Bind.forms_n,
|
188
|
+
note: str = Bind.forms_n,
|
189
|
+
sess: Bind.Sess = depend_file_sess
|
190
|
+
) -> DatabaseORMTableInfo:
|
198
191
|
"""
|
199
192
|
Upload file.
|
200
193
|
|
201
194
|
Parameters
|
202
195
|
----------
|
203
196
|
file : File instance.
|
197
|
+
name : File name.
|
204
198
|
note : File note.
|
199
|
+
|
200
|
+
Returns
|
201
|
+
-------
|
202
|
+
File information.
|
205
203
|
"""
|
206
204
|
|
207
205
|
# Handle parameter.
|
@@ -233,15 +231,14 @@ async def upload_file(
|
|
233
231
|
|
234
232
|
# Get ID.
|
235
233
|
await sess.flush()
|
236
|
-
file_id = table_info.file_id
|
237
234
|
|
238
|
-
return
|
235
|
+
return table_info
|
239
236
|
|
240
237
|
|
241
238
|
@file_router.get('/{file_id}/download')
|
242
239
|
async def download_file(
|
243
|
-
file_id: int =
|
244
|
-
conn:
|
240
|
+
file_id: int = Bind.path,
|
241
|
+
conn: Bind.Conn = depend_file_conn
|
245
242
|
) -> FileResponse:
|
246
243
|
"""
|
247
244
|
Download file.
|
@@ -249,6 +246,10 @@ async def download_file(
|
|
249
246
|
Parameters
|
250
247
|
----------
|
251
248
|
file_id : File ID.
|
249
|
+
|
250
|
+
Returns
|
251
|
+
-------
|
252
|
+
File data.
|
252
253
|
"""
|
253
254
|
|
254
255
|
# Search.
|
@@ -267,8 +268,7 @@ async def download_file(
|
|
267
268
|
|
268
269
|
# Check.
|
269
270
|
if result.empty:
|
270
|
-
|
271
|
-
raise ServerExitHTTP404(text)
|
271
|
+
raise ServerExitHTTP404("file ID '%s' not exist" % file_id)
|
272
272
|
file_name, file_path = result.first()
|
273
273
|
|
274
274
|
# Response.
|
@@ -279,6 +279,26 @@ async def download_file(
|
|
279
279
|
|
280
280
|
@file_router.get('/{file_id}')
|
281
281
|
async def get_file_info(
|
282
|
-
file_id: int =
|
283
|
-
sess:
|
284
|
-
) ->
|
282
|
+
file_id: int = Bind.path,
|
283
|
+
sess: Bind.Sess = depend_file_sess
|
284
|
+
) -> DatabaseORMTableInfo:
|
285
|
+
"""
|
286
|
+
Get file information.
|
287
|
+
|
288
|
+
Parameters
|
289
|
+
----------
|
290
|
+
file_id : File ID.
|
291
|
+
|
292
|
+
Returns
|
293
|
+
-------
|
294
|
+
File information.
|
295
|
+
"""
|
296
|
+
|
297
|
+
# Get.
|
298
|
+
table_info = await sess.get(DatabaseORMTableInfo, file_id)
|
299
|
+
|
300
|
+
# Check.
|
301
|
+
if table_info is None:
|
302
|
+
raise ServerExitHTTP404("file ID '%s' not exist" % file_id)
|
303
|
+
|
304
|
+
return table_info
|
reyserver/rserver.py
CHANGED
@@ -9,15 +9,19 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
|
12
|
-
from
|
12
|
+
from typing import Literal
|
13
|
+
from collections.abc import Sequence, Callable, Coroutine
|
13
14
|
from inspect import iscoroutinefunction
|
14
15
|
from uvicorn import run as uvicorn_run
|
15
|
-
from
|
16
|
+
from starlette.middleware.base import _StreamingResponse
|
17
|
+
from fastapi import FastAPI, Request
|
16
18
|
from fastapi.staticfiles import StaticFiles
|
19
|
+
from fastapi.middleware.gzip import GZipMiddleware
|
20
|
+
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
|
17
21
|
from reydb import DatabaseAsync
|
18
|
-
from reykit.rbase import CoroutineFunctionSimple, Singleton, throw
|
22
|
+
from reykit.rbase import CallableT, CoroutineFunctionSimple, Singleton, throw
|
19
23
|
|
20
|
-
from .rbase import ServerBase, ServerConfig,
|
24
|
+
from .rbase import ServerBase, ServerConfig, Bind
|
21
25
|
|
22
26
|
|
23
27
|
__all__ = (
|
@@ -42,31 +46,33 @@ class Server(ServerBase, Singleton):
|
|
42
46
|
after: CoroutineFunctionSimple | Sequence[CoroutineFunctionSimple] | None = None,
|
43
47
|
ssl_cert: str | None = None,
|
44
48
|
ssl_key: str | None = None,
|
49
|
+
debug: bool = False
|
45
50
|
) -> None:
|
46
51
|
"""
|
47
52
|
Build instance attributes.
|
48
53
|
|
49
54
|
Parameters
|
50
55
|
----------
|
51
|
-
db : Asynchronous database.
|
56
|
+
db : Asynchronous database, must include database engines with APIs.
|
52
57
|
public : Public directory.
|
53
58
|
depend : Global api dependencies.
|
54
59
|
before : Execute before server start.
|
55
60
|
after : Execute after server end.
|
56
61
|
ssl_cert : SSL certificate file path.
|
57
62
|
ssl_key : SSL key file path.
|
63
|
+
debug : Whether use development mode debug server.
|
58
64
|
"""
|
59
65
|
|
60
66
|
# Parameter.
|
61
67
|
if type(ssl_cert) != type(ssl_key):
|
62
68
|
throw(AssertionError, ssl_cert, ssl_key)
|
63
|
-
lifespan = create_lifespan(before, after)
|
69
|
+
lifespan = Bind.create_lifespan(before, after)
|
64
70
|
if depend is None:
|
65
71
|
depend = ()
|
66
72
|
elif iscoroutinefunction(depend):
|
67
73
|
depend = (depend,)
|
68
74
|
depend = [
|
69
|
-
|
75
|
+
Bind.Depend(task)
|
70
76
|
for task in depend
|
71
77
|
]
|
72
78
|
|
@@ -80,18 +86,57 @@ class Server(ServerBase, Singleton):
|
|
80
86
|
self.app = FastAPI(
|
81
87
|
dependencies=depend,
|
82
88
|
lifespan=lifespan,
|
83
|
-
debug=
|
89
|
+
debug=debug
|
84
90
|
)
|
85
91
|
|
86
|
-
## Static.
|
87
92
|
if public is not None:
|
88
93
|
subapp = StaticFiles(directory=public, html=True)
|
89
94
|
self.app.mount('/', subapp)
|
95
|
+
self.wrap_middleware = self.app.middleware('http')
|
96
|
+
'Decorator, add middleware to APP.'
|
90
97
|
|
91
|
-
|
98
|
+
# Middleware
|
99
|
+
self.app.add_middleware(GZipMiddleware)
|
100
|
+
if not debug:
|
101
|
+
self.app.add_middleware(HTTPSRedirectMiddleware)
|
102
|
+
self.__add_default_middleware()
|
92
103
|
|
93
|
-
|
104
|
+
# API.
|
94
105
|
self.api_file_dir: str
|
106
|
+
'File API store directory path.'
|
107
|
+
|
108
|
+
|
109
|
+
def __add_default_middleware(self) -> None:
|
110
|
+
"""
|
111
|
+
Add default handle middleware.
|
112
|
+
"""
|
113
|
+
|
114
|
+
# Add.
|
115
|
+
@self.wrap_middleware
|
116
|
+
async def foo(
|
117
|
+
request: Request,
|
118
|
+
call_next: Callable[[Request], Coroutine[None, None, _StreamingResponse]]
|
119
|
+
) -> _StreamingResponse:
|
120
|
+
"""
|
121
|
+
Default handle middleware.
|
122
|
+
|
123
|
+
Parameters
|
124
|
+
----------
|
125
|
+
Reqeust : Request instance.
|
126
|
+
call_next : Next middleware.
|
127
|
+
"""
|
128
|
+
|
129
|
+
# Before.
|
130
|
+
...
|
131
|
+
|
132
|
+
# Next.
|
133
|
+
response = await call_next(request)
|
134
|
+
|
135
|
+
# After.
|
136
|
+
if request.method == 'POST':
|
137
|
+
response.status_code = 201
|
138
|
+
|
139
|
+
return response
|
95
140
|
|
96
141
|
|
97
142
|
def run(self) -> None:
|
@@ -107,16 +152,54 @@ class Server(ServerBase, Singleton):
|
|
107
152
|
)
|
108
153
|
|
109
154
|
|
110
|
-
def
|
155
|
+
def set_doc(
|
156
|
+
self,
|
157
|
+
version: str | None = None,
|
158
|
+
title: str | None = None,
|
159
|
+
summary: str | None = None,
|
160
|
+
desc: str | None = None,
|
161
|
+
contact: dict[Literal['name', 'email', 'url'], str] | None = None
|
162
|
+
) -> None:
|
163
|
+
"""
|
164
|
+
Set server document.
|
165
|
+
|
166
|
+
Parameters
|
167
|
+
----------
|
168
|
+
version : Server version.
|
169
|
+
title : Server title.
|
170
|
+
summary : Server summary.
|
171
|
+
desc : Server description.
|
172
|
+
contact : Server contact information.
|
173
|
+
"""
|
174
|
+
|
175
|
+
# Parameter.
|
176
|
+
set_dict = {
|
177
|
+
'version': version,
|
178
|
+
'title': title,
|
179
|
+
'summary': summary,
|
180
|
+
'description': desc,
|
181
|
+
'contact': contact
|
182
|
+
}
|
183
|
+
|
184
|
+
# Set.
|
185
|
+
for key, value in set_dict.items():
|
186
|
+
if value is not None:
|
187
|
+
setattr(self.app, key, value)
|
188
|
+
|
189
|
+
|
190
|
+
def add_api_auth(self):
|
191
|
+
"""
|
192
|
+
Add Authentication API.
|
193
|
+
Note: must include database engine of `auth` name.
|
194
|
+
"""
|
111
195
|
|
112
|
-
|
113
|
-
async def test():
|
114
|
-
return {'message': 'test'}
|
196
|
+
...
|
115
197
|
|
116
198
|
|
117
199
|
def add_api_file(self, file_dir: str = 'file') -> None:
|
118
200
|
"""
|
119
201
|
Add file API.
|
202
|
+
Note: must include database engine of `file` name.
|
120
203
|
|
121
204
|
Parameters
|
122
205
|
----------
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: reyserver
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.47
|
4
4
|
Summary: Backend server method set.
|
5
5
|
Project-URL: homepage, https://github.com/reyxbo/reyserver/
|
6
6
|
Author-email: Rey <reyxbo@163.com>
|
@@ -14,6 +14,7 @@ License: Copyright 2025 ReyXBo
|
|
14
14
|
License-File: LICENSE
|
15
15
|
Keywords: API,async,asynchronous,backend,rey,reyxbo,server
|
16
16
|
Requires-Python: >=3.12
|
17
|
+
Requires-Dist: email-validator
|
17
18
|
Requires-Dist: fastapi
|
18
19
|
Requires-Dist: python-multipart
|
19
20
|
Requires-Dist: reydb
|
@@ -0,0 +1,11 @@
|
|
1
|
+
reyserver/__init__.py,sha256=7GX64p7uI2eetJH9NJ-DTg-8iyQwOsGcviADFJCPxVA,373
|
2
|
+
reyserver/rall.py,sha256=riyDRTUsigco_Bee1H4aZFb8IgvjnxdX9qcnVb9i9mE,270
|
3
|
+
reyserver/rauth.py,sha256=QyY4gZ0ulpH9Kxvux_jnZBhzfWZZEuOWB1oYU9uzCnY,167
|
4
|
+
reyserver/rbase.py,sha256=nJ0x4hm_YZN210quppSFu_6mRNKDLLNyS27jzSc0Yg8,5220
|
5
|
+
reyserver/rclient.py,sha256=pTJtn78jPKgFo5EoQwZRdM0cYHdCs7QUKqfl-jUBRgk,4220
|
6
|
+
reyserver/rfile.py,sha256=5ynG0LlJLdvNiuFBBBuZhT-0jf_1LxEzac55Q40bsk8,9086
|
7
|
+
reyserver/rserver.py,sha256=hqpemzJHO6xHy_7pO3cvvjnfy8Yfqy8HfyIq4sjk4Dc,5889
|
8
|
+
reyserver-1.1.47.dist-info/METADATA,sha256=gav3pRrTdUZXsbSxo-3JkNjlzhzhasdolU8iywyKQmc,1689
|
9
|
+
reyserver-1.1.47.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
10
|
+
reyserver-1.1.47.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
|
11
|
+
reyserver-1.1.47.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
reyserver/__init__.py,sha256=JmDkcdP7oxmehE53rRRL_zhxmPinAbJRONpQp5qhsGI,340
|
2
|
-
reyserver/rall.py,sha256=6vqacf9erEfVfK5sgGJMDXD1h4ebt5gDN7NrPdtELms,248
|
3
|
-
reyserver/rbase.py,sha256=6mfTSuVzJGTK6Ch0HNlN0bmKIkPMLUlUAAE_EGt-1uo,3298
|
4
|
-
reyserver/rclient.py,sha256=OjY_OEH_USrJK8TuCevXG6jNPVbM0lN-xMBozB7kSM8,2195
|
5
|
-
reyserver/rfile.py,sha256=pA1LdHjBDJwj7S2k7cemwsHO19Oo0bHtkX_r79RBlJA,8770
|
6
|
-
reyserver/rserver.py,sha256=lsOr_fhiAukQhLHfqH1OfZByuUEzjFoJtqLI7BoNxvI,3401
|
7
|
-
reyserver-1.1.46.dist-info/METADATA,sha256=3E8xJWPt5S6j3piVBeuAbFSXzqbTHq6hhrEp5EJ0YLg,1658
|
8
|
-
reyserver-1.1.46.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
reyserver-1.1.46.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
|
10
|
-
reyserver-1.1.46.dist-info/RECORD,,
|
File without changes
|
File without changes
|