reyserver 1.1.37__py3-none-any.whl → 1.1.38__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/rfile.py CHANGED
@@ -5,45 +5,32 @@
5
5
  @Time : 2025-10-06 18:23:51
6
6
  @Author : Rey
7
7
  @Contact : reyxbo@163.com
8
- @Explain : File methods.
8
+ @Explain : File methods. Can create database used `self.build_db` function.
9
9
  """
10
10
 
11
11
 
12
12
  from fastapi import APIRouter
13
13
  from reydb import rorm
14
+ from reydb.rdb import DatabaseAsync
14
15
 
15
16
  from . import rserver
16
17
  from .rbase import ServerAPI
17
18
 
18
19
 
19
20
  __all__ = (
20
- 'ServerAPIFile',
21
+ 'file_router',
22
+ 'DatabaseORMTableInfo',
23
+ 'DatabaseORMTableData',
24
+ 'build_file_db'
21
25
  )
22
26
 
23
27
 
24
- # class ServerAPIFile(ServerAPI):
25
- # """
26
- # Server File API type.
27
- # """
28
-
29
-
30
- # def __init__(self, server: 'rserver.Server') -> None:
31
- # """
32
- # Build instance attributes.
33
-
34
- # Parameters
35
- # ----------
36
- # server : Server instance.
37
- # """
38
-
39
- # # Build.
40
- # self.server = server
41
-
28
+ file_router = APIRouter()
42
29
 
43
30
 
44
31
  class DatabaseORMTableInfo(rorm.Model, table=True):
45
32
  """
46
- Database `info` table model.
33
+ Database `info` table ORM model.
47
34
  """
48
35
 
49
36
  __name__ = 'info'
@@ -57,7 +44,7 @@ class DatabaseORMTableInfo(rorm.Model, table=True):
57
44
 
58
45
  class DatabaseORMTableData(rorm.Model, table=True):
59
46
  """
60
- Database `data` table model.
47
+ Database `data` table ORM model.
61
48
  """
62
49
 
63
50
  __name__ = 'data'
@@ -67,13 +54,218 @@ class DatabaseORMTableData(rorm.Model, table=True):
67
54
  path: str = rorm.Field(rorm.types.VARCHAR(4095), not_null=True, comment='File disk storage path.')
68
55
 
69
56
 
70
- router = APIRouter()
57
+ def build_file_db(db: DatabaseAsync) -> None:
58
+ """
59
+ Check and build all standard databases and tables, by `self.db_names`.
60
+
61
+ Parameters
62
+ db : Asynchronous database instance.
63
+ """
64
+
65
+ # Set parameter.
66
+ database = db.database
67
+
68
+ ## Table.
69
+ tables = [DatabaseORMTableInfo, DatabaseORMTableData]
70
+
71
+ ## View.
72
+ views = [
73
+ {
74
+ 'path': 'data_info',
75
+ 'select': (
76
+ 'SELECT `b`.`last_time`, `a`.`md5`, `a`.`size`, `b`.`names`, `b`.`notes`\n'
77
+ f'FROM `{database}`.`data` AS `a`\n'
78
+ 'LEFT JOIN (\n'
79
+ ' SELECT\n'
80
+ ' `md5`,\n'
81
+ " GROUP_CONCAT(DISTINCT(`name`) ORDER BY `create_time` DESC SEPARATOR ' | ') AS `names`,\n"
82
+ " GROUP_CONCAT(DISTINCT(`note`) ORDER BY `create_time` DESC SEPARATOR ' | ') AS `notes`,\n"
83
+ ' MAX(`create_time`) as `last_time`\n'
84
+ f' FROM `{database}`.`info`\n'
85
+ ' GROUP BY `md5`\n'
86
+ ' ORDER BY `last_time` DESC\n'
87
+ ') AS `b`\n'
88
+ 'ON `a`.`md5` = `b`.`md5`\n'
89
+ 'ORDER BY `last_time` DESC'
90
+ )
91
+ }
92
+ ]
93
+
94
+ ## View stats.
95
+ views_stats = [
96
+ {
97
+ 'path': 'stats',
98
+ 'items': [
99
+ {
100
+ 'name': 'count',
101
+ 'select': (
102
+ 'SELECT COUNT(1)\n'
103
+ f'FROM `{database}`.`info`'
104
+ ),
105
+ 'comment': 'File information count.'
106
+ },
107
+ {
108
+ 'name': 'past_day_count',
109
+ 'select': (
110
+ 'SELECT COUNT(1)\n'
111
+ f'FROM `{database}`.`info`\n'
112
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) = 0'
113
+ ),
114
+ 'comment': 'File information count in the past day.'
115
+ },
116
+ {
117
+ 'name': 'past_week_count',
118
+ 'select': (
119
+ 'SELECT COUNT(1)\n'
120
+ f'FROM `{database}`.`info`\n'
121
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 6'
122
+ ),
123
+ 'comment': 'File information count in the past week.'
124
+ },
125
+ {
126
+ 'name': 'past_month_count',
127
+ 'select': (
128
+ 'SELECT COUNT(1)\n'
129
+ f'FROM `{database}`.`info`\n'
130
+ 'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 29'
131
+ ),
132
+ 'comment': 'File information count in the past month.'
133
+ },
134
+ {
135
+ 'name': 'data_count',
136
+ 'select': (
137
+ 'SELECT COUNT(1)\n'
138
+ f'FROM `{database}`.`data`'
139
+ ),
140
+ 'comment': 'File data unique count.'
141
+ },
142
+ {
143
+ 'name': 'total_size',
144
+ 'select': (
145
+ 'SELECT FORMAT(SUM(`size`), 0)\n'
146
+ f'FROM `{database}`.`data`'
147
+ ),
148
+ 'comment': 'File total byte size.'
149
+ },
150
+ {
151
+ 'name': 'avg_size',
152
+ 'select': (
153
+ 'SELECT FORMAT(AVG(`size`), 0)\n'
154
+ f'FROM `{database}`.`data`'
155
+ ),
156
+ 'comment': 'File average byte size.'
157
+ },
158
+ {
159
+ 'name': 'max_size',
160
+ 'select': (
161
+ 'SELECT FORMAT(MAX(`size`), 0)\n'
162
+ f'FROM `{database}`.`data`'
163
+ ),
164
+ 'comment': 'File maximum byte size.'
165
+ },
166
+ {
167
+ 'name': 'last_time',
168
+ 'select': (
169
+ 'SELECT MAX(`create_time`)\n'
170
+ f'FROM `{database}`.`info`'
171
+ ),
172
+ 'comment': 'File last record create time.'
173
+ }
174
+ ]
175
+ }
176
+ ]
177
+
178
+ # Build.
179
+ db.build.build(tables=tables, views=views, views_stats=views_stats)
180
+
181
+
182
+ @file_router.post('/upload')
183
+ def upload(
184
+ source: bytes,
185
+ name: str | None = None,
186
+ note: str | None = None
187
+ ) -> int:
188
+ """
189
+ Upload file.
190
+
191
+ Parameters
192
+ ----------
193
+ source : File path or file bytes.
194
+ name : File name.
195
+ - `None`: Automatic set.
196
+ `parameter 'file' is 'str'`: Use path file name.
197
+ `parameter 'file' is 'bytes'`: No name.
198
+ - `str`: Use this name.
199
+ note : File note.
200
+
201
+ Returns
202
+ -------
203
+ File ID.
204
+ """
205
+
206
+ # Handle parameter.
207
+ conn = self.db.connect()
208
+ match source:
209
+
210
+ ## File path.
211
+ case str():
212
+ file = File(source)
213
+ file_bytes = file.bytes
214
+ file_md5 = get_md5(file_bytes)
215
+ file_name = file.name_suffix
216
+
217
+ ## File bytes.
218
+ case bytes() | bytearray():
219
+ if type(source) == bytearray:
220
+ source = bytes(source)
221
+ file_bytes = source
222
+ file_md5 = get_md5(file_bytes)
223
+ file_name = None
224
+
225
+ ## File name.
226
+ if name is not None:
227
+ file_name = name
228
+
229
+ ## File size.
230
+ file_size = len(file_bytes)
231
+
232
+ # Exist.
233
+ exist = conn.execute.exist(
234
+ (self.db_names['file'], self.db_names['file.data']),
235
+ '`md5` = :file_md5',
236
+ file_md5=file_md5
237
+ )
238
+
239
+ # Upload.
71
240
 
241
+ ## Data.
242
+ if not exist:
243
+ data = {
244
+ 'md5': file_md5,
245
+ 'size': file_size,
246
+ 'bytes': file_bytes
247
+ }
248
+ conn.execute.insert(
249
+ (self.db_names['file'], self.db_names['file.data']),
250
+ data,
251
+ 'ignore'
252
+ )
72
253
 
254
+ ## Information.
255
+ data = {
256
+ 'md5': file_md5,
257
+ 'name': file_name,
258
+ 'note': note
259
+ }
260
+ conn.execute.insert(
261
+ (self.db_names['file'], self.db_names['file.information']),
262
+ data
263
+ )
73
264
 
74
- @router.get('/{file_id}')
75
- def get_file_info(): ...
265
+ # Get ID.
266
+ file_id = conn.insert_id
76
267
 
77
- @router.get('/{}/bytes')
78
- def get_file_bytes(): ...
268
+ # Commit.
269
+ conn.commit()
79
270
 
271
+ return file_id
reyserver/rserver.py CHANGED
@@ -18,7 +18,6 @@ from uvicorn import run as uvicorn_run
18
18
  from reykit.rbase import CoroutineFunctionSimple
19
19
 
20
20
  from .rbase import ServerBase
21
- from .rfile import ServerAPIFile
22
21
 
23
22
 
24
23
  __all__ = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reyserver
3
- Version: 1.1.37
3
+ Version: 1.1.38
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>
@@ -0,0 +1,9 @@
1
+ reyserver/__init__.py,sha256=ZNzM6wBvBSXe1LgV40ZJ1WIAbejWNYGl8x22dmt8C60,289
2
+ reyserver/rall.py,sha256=F-vUJIf5DgP0FXI0pdTrEeEiMtN-g81_yTo4ibUL9xk,233
3
+ reyserver/rbase.py,sha256=TtCmqjofwKkE0vdOIc5WhWxbgAUd8pFgx26-VON11yA,397
4
+ reyserver/rfile.py,sha256=P3i1wa2JYsgNFrm0pDCsDN_zFo_Xpv4XigePotVzn8s,8213
5
+ reyserver/rserver.py,sha256=NyI9_evkZ2uGXajI75X8Paj18N1S2f9xUGgLGeQ_2ag,2546
6
+ reyserver-1.1.38.dist-info/METADATA,sha256=CuZu-kkGUgw0qSvNpzMYVlhIhvF2QL7uG36GZuEn9qE,1549
7
+ reyserver-1.1.38.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ reyserver-1.1.38.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
9
+ reyserver-1.1.38.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- reyserver/__init__.py,sha256=ZNzM6wBvBSXe1LgV40ZJ1WIAbejWNYGl8x22dmt8C60,289
2
- reyserver/rall.py,sha256=F-vUJIf5DgP0FXI0pdTrEeEiMtN-g81_yTo4ibUL9xk,233
3
- reyserver/rbase.py,sha256=TtCmqjofwKkE0vdOIc5WhWxbgAUd8pFgx26-VON11yA,397
4
- reyserver/rfile.py,sha256=j4-X1WJPhiYXLvojMUBVEitlPTlSTKWgIb4uJSeMK6k,1989
5
- reyserver/rserver.py,sha256=PopXz0gu1c36FRgrpvT13BWFCOVwctb-JAlcFmocdjI,2580
6
- reyserver-1.1.37.dist-info/METADATA,sha256=DO6G-zowwi8w6vI74KWig-jtL6Zsz3hsrjZQ-j5ioQM,1549
7
- reyserver-1.1.37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- reyserver-1.1.37.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
9
- reyserver-1.1.37.dist-info/RECORD,,