dbgr-server 1.1.0.dev1__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.
- dbgr_server/__init__.py +1 -0
- dbgr_server/__main__.py +61 -0
- dbgr_server/app.py +139 -0
- dbgr_server/constants.py +10 -0
- dbgr_server/routes.py +22 -0
- dbgr_server/static/fonts/MapleMono-NF-Bold.ttf +0 -0
- dbgr_server/static/fonts/MapleMono-NF-BoldItalic.ttf +0 -0
- dbgr_server/static/fonts/MapleMono-NF-Italic.ttf +0 -0
- dbgr_server/static/fonts/MapleMono-NF-Regular.ttf +0 -0
- dbgr_server/static/images/favicon.ico +0 -0
- dbgr_server/static/javascripts/dist/0d8bb5b3ee5f5dac9e44.woff2 +0 -0
- dbgr_server/static/javascripts/dist/16b1558858fe1064b5af.woff +0 -0
- dbgr_server/static/javascripts/dist/176f8f5bd5f02b3abfcf.woff2 +0 -0
- dbgr_server/static/javascripts/dist/18d00f739ff1e1c52db1.woff +0 -0
- dbgr_server/static/javascripts/dist/1b3b4f49d5b3b3fb2c20.jpg +0 -0
- dbgr_server/static/javascripts/dist/1ce08cfde36c0d81af5b.woff +0 -0
- dbgr_server/static/javascripts/dist/213eedde97d22010287c.woff +0 -0
- dbgr_server/static/javascripts/dist/2267169ee7270a22a963.woff +0 -0
- dbgr_server/static/javascripts/dist/24a9d3bbf9b715214bf5.woff +0 -0
- dbgr_server/static/javascripts/dist/2900d24e7347deaf65cd.woff +0 -0
- dbgr_server/static/javascripts/dist/2ed4651232a34d737777.woff +0 -0
- dbgr_server/static/javascripts/dist/37a7069dc30fc663c878.woff2 +0 -0
- dbgr_server/static/javascripts/dist/451d4e559d6f57cdf6a1.woff +0 -0
- dbgr_server/static/javascripts/dist/4674f8ded773cb03e824.eot +0 -0
- dbgr_server/static/javascripts/dist/498042b7fe9cd07b4fd1.woff +0 -0
- dbgr_server/static/javascripts/dist/49ae34d4cc6b98c00c69.woff +0 -0
- dbgr_server/static/javascripts/dist/51aa168dd4ba03bd83f0.woff2 +0 -0
- dbgr_server/static/javascripts/dist/535bc89d4af715503b01.woff2 +0 -0
- dbgr_server/static/javascripts/dist/53b43867955fbecc811a.woff2 +0 -0
- dbgr_server/static/javascripts/dist/5e7382c63da0098d634a.ttf +0 -0
- dbgr_server/static/javascripts/dist/640f8692dc49a19f1541.woff +0 -0
- dbgr_server/static/javascripts/dist/79f21d796f266ce0ea70.woff +0 -0
- dbgr_server/static/javascripts/dist/7d8125ff7f707231fd89.woff2 +0 -0
- dbgr_server/static/javascripts/dist/7f7e9cd596438fea4b02.woff2 +0 -0
- dbgr_server/static/javascripts/dist/7f839a8652da29745ce4.woff2 +0 -0
- dbgr_server/static/javascripts/dist/83bebaf37c09c7e1c3ee.woff +0 -0
- dbgr_server/static/javascripts/dist/865f928cbabcc9f8f2b5.woff +0 -0
- dbgr_server/static/javascripts/dist/870c8c1486f76054301a.woff2 +0 -0
- dbgr_server/static/javascripts/dist/9216be4e13fe7dbe70ef.woff2 +0 -0
- dbgr_server/static/javascripts/dist/9360531f9bb817f917f0.woff +0 -0
- dbgr_server/static/javascripts/dist/969a44e1b6fc26105bd6.woff2 +0 -0
- dbgr_server/static/javascripts/dist/a45108d3b34af91f9113.woff +0 -0
- dbgr_server/static/javascripts/dist/b1d9d9904bfca8802a63.woff +0 -0
- dbgr_server/static/javascripts/dist/b39a11f9a6107e57a21f.woff2 +0 -0
- dbgr_server/static/javascripts/dist/bac8362e7a6ea60b6983.woff +0 -0
- dbgr_server/static/javascripts/dist/bbbf6951525a78fff340.woff +0 -0
- dbgr_server/static/javascripts/dist/bc628a95b5026af0df2c.woff2 +0 -0
- dbgr_server/static/javascripts/dist/bd5b7a13f2c52b531a2a.woff +0 -0
- dbgr_server/static/javascripts/dist/bf4b4e73015a3066da91.woff +0 -0
- dbgr_server/static/javascripts/dist/bfe6eaec56c141a0bd72.woff2 +0 -0
- dbgr_server/static/javascripts/dist/c18ee39fb002ad58b6dc.woff2 +0 -0
- dbgr_server/static/javascripts/dist/c1f17364fee75703a7ee.woff2 +0 -0
- dbgr_server/static/javascripts/dist/c20d916c1a1b094c1cec.woff +0 -0
- dbgr_server/static/javascripts/dist/c2aa4ab115bf9c6057cb.woff2 +0 -0
- dbgr_server/static/javascripts/dist/c5c3959c04004102ea46.woff2 +0 -0
- dbgr_server/static/javascripts/dist/c64e7e354c88e613c77c.woff2 +0 -0
- dbgr_server/static/javascripts/dist/ca100b2be6274105bb16.woff +0 -0
- dbgr_server/static/javascripts/dist/cb5ad999740e9d8a8bd1.woff2 +0 -0
- dbgr_server/static/javascripts/dist/cc9e42999888377183f8.woff2 +0 -0
- dbgr_server/static/javascripts/dist/cea99d3e3e13a3a599a0.woff +0 -0
- dbgr_server/static/javascripts/dist/cff684e59ffb052d72cb.woff2 +0 -0
- dbgr_server/static/javascripts/dist/d022bc70dc1bf7b3425d.woff2 +0 -0
- dbgr_server/static/javascripts/dist/d97850bb044fb5584361.woff2 +0 -0
- dbgr_server/static/javascripts/dist/da65dcd09cdc4863ece2.woff +0 -0
- dbgr_server/static/javascripts/dist/dbgr.js +1463 -0
- dbgr_server/static/javascripts/dist/eba647ae67ba7dc20f05.woff +0 -0
- dbgr_server/static/javascripts/dist/f5b74d7ffcdf85b9dd60.woff2 +0 -0
- dbgr_server/static/javascripts/dist/ff2c5c919a01e9ddda85.woff2 +0 -0
- dbgr_server/static/javascripts/dist/home.js +1037 -0
- dbgr_server/static/libs/material-design-lite/material.indigo-red.min.css +8 -0
- dbgr_server/templates/_layout.html +17 -0
- dbgr_server/templates/dbgr.html +138 -0
- dbgr_server/templates/home.html +115 -0
- dbgr_server/utils/__init__.py +0 -0
- dbgr_server/utils/state.py +249 -0
- dbgr_server/utils/streams.py +151 -0
- dbgr_server/utils/technical.py +132 -0
- dbgr_server/views.py +298 -0
- dbgr_server-1.1.0.dev1.data/scripts/dbgr.server.py +105 -0
- dbgr_server-1.1.0.dev1.dist-info/METADATA +534 -0
- dbgr_server-1.1.0.dev1.dist-info/RECORD +86 -0
- dbgr_server-1.1.0.dev1.dist-info/WHEEL +5 -0
- dbgr_server-1.1.0.dev1.dist-info/licenses/LICENSE +674 -0
- dbgr_server-1.1.0.dev1.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/test_app.py +84 -0
dbgr_server/views.py
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# pylint: disable=missing-function-docstring
|
|
2
|
+
# Stdlib:
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import multiprocessing
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from uuid import uuid4
|
|
11
|
+
|
|
12
|
+
# Thirdparty:
|
|
13
|
+
from fastapi import Form, HTTPException, Request
|
|
14
|
+
from fastapi.responses import RedirectResponse
|
|
15
|
+
from fastapi.templating import Jinja2Templates
|
|
16
|
+
from starlette.websockets import WebSocket, WebSocketDisconnect
|
|
17
|
+
|
|
18
|
+
# Firstparty:
|
|
19
|
+
from dbgr_server.constants import UNKNOWN_UUID, UUID_REGEXP, DBGR_TYPES
|
|
20
|
+
from dbgr_server.utils.state import (
|
|
21
|
+
breakpoints,
|
|
22
|
+
settings,
|
|
23
|
+
sockets,
|
|
24
|
+
syncwebsockets,
|
|
25
|
+
websockets,
|
|
26
|
+
)
|
|
27
|
+
from dbgr_server.utils.technical import LibPythonWatcher, refresh_process
|
|
28
|
+
|
|
29
|
+
log = logging.getLogger("dbgr_server")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def self_shell() -> None: # pragma: no cover
|
|
33
|
+
import dbgr # pylint: disable=import-outside-toplevel
|
|
34
|
+
|
|
35
|
+
dbgr.set_trace() # pylint: disable=no-member
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def run_shell() -> None: # pragma: no cover
|
|
39
|
+
from dbgr import Dbgr # pylint: disable=import-outside-toplevel
|
|
40
|
+
|
|
41
|
+
Dbgr.get().shell()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def run_file(file_name: str) -> None: # pragma: no cover
|
|
45
|
+
from dbgr import Dbgr # pylint: disable=import-outside-toplevel
|
|
46
|
+
|
|
47
|
+
Dbgr.get().run_file(file_name)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
# HTTP handlers
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
def _get_templates(request: Request) -> Jinja2Templates:
|
|
55
|
+
return request.app.state.templates # type: ignore[no-any-return]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
async def home_get(request: Request) -> "TemplateResponse": # type: ignore[name-defined]
|
|
59
|
+
templates = _get_templates(request)
|
|
60
|
+
return templates.TemplateResponse(
|
|
61
|
+
request,
|
|
62
|
+
"home.html",
|
|
63
|
+
context={
|
|
64
|
+
"settings": request.app.state.settings,
|
|
65
|
+
"theme": request.app.state.theme,
|
|
66
|
+
"type_": "home",
|
|
67
|
+
"handler_name": "HomeHandler",
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def main_get(request: Request, type_: str, uuid: str) -> "TemplateResponse": # type: ignore[name-defined]
|
|
73
|
+
if type_ not in DBGR_TYPES:
|
|
74
|
+
raise HTTPException(status_code=404, detail=f"type_ {type_} Not Found")
|
|
75
|
+
if not re.fullmatch(UUID_REGEXP, uuid):
|
|
76
|
+
raise HTTPException(status_code=404, detail="Not Found")
|
|
77
|
+
templates = _get_templates(request)
|
|
78
|
+
return templates.TemplateResponse(
|
|
79
|
+
request,
|
|
80
|
+
"dbgr.html",
|
|
81
|
+
context={
|
|
82
|
+
"uuid": uuid,
|
|
83
|
+
"new_version": request.app.state.new_version,
|
|
84
|
+
"type_": type_,
|
|
85
|
+
"settings": request.app.state.settings,
|
|
86
|
+
"theme": request.app.state.theme,
|
|
87
|
+
"handler_name": "MainHandler",
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _debug(fnc: str) -> RedirectResponse:
|
|
93
|
+
multiprocessing.Process(target=run_file, args=(fnc,)).start()
|
|
94
|
+
return RedirectResponse("/", status_code=302)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def debug_get(fn: str) -> RedirectResponse:
|
|
98
|
+
return _debug(fn)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
async def debug_post_form(
|
|
102
|
+
fn: str = "",
|
|
103
|
+
debug_file: Optional[str] = Form(None),
|
|
104
|
+
) -> RedirectResponse:
|
|
105
|
+
target = debug_file or fn
|
|
106
|
+
if target:
|
|
107
|
+
return _debug(target)
|
|
108
|
+
raise HTTPException(status_code=400, detail="No file specified")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# ---------------------------------------------------------------------------
|
|
112
|
+
# WebSocket handlers
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
class BaseWebSocketHandler:
|
|
116
|
+
uuid: str = UNKNOWN_UUID
|
|
117
|
+
|
|
118
|
+
def __init__(self, ws: WebSocket) -> None:
|
|
119
|
+
self.ws = ws
|
|
120
|
+
|
|
121
|
+
async def write_message(self, message: str) -> None:
|
|
122
|
+
await self.ws.send_text(message)
|
|
123
|
+
|
|
124
|
+
async def write(self, message: str) -> None:
|
|
125
|
+
raise NotImplementedError
|
|
126
|
+
|
|
127
|
+
async def on_open(self) -> None:
|
|
128
|
+
raise NotImplementedError
|
|
129
|
+
|
|
130
|
+
async def on_message(self, message: str) -> None:
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
|
|
133
|
+
async def close(self) -> None:
|
|
134
|
+
try:
|
|
135
|
+
await self.ws.close()
|
|
136
|
+
except Exception: # pylint: disable=broad-except
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
async def on_close(self) -> None:
|
|
140
|
+
raise NotImplementedError
|
|
141
|
+
|
|
142
|
+
async def get(self) -> None:
|
|
143
|
+
await self.ws.accept()
|
|
144
|
+
await self.on_open()
|
|
145
|
+
try:
|
|
146
|
+
while True:
|
|
147
|
+
try:
|
|
148
|
+
data = await self.ws.receive_text()
|
|
149
|
+
await self.on_message(data)
|
|
150
|
+
except WebSocketDisconnect:
|
|
151
|
+
break
|
|
152
|
+
finally:
|
|
153
|
+
await self.on_close()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class SyncWebSocketHandler(BaseWebSocketHandler):
|
|
157
|
+
async def write(self, message: str) -> None:
|
|
158
|
+
log.debug("server -> syncsocket: %s", message)
|
|
159
|
+
await self.write_message(message)
|
|
160
|
+
|
|
161
|
+
async def on_open(self) -> None:
|
|
162
|
+
self.uuid = str(uuid4())
|
|
163
|
+
await syncwebsockets.add(self.uuid, self)
|
|
164
|
+
if not LibPythonWatcher:
|
|
165
|
+
await syncwebsockets.send(self.uuid, "StartLoop")
|
|
166
|
+
|
|
167
|
+
# pylint: disable=too-many-branches
|
|
168
|
+
async def on_message(self, message: str) -> None:
|
|
169
|
+
if "|" in message:
|
|
170
|
+
cmd, data = message.split("|", 1)
|
|
171
|
+
else:
|
|
172
|
+
cmd, data = message, ""
|
|
173
|
+
|
|
174
|
+
if cmd == "ListSockets":
|
|
175
|
+
for uuid in sockets.uuids:
|
|
176
|
+
await syncwebsockets.send(
|
|
177
|
+
self.uuid,
|
|
178
|
+
"AddSocket",
|
|
179
|
+
{
|
|
180
|
+
"uuid": uuid,
|
|
181
|
+
"filename": sockets.get_filename(uuid)
|
|
182
|
+
if settings.show_filename
|
|
183
|
+
else "",
|
|
184
|
+
},
|
|
185
|
+
)
|
|
186
|
+
elif cmd == "ListWebsockets":
|
|
187
|
+
for uuid in websockets.uuids:
|
|
188
|
+
await syncwebsockets.send(self.uuid, "AddWebSocket", uuid)
|
|
189
|
+
elif cmd == "ListBreaks":
|
|
190
|
+
for brk in breakpoints.get():
|
|
191
|
+
await syncwebsockets.send(self.uuid, "AddBreak", brk)
|
|
192
|
+
elif cmd == "RemoveBreak":
|
|
193
|
+
brk = json.loads(data)
|
|
194
|
+
await breakpoints.remove(brk)
|
|
195
|
+
brk["temporary"] = False
|
|
196
|
+
await sockets.broadcast("Unbreak", brk)
|
|
197
|
+
elif cmd == "RemoveUUID":
|
|
198
|
+
await sockets.close(data)
|
|
199
|
+
await sockets.remove(data)
|
|
200
|
+
await websockets.close(data)
|
|
201
|
+
await websockets.remove(data)
|
|
202
|
+
elif cmd == "ListProcesses":
|
|
203
|
+
await refresh_process(self.uuid)
|
|
204
|
+
elif cmd == "Pause":
|
|
205
|
+
if int(data) == os.getpid():
|
|
206
|
+
log.debug("Pausing self")
|
|
207
|
+
multiprocessing.Process(target=self_shell).start()
|
|
208
|
+
else:
|
|
209
|
+
log.debug("Pausing %s", data)
|
|
210
|
+
command = ["gdb", "-p", data, "-batch"] + [
|
|
211
|
+
f"-eval-command=call {hook}"
|
|
212
|
+
for hook in [
|
|
213
|
+
"PyGILState_Ensure()",
|
|
214
|
+
"PyRun_SimpleString("
|
|
215
|
+
'"import dbgr; dbgr.set_trace(skip=1)"'
|
|
216
|
+
")",
|
|
217
|
+
"PyGILState_Release($1)",
|
|
218
|
+
]
|
|
219
|
+
]
|
|
220
|
+
await asyncio.create_subprocess_exec(
|
|
221
|
+
*command,
|
|
222
|
+
stdin=asyncio.subprocess.PIPE,
|
|
223
|
+
stderr=asyncio.subprocess.PIPE,
|
|
224
|
+
)
|
|
225
|
+
elif cmd == "RunFile":
|
|
226
|
+
multiprocessing.Process(target=run_file, args=(data,)).start()
|
|
227
|
+
elif cmd == "RunShell":
|
|
228
|
+
multiprocessing.Process(target=run_shell).start()
|
|
229
|
+
|
|
230
|
+
async def on_close(self) -> None:
|
|
231
|
+
await syncwebsockets.remove(self.uuid)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class WebSocketHandler(BaseWebSocketHandler):
|
|
235
|
+
async def write(self, message: str) -> None:
|
|
236
|
+
log.debug("socket -> websocket: %s", message)
|
|
237
|
+
if message.startswith("BreakSet|") or message.startswith("BreakUnset|"):
|
|
238
|
+
log.debug("Intercepted break")
|
|
239
|
+
cmd, _brk = message.split("|", 1)
|
|
240
|
+
brk = json.loads(_brk)
|
|
241
|
+
if not brk["temporary"]:
|
|
242
|
+
del brk["temporary"]
|
|
243
|
+
if cmd == "BreakSet":
|
|
244
|
+
await breakpoints.add(brk)
|
|
245
|
+
elif cmd == "BreakUnset":
|
|
246
|
+
await breakpoints.remove(brk)
|
|
247
|
+
|
|
248
|
+
await self.write_message(message)
|
|
249
|
+
|
|
250
|
+
async def on_open(self) -> None:
|
|
251
|
+
if self.uuid in websockets.uuids:
|
|
252
|
+
log.warning(
|
|
253
|
+
"Websocket already opened for %s. Closing previous one",
|
|
254
|
+
self.uuid,
|
|
255
|
+
)
|
|
256
|
+
await websockets.send(self.uuid, "Die")
|
|
257
|
+
await websockets.close(self.uuid)
|
|
258
|
+
|
|
259
|
+
if self.uuid not in sockets.uuids:
|
|
260
|
+
log.warning(
|
|
261
|
+
"Websocket opened for %s with no corresponding socket",
|
|
262
|
+
self.uuid,
|
|
263
|
+
)
|
|
264
|
+
await sockets.send(self.uuid, "Die")
|
|
265
|
+
await self.on_close()
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
log.info("Websocket opened for %s", self.uuid)
|
|
269
|
+
await websockets.add(self.uuid, self)
|
|
270
|
+
|
|
271
|
+
async def on_message(self, message: str) -> None:
|
|
272
|
+
log.debug("websocket -> socket: %s", message)
|
|
273
|
+
if message.startswith("Broadcast|"):
|
|
274
|
+
message = message.split("|", 1)[1]
|
|
275
|
+
await sockets.broadcast(message)
|
|
276
|
+
else:
|
|
277
|
+
await sockets.send(self.uuid, message)
|
|
278
|
+
|
|
279
|
+
async def on_close(self) -> None:
|
|
280
|
+
log.info("Websocket closed for %s", self.uuid)
|
|
281
|
+
if not settings.detached_session:
|
|
282
|
+
await sockets.send(self.uuid, "Close")
|
|
283
|
+
await sockets.close(self.uuid)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
# ---------------------------------------------------------------------------
|
|
287
|
+
# FastAPI WebSocket endpoints
|
|
288
|
+
# ---------------------------------------------------------------------------
|
|
289
|
+
|
|
290
|
+
async def status_ws(websocket: WebSocket) -> None:
|
|
291
|
+
handler = SyncWebSocketHandler(websocket)
|
|
292
|
+
await handler.get()
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
async def websocket_ws(websocket: WebSocket, uuid: str) -> None:
|
|
296
|
+
handler = WebSocketHandler(websocket)
|
|
297
|
+
handler.uuid = uuid
|
|
298
|
+
await handler.get()
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!python
|
|
2
|
+
# pylint: disable=missing-function-docstring
|
|
3
|
+
|
|
4
|
+
# Stdlib:
|
|
5
|
+
import asyncio
|
|
6
|
+
import argparse
|
|
7
|
+
from logging import DEBUG, INFO, WARNING, getLogger
|
|
8
|
+
|
|
9
|
+
# Thirdparty:
|
|
10
|
+
import uvicorn
|
|
11
|
+
|
|
12
|
+
# Firstparty:
|
|
13
|
+
from dbgr_server.app import init_app
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
parser = argparse.ArgumentParser()
|
|
18
|
+
parser.add_argument(
|
|
19
|
+
"--debug", action="store_true", help="Debug mode (default False)"
|
|
20
|
+
)
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--extra-search-path",
|
|
23
|
+
action="store_true",
|
|
24
|
+
help=(
|
|
25
|
+
"Try harder to find the 'libpython*' shared library at the cost "
|
|
26
|
+
"of a slower server startup. (default False)"
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--more",
|
|
31
|
+
action="store_true",
|
|
32
|
+
help="Set the debug more verbose (default False)",
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"--detached_session",
|
|
36
|
+
action="store_true",
|
|
37
|
+
help="Whether to continue program on browser close (default False)",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--show-filename",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="Whether to show filename in session list (default False)",
|
|
43
|
+
)
|
|
44
|
+
parser.add_argument(
|
|
45
|
+
"--server-host",
|
|
46
|
+
type=str,
|
|
47
|
+
default="localhost",
|
|
48
|
+
help="Host used to serve debugging pages (default localhost)",
|
|
49
|
+
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"--server-port",
|
|
52
|
+
type=int,
|
|
53
|
+
default=1984,
|
|
54
|
+
help="Port used to serve debugging pages (default 1984)",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--socket-host",
|
|
58
|
+
type=str,
|
|
59
|
+
default="localhost",
|
|
60
|
+
help="Host used to communicate with dbgr instances (default localhost)",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--socket-port",
|
|
64
|
+
type=int,
|
|
65
|
+
default=19840,
|
|
66
|
+
help="Port used to communicate with dbgr instances (default 19840)",
|
|
67
|
+
)
|
|
68
|
+
args = parser.parse_args()
|
|
69
|
+
|
|
70
|
+
log = getLogger("dbgr_server")
|
|
71
|
+
if args.debug:
|
|
72
|
+
log.setLevel(INFO)
|
|
73
|
+
if args.more:
|
|
74
|
+
log.setLevel(DEBUG)
|
|
75
|
+
else:
|
|
76
|
+
log.setLevel(WARNING)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
import uvloop # pylint: disable=import-outside-toplevel
|
|
80
|
+
uvloop.install()
|
|
81
|
+
except ImportError: # pragma: no cover
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
settings = {
|
|
85
|
+
"debug": args.debug,
|
|
86
|
+
"extra_search_path": args.extra_search_path,
|
|
87
|
+
"more": args.more,
|
|
88
|
+
"detached_session": args.detached_session,
|
|
89
|
+
"show_filename": args.show_filename,
|
|
90
|
+
"socket_host": args.socket_host,
|
|
91
|
+
"socket_port": args.socket_port,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
app = asyncio.run(init_app(settings))
|
|
95
|
+
|
|
96
|
+
uvicorn.run(
|
|
97
|
+
app,
|
|
98
|
+
host=args.server_host,
|
|
99
|
+
port=args.server_port,
|
|
100
|
+
loop="none",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
main()
|