CheeseAPI 0.3.5__tar.gz → 0.3.6__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.
@@ -18,41 +18,43 @@ class App:
18
18
 
19
19
  self.workspace: Workspace = Workspace()
20
20
  self.server: Server = Server()
21
- self.httpWorker: HttpWorker = HttpWorker()
22
- self.websocketWorker: WebsocketWorker = WebsocketWorker()
23
21
  self.routeBus: RouteBus = RouteBus()
24
22
  self.route: Route = Route()
25
23
  self.cors: Cors = Cors()
26
- self.managers: Dict[str, multiprocessing.Manager] = {}
24
+ self.g: Dict[str, Any] = {}
25
+ self.managers: Dict[str, Any] = {
26
+ 'lock': multiprocessing.Lock()
27
+ }
27
28
 
28
29
  self.modules: List[str] = []
29
30
  self.localModules: List[str] | Literal[True] = True
30
31
  self.exclude_localModules: List[str] = []
31
32
  self.preferred_localModules: List[str] = []
32
33
 
33
- self.handle: Handle = Handle()
34
- self.g: Dict[str, Any] = {}
34
+ self.httpWorker: HttpWorker = HttpWorker()
35
+ self.websocketWorker: WebsocketWorker = WebsocketWorker()
36
+ self._handle: Handle = Handle()
37
+ self._managers: Dict[str, Any] = {
38
+ 'firstRequest': multiprocessing.Value('b', False),
39
+ 'startedWorkerNum': multiprocessing.Value('i', 0)
40
+ }
35
41
 
36
42
  def init(self):
37
43
  try:
38
- self.handle._initHandle(self)
44
+ self._handle._initHandle(self)
39
45
  except Exception as e:
40
46
  sys.excepthook(Exception, e, sys.exc_info()[2])
41
47
 
42
- def run(self, *, managers: Dict[str, multiprocessing.Manager] = {}):
48
+ def run(self, *, managers: Dict[str, Any] = {}):
43
49
  if 'startTimer' not in app.g:
44
- logger.error('The app has not yet been initiated!')
50
+ logger.error('The app has not yet been initiated')
45
51
  else:
46
52
  try:
47
53
  self.managers.update(managers)
48
54
  manager = multiprocessing.Manager()
49
- self.managers['lock'] = manager.Lock()
50
- self.managers['startedWorkerNum'] = manager.Value(int, 0)
51
- self.managers['firstRequest'] = manager.Value(bool, False)
55
+ self._managers['workspace.logger'] = manager.Value(str, self.workspace.logger)
52
56
 
53
- self.handle._server_beforeStartingHandle(self)
54
- for server_beforeStartingHandle in self.handle.server_beforeStartingHandles:
55
- server_beforeStartingHandle()
57
+ self._handle._server_beforeStartingHandle(self)
56
58
  if signal.receiver('server_beforeStartingHandle'):
57
59
  signal.send('server_beforeStartingHandle')
58
60
 
@@ -63,70 +65,73 @@ class App:
63
65
 
64
66
  multiprocessing.allow_connection_pickling()
65
67
  for i in range(0, self.server.workers - 1):
66
- process = multiprocessing.Process(target = run, args = (self, sock), name = f'CheeseAPI_Subprocess<{i}>', daemon = True)
68
+ process = multiprocessing.Process(target = run, args = (self, sock), name = f'CheeseAPI_subprocess')
67
69
  process.start()
68
70
 
69
71
  run(self, sock, True)
70
72
 
71
- while self.managers['startedWorkerNum'].value != 0:
72
- time.sleep(0.1)
73
+ while self._managers['startedWorkerNum'].value != 0:
74
+ time.sleep(0.01)
73
75
  except Exception as e:
74
76
  sys.excepthook(Exception, e, sys.exc_info()[2])
75
77
 
76
78
  if signal.receiver('server_beforeStoppingHandle'):
77
79
  signal.send('server_beforeStoppingHandle')
78
- for server_beforeStoppingHandle in self.handle.server_beforeStoppingHandles:
79
- server_beforeStoppingHandle()
80
- self.handle._server_beforeStoppingHandle(self)
81
- logger.destory()
80
+ self._handle._server_beforeStoppingHandle(self)
81
+ logger.destroy()
82
82
 
83
83
  app = App()
84
84
 
85
- async def _run(app: App, sock: socket.socket, master: bool = False):
85
+ async def _run(_app: App, sock: socket.socket, master: bool = False):
86
86
  from CheeseAPI.protocol import HttpProtocol
87
87
 
88
- app.handle._worker_beforeStartingHandle()
89
- for worker_beforeStartingHandle in app.handle.worker_beforeStartingHandles:
90
- worker_beforeStartingHandle()
88
+ app.g = _app.g
89
+ app.managers = _app.managers
90
+ app._managers = _app._managers
91
+
92
+ app.workspace.logger = app._managers['workspace.logger'].value
93
+
94
+ app._handle._worker_beforeStartingHandle()
91
95
  if signal.receiver('worker_beforeStartingHandle'):
92
- signal.send('worker_beforeStartingHandle')
96
+ await signal.async_send('worker_beforeStartingHandle')
93
97
 
94
- HttpProtocol.managers = app.managers
98
+ HttpProtocol.managers = app._managers
95
99
 
96
100
  loop = asyncio.get_running_loop()
97
101
  server = await loop.create_server(HttpProtocol, sock = sock)
98
- loop.add_signal_handler(pySignal.SIGINT, app.handle._exitSignalHandle, server)
99
- loop.add_signal_handler(pySignal.SIGTERM, app.handle._exitSignalHandle, server)
102
+ loop.add_signal_handler(pySignal.SIGINT, app._handle._exitSignalHandle, server)
103
+ loop.add_signal_handler(pySignal.SIGTERM, app._handle._exitSignalHandle, server)
100
104
 
101
- for worker_afterStartingHandle in app.handle.worker_afterStartingHandles:
102
- worker_afterStartingHandle()
103
105
  if signal.receiver('worker_afterStartingHandle'):
104
- signal.send('worker_afterStartingHandle')
106
+ await signal.async_send('worker_afterStartingHandle')
105
107
 
106
108
  with app.managers['lock']:
107
- app.managers['startedWorkerNum'].value += 1
108
- if app.managers['startedWorkerNum'].value == app.server.workers:
109
- app.handle._server_afterStartingHandle(app)
110
- for server_afterStartingHandle in app.handle.server_afterStartingHandles:
111
- server_afterStartingHandle()
109
+ app._managers['startedWorkerNum'].value += 1
110
+ if app._managers['startedWorkerNum'].value == app.server.workers:
111
+ app._handle._server_afterStartingHandle(app)
112
112
  if signal.receiver('server_afterStartingHandle'):
113
- signal.send('server_afterStartingHandle')
113
+ await signal.async_send('server_afterStartingHandle')
114
114
 
115
115
  while server.is_serving():
116
- await asyncio.sleep(0.1)
116
+ if app._managers['workspace.logger'].value != app.workspace.logger:
117
+ app.workspace.logger = app._managers['workspace.logger'].value
118
+
119
+ await asyncio.sleep(0.01)
117
120
 
118
121
  if signal.receiver('worker_beforeStoppingHandle'):
119
- signal.send('worker_beforeStoppingHandle')
120
- for worker_beforeStoppingHandle in app.handle.worker_beforeStoppingHandles:
121
- worker_beforeStoppingHandle()
122
- app.handle._worker_beforeStoppingHandle(app)
122
+ await signal.async_send('worker_beforeStoppingHandle')
123
+ app._handle._worker_beforeStoppingHandle(app)
123
124
 
124
125
  with app.managers['lock']:
125
- app.managers['startedWorkerNum'].value -= 1
126
+ app._managers['startedWorkerNum'].value -= 1
126
127
 
127
128
  if not master:
128
- logger.destory()
129
+ logger.destroy()
129
130
 
130
131
  def run(app, sock, master: bool = False):
132
+ import setproctitle
133
+
134
+ setproctitle.setproctitle('CheeseAPI_masterProcess' if master else 'CheeseAPI_subprocess')
135
+
131
136
  asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
132
137
  asyncio.run(_run(app, sock, master))
@@ -14,20 +14,6 @@ if TYPE_CHECKING:
14
14
  from CheeseAPI.protocol import WebsocketProtocol, Protocol
15
15
 
16
16
  class Handle:
17
- def __init__(self):
18
- self.afterInitHandles: List[Callable] = []
19
- self.server_beforeStartingHandles: List[Callable] = []
20
- self.worker_beforeStartingHandles: List[Callable] = []
21
- self.worker_afterStartingHandles: List[Callable] = []
22
- self.server_afterStartingHandles: List[Callable] = []
23
- self.context_beforeFirstRequestHandles: List[Callable] = []
24
- self.http_beforeRequestHandles: List[Callable] = []
25
- self.http_afterResponseHandles: List[Callable] = []
26
- self.websocket_beforeConnectionHandles: List[Callable] = []
27
- self.websocket_afterDisconnectionHandles: List[Callable] = []
28
- self.worker_beforeStoppingHandles: List[Callable] = []
29
- self.server_beforeStoppingHandles: List[Callable] = []
30
-
31
17
  async def _httpHandle(self, protocol: 'Protocol', app: 'App'):
32
18
  try:
33
19
  if app.server.static and protocol.request.path.startswith(app.server.static) and protocol.request.method == http.HTTPMethod.GET:
@@ -40,8 +26,6 @@ class Handle:
40
26
  try:
41
27
  func, kwargs = app.routeBus._match(protocol.request.path, protocol.request.method)
42
28
 
43
- for http_beforeRequestHandle in self.http_beforeRequestHandles:
44
- await http_beforeRequestHandle(**{ 'request': protocol.request })
45
29
  if signal.receiver('http_beforeRequestHandle'):
46
30
  await signal.async_send('http_beforeRequestHandle', { 'request': protocol.request })
47
31
 
@@ -99,16 +83,6 @@ class Handle:
99
83
 
100
84
  if signal.receiver('afterInitHandle'):
101
85
  signal.send('afterInitHandle')
102
- for afterInitHandle in app.handle.afterInitHandles:
103
- afterInitHandle()
104
-
105
- def afterInitHandle(self, func: Callable):
106
- self.afterInitHandles.append(func)
107
- return func
108
-
109
- def server_beforeStartingHandle(self, func: Callable):
110
- self.server_beforeStartingHandles.append(func)
111
- return func
112
86
 
113
87
  def _server_beforeStartingHandle(self, app: 'App'):
114
88
  logger.starting(f'The master process {os.getpid()} started', f'The master process <blue>{os.getpid()}</blue> started')
@@ -136,39 +110,19 @@ Workers: <blue>{app.server.workers}</blue>''' + (f'''
136
110
  Static: <cyan>{app.server.static}</cyan>''' if app.server.static else ''))
137
111
 
138
112
  if app.modules:
139
- logger.starting(f'''Modules:
113
+ logger.loaded(f'''Modules:
140
114
  ''' + ' | '.join(app.modules))
141
115
 
142
116
  if app.localModules:
143
- logger.starting(f'''Local Modules:
117
+ logger.loaded(f'''Local Modules:
144
118
  ''' + ' | '.join(app.localModules))
145
119
 
146
- def worker_beforeStartingHandle(self, func: Callable):
147
- self.worker_beforeStartingHandles.append(func)
148
- return func
149
-
150
120
  def _worker_beforeStartingHandle(self):
151
121
  logger.debug(f'The subprocess {os.getpid()} started', f'The subprocess <blue>{os.getpid()}</blue> started')
152
122
 
153
- def worker_afterStartingHandle(self, func: Callable):
154
- self.worker_afterStartingHandles.append(func)
155
- return func
156
-
157
- def server_afterStartingHandle(self, func: Callable):
158
- self.server_afterStartingHandles.append(func)
159
- return func
160
-
161
123
  def _server_afterStartingHandle(self, app: 'App'):
162
124
  logger.starting(f'The server started on http://{app.server.host}:{app.server.port}', f'The server started on <cyan><underline>http://{app.server.host}:{app.server.port}</underline></cyan>')
163
125
 
164
- def context_beforeFirstRequestHandle(self, func: Callable):
165
- self.context_beforeFirstRequestHandles.append(func)
166
- return func
167
-
168
- def http_beforeRequestHandle(self, func: Callable):
169
- self.http_beforeRequestHandles.append(func)
170
- return func
171
-
172
126
  async def _http_staticHandle(self, protocol: 'Protocol', app: 'App'):
173
127
  return FileResponse(app.workspace.static[:-1] + protocol.request.path)
174
128
 
@@ -203,11 +157,6 @@ A usable BaseResponse is not returned''')
203
157
  'response': response,
204
158
  'request': protocol.request
205
159
  })
206
- for http_afterResponseHandle in self.http_afterResponseHandles:
207
- await http_afterResponseHandle(**{
208
- 'response': response,
209
- 'request': protocol.request
210
- })
211
160
 
212
161
  if app.cors.origin == '*':
213
162
  response.headers['Access-Control-Allow-Origin'] = app.cors.origin
@@ -241,17 +190,13 @@ A usable BaseResponse is not returned''')
241
190
  if protocol.deque:
242
191
  _protocol = protocol.deque.popleft()
243
192
  _protocol.transport.resume_reading()
244
- protocol.task = asyncio.get_event_loop().create_task(app.handle._httpHandle(_protocol, app))
193
+ protocol.task = asyncio.get_event_loop().create_task(app._handle._httpHandle(_protocol, app))
245
194
  protocol.task.add_done_callback(app.httpWorker.tasks.discard)
246
195
  app.httpWorker.tasks.add(protocol.task)
247
196
 
248
197
  return True
249
198
  return False
250
199
 
251
- def http_afterResponseHandle(self, func: Callable):
252
- self.http_afterResponseHandles.append(func)
253
- return func
254
-
255
200
  async def _websocket_requestHandle(self, protocol: 'WebsocketProtocol', app: 'App') -> Tuple[Callable, Dict[str, Any]] | HTTPResponse:
256
201
  try:
257
202
  func, kwargs = app.routeBus._match(protocol.request.path, 'WEBSOCKET')
@@ -270,14 +215,12 @@ A usable BaseResponse is not returned''')
270
215
  async def _websocket_405Handle(self, protocol: 'WebsocketProtocol', app: 'App') -> Response:
271
216
  return Response(status = http.HTTPStatus.METHOD_NOT_ALLOWED)
272
217
 
273
- async def _websocket_responseHandle(self, protocol: 'WebsocketProtocol', app: 'App', response) -> HTTPResponse:
274
- for http_afterResponseHandle in self.http_afterResponseHandles:
275
- _response = await http_afterResponseHandle(**{
218
+ async def _websocket_responseHandle(self, protocol: 'WebsocketProtocol', app: 'App', response: BaseResponse) -> HTTPResponse:
219
+ if signal.receiver('http_afterResponseHandle'):
220
+ await signal.async_send('http_afterResponseHandle', {
276
221
  'response': response,
277
222
  'request': protocol.request
278
223
  })
279
- if isinstance(_response, BaseResponse):
280
- response = _response
281
224
 
282
225
  logger.http(f'The {protocol.request.headers.get("X-Forwarded-For").split(", ")[0]} accessed WEBSOCKET {protocol.request.fullPath} and returned {response.status}', f'The <cyan>{protocol.request.headers.get("X-Forwarded-For").split(", ")[0]}</cyan> accessed <cyan>WEBSOCKET ' + logger.encode(protocol.request.fullPath) + f'</cyan> and returned <blue>{response.status}</blue>')
283
226
 
@@ -290,10 +233,6 @@ A usable BaseResponse is not returned''')
290
233
  })
291
234
  return protocol.func[0].subprotocolHandle(**kwargs)
292
235
 
293
- def websocket_beforeConnectionHandle(self, func: Callable):
294
- self.websocket_beforeConnectionHandles.append(func)
295
- return func
296
-
297
236
  async def _websocket_connectionHandle(self, protocol: 'WebsocketProtocol', app: 'App'):
298
237
  try:
299
238
  logger.websocket(f'The {protocol.request.headers.get("X-Forwarded-For").split(", ")[0]} connected WEBSOCKET {protocol.request.fullPath}', f'The <cyan>{protocol.request.headers.get("X-Forwarded-For").split(", ")[0]}</cyan> connected <cyan>WEBSOCKET {protocol.request.fullPath}</cyan>')
@@ -307,15 +246,13 @@ A usable BaseResponse is not returned''')
307
246
 
308
247
  async def _websocket_handler(self, protocol: 'WebsocketProtocol', app: 'App'):
309
248
  try:
310
- for websocket_beforeConnectionHandle in app.handle.websocket_beforeConnectionHandles:
311
- await websocket_beforeConnectionHandle(**protocol.func[1])
312
249
  if signal.receiver('websocket_beforeConnectionHandle'):
313
250
  await signal.async_send('websocket_beforeConnectionHandle', protocol.func[1])
314
251
 
315
- await app.handle._websocket_connectionHandle(protocol, app)
252
+ await app._handle._websocket_connectionHandle(protocol, app)
316
253
 
317
254
  while not protocol.closed:
318
- await app.handle._websocket_messageHandle(protocol, app)
255
+ await app._handle._websocket_messageHandle(protocol, app)
319
256
  except:
320
257
  message = logger.encode(traceback.format_exc()[:-1])
321
258
  logger.danger(f'''An error occurred while receiving WEBSOCKET {protocol.request.fullPath} message:
@@ -341,10 +278,6 @@ A usable BaseResponse is not returned''')
341
278
  {message}''', f'''An error occurred while receiving <cyan>WEBSOCKET {protocol.request.fullPath}</cyan> message:
342
279
  {message}''')
343
280
 
344
- def websocket_afterDisconnectionHandle(self, func: Callable):
345
- self.websocket_afterDisconnectionHandles.append(func)
346
- return func
347
-
348
281
  def _websocket_disconnectionHandle(self, protocol: 'WebsocketProtocol', app: 'App'):
349
282
  if not protocol.func:
350
283
  return
@@ -356,25 +289,15 @@ A usable BaseResponse is not returned''')
356
289
 
357
290
  if signal.receiver('websocket_afterDisconnectionHandle'):
358
291
  signal.send('websocket_afterDisconnectionHandle', protocol.func[1])
359
- for websocket_afterDisconnectionHandle in app.handle.websocket_afterDisconnectionHandles:
360
- websocket_afterDisconnectionHandle(**protocol.func[1])
361
292
  except:
362
293
  message = logger.encode(traceback.format_exc()[:-1])
363
294
  logger.danger(f'''An error occurred while disconnecting WEBSOCKET {protocol.request.fullPath}:
364
295
  {message}''', f'''An error occurred while disconnecting <cyan>WEBSOCKET {protocol.request.fullPath}</cyan>:
365
296
  {message}''')
366
297
 
367
- def worker_beforeStoppingHandle(self, func: Callable):
368
- self.worker_beforeStoppingHandles.append(func)
369
- return func
370
-
371
298
  def _worker_beforeStoppingHandle(self, app: 'App'):
372
299
  logger.debug(f'The {os.getpid()} subprocess stopped', f'The <blue>{os.getpid()}</blue> subprocess stopped')
373
300
 
374
- def server_beforeStoppingHandle(self, func: Callable):
375
- self.server_beforeStoppingHandles.append(func)
376
- return func
377
-
378
301
  def _server_beforeStoppingHandle(self, app: 'App'):
379
302
  timer = time.time() - app.g['startTimer']
380
303
  message = 'The server runs for a total of '
@@ -48,7 +48,7 @@ class WebsocketProtocol(WebSocketServerProtocol):
48
48
  super().connection_made(transport)
49
49
 
50
50
  async def process_request(self, *args, **kwargs) -> HTTPResponse | None:
51
- result = await app.handle._websocket_requestHandle(self, app)
51
+ result = await app._handle._websocket_requestHandle(self, app)
52
52
  if len(result) == 3:
53
53
  return result
54
54
  self.func = result
@@ -56,13 +56,13 @@ class WebsocketProtocol(WebSocketServerProtocol):
56
56
  self.func[0].close = self.close
57
57
 
58
58
  def process_subprotocol(self, *args, **kwargs) -> str:
59
- self.func[1]['subprotocol'] = app.handle._websocket_subprotocolHandle(self, app)
59
+ self.func[1]['subprotocol'] = app._handle._websocket_subprotocolHandle(self, app)
60
60
  if self.func[1]['subprotocol'] not in self.request.headers.get('Sec-Websocket-Protocol', '').split(', '):
61
61
  raise InvalidHandshake()
62
62
  return self.func[1]['subprotocol']
63
63
 
64
64
  async def ws_handler(self, *args, **kwargs):
65
- await app.handle._websocket_handler(self, app)
65
+ await app._handle._websocket_handler(self, app)
66
66
 
67
67
  def connection_lost(self, exc: Exception | None) -> None:
68
68
  app.websocketWorker.connections.discard(self)
@@ -70,7 +70,7 @@ class WebsocketProtocol(WebSocketServerProtocol):
70
70
  if exc is None:
71
71
  self.transport.close()
72
72
 
73
- app.handle._websocket_disconnectionHandle(self, app)
73
+ app._handle._websocket_disconnectionHandle(self, app)
74
74
 
75
75
  class Protocol:
76
76
  def __init__(self, parser):
@@ -87,8 +87,6 @@ class HttpProtocol(asyncio.Protocol):
87
87
 
88
88
  def __init__(self):
89
89
  if not HttpProtocol.managers['firstRequest'].value:
90
- for context_beforeFirstRequestHandle in app.handle.context_beforeFirstRequestHandles:
91
- context_beforeFirstRequestHandle()
92
90
  if signal.receiver('context_beforeFirstRequestHandle'):
93
91
  signal.send('context_beforeFirstRequestHandle')
94
92
  HttpProtocol.managers['firstRequest'].value = True
@@ -149,7 +147,7 @@ class HttpProtocol(asyncio.Protocol):
149
147
  self.protocol.transport.pause_reading()
150
148
  self.protocol.deque.append(self.protocol)
151
149
  else:
152
- self.protocol.task = asyncio.get_event_loop().create_task(app.handle._httpHandle(self.protocol, app))
150
+ self.protocol.task = asyncio.get_event_loop().create_task(app._handle._httpHandle(self.protocol, app))
153
151
  self.protocol.task.add_done_callback(app.httpWorker.tasks.discard)
154
152
  app.httpWorker.tasks.add(self.protocol.task)
155
153
 
@@ -1,4 +1,5 @@
1
1
  import blinker
2
+ from ordered_set import OrderedSet
2
3
 
3
4
  class Signal(dict):
4
5
  def register(self, name: str):
@@ -32,6 +33,8 @@ class Signal(dict):
32
33
 
33
34
  await self[name].send_async(*args, **kwargs)
34
35
 
36
+ blinker.Signal.set_class = OrderedSet
37
+
35
38
  signal = Signal()
36
39
 
37
40
  signal.register('afterInitHandle')
@@ -16,6 +16,8 @@ class Workspace:
16
16
 
17
17
  @logger.setter
18
18
  def logger(self, value: str | bool):
19
+ from CheeseAPI import app
20
+
19
21
  if value is True:
20
22
  self._logger = datetime.datetime.now().strftime('%Y_%m_%d-%H_%M_%S.log')
21
23
  elif value is False:
@@ -24,3 +26,6 @@ class Workspace:
24
26
  else:
25
27
  self._logger = datetime.datetime.now().strftime(str(value))
26
28
  logger.filePath = self.log + self._logger
29
+
30
+ if 'workspace.logger' in app._managers and app._managers['workspace.logger'].value != logger.filePath:
31
+ app._managers['workspace.logger'].value = self.logger
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: CheeseAPI
3
- Version: 0.3.5
3
+ Version: 0.3.6
4
4
  Summary: 一款web协程框架。
5
5
  Project-URL: Source, https://github.com/CheeseUnknown/CheeseAPI
6
6
  Author-email: Cheese Unknown <cheese@cheese.ren>
@@ -8,6 +8,7 @@ License-File: LICENSE
8
8
  Requires-Dist: blinker
9
9
  Requires-Dist: cheeselog
10
10
  Requires-Dist: httptools
11
+ Requires-Dist: ordered-set
11
12
  Requires-Dist: uvloop
12
13
  Requires-Dist: websockets
13
14
  Requires-Dist: xmltodict
@@ -111,31 +112,28 @@ CheeseAPI采用类Django的结构:
111
112
  | model.py | 模型类 |
112
113
  | api.py | api接口 |
113
114
  | service.py | 业务逻辑实现 |
115
+ | handle.py | 初始化逻辑 |
114
116
 
115
117
  ## **更多...**
116
118
 
117
- ### 1. [**生命周期**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/生命周期.md)
119
+ ### 1. [**App**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App.md)
118
120
 
119
- ### 2. [**App**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App.md)
121
+ #### 1.1 [**Workspace**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Workspace.md)
120
122
 
121
- #### 2.1 [**Workspace**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Workspace.md)
123
+ #### 1.2 [**Server**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Server.md)
122
124
 
123
- #### 2.2 [**Server**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Server.md)
125
+ #### 1.3 [**Cors**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Cors.md)
124
126
 
125
- #### 2.3 [**Cors**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Cors.md)
127
+ ### 2. [**Route**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Route.md)
126
128
 
127
- #### 2.4 [**Handle**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Handle.md)
129
+ ### 3. [**Request**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Request.md)
128
130
 
129
- ### 3. [**Route**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Route.md)
131
+ ### 4. [**Response**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Response.md)
130
132
 
131
- ### 4. [**Request**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Request.md)
133
+ ### 5. [**Websocket**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Websocket.md)
132
134
 
133
- ### 5. [**Response**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Response.md)
135
+ ### 6. [**Module**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Module.md)
134
136
 
135
- ### 6. [**Websocket**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Websocket.md)
136
-
137
- ### 7. [**Module**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Module.md)
137
+ ### 7. [**Signal**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Signal.md)
138
138
 
139
139
  ### 8. [**File**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/File.md)
140
-
141
- ### 9. [**Signal**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Signal.md)
@@ -96,31 +96,28 @@ CheeseAPI采用类Django的结构:
96
96
  | model.py | 模型类 |
97
97
  | api.py | api接口 |
98
98
  | service.py | 业务逻辑实现 |
99
+ | handle.py | 初始化逻辑 |
99
100
 
100
101
  ## **更多...**
101
102
 
102
- ### 1. [**生命周期**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/生命周期.md)
103
+ ### 1. [**App**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App.md)
103
104
 
104
- ### 2. [**App**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App.md)
105
+ #### 1.1 [**Workspace**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Workspace.md)
105
106
 
106
- #### 2.1 [**Workspace**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Workspace.md)
107
+ #### 1.2 [**Server**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Server.md)
107
108
 
108
- #### 2.2 [**Server**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Server.md)
109
+ #### 1.3 [**Cors**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Cors.md)
109
110
 
110
- #### 2.3 [**Cors**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Cors.md)
111
+ ### 2. [**Route**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Route.md)
111
112
 
112
- #### 2.4 [**Handle**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/App/Handle.md)
113
+ ### 3. [**Request**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Request.md)
113
114
 
114
- ### 3. [**Route**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Route.md)
115
+ ### 4. [**Response**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Response.md)
115
116
 
116
- ### 4. [**Request**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Request.md)
117
+ ### 5. [**Websocket**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Websocket.md)
117
118
 
118
- ### 5. [**Response**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Response.md)
119
+ ### 6. [**Module**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Module.md)
119
120
 
120
- ### 6. [**Websocket**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Websocket.md)
121
-
122
- ### 7. [**Module**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Module.md)
121
+ ### 7. [**Signal**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Signal.md)
123
122
 
124
123
  ### 8. [**File**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/File.md)
125
-
126
- ### 9. [**Signal**](https://github.com/CheeseUnknown/CheeseAPI/blob/master/documents/Signal.md)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "CheeseAPI"
7
- version = "0.3.5"
7
+ version = "0.3.6"
8
8
  description = "一款web协程框架。"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -16,7 +16,8 @@ dependencies = [
16
16
  "blinker",
17
17
  "websockets",
18
18
  "uvloop",
19
- "httptools"
19
+ "httptools",
20
+ "ordered_set"
20
21
  ]
21
22
 
22
23
  [project.urls]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes