setta 0.0.1.dev0__py3-none-any.whl → 0.0.2.dev0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (265) hide show
  1. setta/__init__.py +1 -1
  2. setta/cli/__init__.py +1 -0
  3. setta/cli/connect.py +43 -0
  4. setta/cli/logger.py +225 -0
  5. setta/code_gen/__init__.py +0 -0
  6. setta/code_gen/create_runnable_scripts.py +466 -0
  7. setta/code_gen/export_selected.py +776 -0
  8. setta/code_gen/find_placeholders.py +13 -0
  9. setta/code_gen/python/__init__.py +0 -0
  10. setta/code_gen/python/ast_utils.py +183 -0
  11. setta/code_gen/python/check_scope.py +187 -0
  12. setta/code_gen/python/generate_code.py +280 -0
  13. setta/code_gen/python/make_parseable.py +97 -0
  14. setta/code_gen/python/position_line_col.py +33 -0
  15. setta/code_gen/python/validate_imports.py +87 -0
  16. setta/code_gen/utils.py +120 -0
  17. setta/code_gen/yaml/__init__.py +0 -0
  18. setta/code_gen/yaml/generate_yaml.py +23 -0
  19. setta/code_gen/yaml/section_dict.py +93 -0
  20. setta/database/__init__.py +0 -0
  21. setta/database/backup.py +80 -0
  22. setta/database/db/__init__.py +0 -0
  23. setta/database/db/artifacts/__init__.py +0 -0
  24. setta/database/db/artifacts/load.py +93 -0
  25. setta/database/db/artifacts/save.py +85 -0
  26. setta/database/db/artifacts/save_or_create.py +68 -0
  27. setta/database/db/artifacts/utils.py +13 -0
  28. setta/database/db/codeInfo/__init__.py +0 -0
  29. setta/database/db/codeInfo/copy.py +26 -0
  30. setta/database/db/codeInfo/load.py +65 -0
  31. setta/database/db/codeInfo/save.py +75 -0
  32. setta/database/db/codeInfo/utils.py +33 -0
  33. setta/database/db/evRefs/__init__.py +0 -0
  34. setta/database/db/evRefs/load.py +45 -0
  35. setta/database/db/evRefs/save.py +95 -0
  36. setta/database/db/projects/__init__.py +0 -0
  37. setta/database/db/projects/copy.py +36 -0
  38. setta/database/db/projects/delete.py +7 -0
  39. setta/database/db/projects/load.py +184 -0
  40. setta/database/db/projects/save.py +267 -0
  41. setta/database/db/projects/saveAs.py +40 -0
  42. setta/database/db/projects/utils.py +135 -0
  43. setta/database/db/sectionVariants/__init__.py +0 -0
  44. setta/database/db/sectionVariants/copy.py +28 -0
  45. setta/database/db/sectionVariants/load.py +139 -0
  46. setta/database/db/sectionVariants/save.py +140 -0
  47. setta/database/db/sectionVariants/utils.py +44 -0
  48. setta/database/db/sections/__init__.py +0 -0
  49. setta/database/db/sections/copy.py +70 -0
  50. setta/database/db/sections/jsonSource.py +119 -0
  51. setta/database/db/sections/load.py +350 -0
  52. setta/database/db/sections/save.py +204 -0
  53. setta/database/db/sections/utils.py +13 -0
  54. setta/database/db/uiTypes/__init__.py +0 -0
  55. setta/database/db/uiTypes/copy.py +33 -0
  56. setta/database/db/uiTypes/load.py +51 -0
  57. setta/database/db/uiTypes/save.py +99 -0
  58. setta/database/db/uiTypes/utils.py +27 -0
  59. setta/database/db_init.py +36 -0
  60. setta/database/db_objs.py +102 -0
  61. setta/database/db_path.py +8 -0
  62. setta/database/export_db/__init__.py +0 -0
  63. setta/database/export_db/export_db.py +43 -0
  64. setta/database/export_db/export_raw.py +53 -0
  65. setta/database/export_db/export_readable.py +242 -0
  66. setta/database/export_db/utils.py +16 -0
  67. setta/database/import_db.py +28 -0
  68. setta/database/seed.py +41 -0
  69. setta/database/settings_file.py +118 -0
  70. setta/database/utils.py +32 -0
  71. setta/lsp/__init__.py +0 -0
  72. setta/lsp/file_watcher.py +113 -0
  73. setta/lsp/reader.py +184 -0
  74. setta/lsp/reader_fns/__init__.py +0 -0
  75. setta/lsp/reader_fns/completion.py +84 -0
  76. setta/lsp/reader_fns/definition.py +2 -0
  77. setta/lsp/reader_fns/diagnostics.py +99 -0
  78. setta/lsp/reader_fns/documentHighlight.py +25 -0
  79. setta/lsp/reader_fns/references.py +34 -0
  80. setta/lsp/reader_fns/signatureHelp.py +99 -0
  81. setta/lsp/server.py +150 -0
  82. setta/lsp/utils.py +60 -0
  83. setta/lsp/writer.py +306 -0
  84. setta/routers/__init__.py +11 -0
  85. setta/routers/artifact.py +105 -0
  86. setta/routers/code_info.py +32 -0
  87. setta/routers/dependencies.py +49 -0
  88. setta/routers/in_memory_fn_stdout_websocket.py +21 -0
  89. setta/routers/interactive.py +119 -0
  90. setta/routers/lsp.py +14 -0
  91. setta/routers/projects.py +188 -0
  92. setta/routers/reference_renaming.py +111 -0
  93. setta/routers/sections.py +174 -0
  94. setta/routers/settings.py +40 -0
  95. setta/routers/terminals.py +83 -0
  96. setta/routers/websocket.py +36 -0
  97. setta/server.py +141 -0
  98. setta/start.py +112 -0
  99. setta/static/constants/BaseUITypes.json +153 -0
  100. setta/static/constants/Settings.json +113 -0
  101. setta/static/constants/constants.json +117 -0
  102. setta/static/constants/db_init.sql +249 -0
  103. setta/static/constants/defaultValues.json +125 -0
  104. setta/static/constants/settingsProject.json +276 -0
  105. setta/static/frontend/android-chrome-192x192.png +0 -0
  106. setta/static/frontend/android-chrome-512x512.png +0 -0
  107. setta/static/frontend/apple-touch-icon.png +0 -0
  108. setta/static/frontend/assets/KaTeX_AMS-Regular-0cdd387c.woff2 +0 -0
  109. setta/static/frontend/assets/KaTeX_AMS-Regular-30da91e8.woff +0 -0
  110. setta/static/frontend/assets/KaTeX_AMS-Regular-68534840.ttf +0 -0
  111. setta/static/frontend/assets/KaTeX_Caligraphic-Bold-07d8e303.ttf +0 -0
  112. setta/static/frontend/assets/KaTeX_Caligraphic-Bold-1ae6bd74.woff +0 -0
  113. setta/static/frontend/assets/KaTeX_Caligraphic-Bold-de7701e4.woff2 +0 -0
  114. setta/static/frontend/assets/KaTeX_Caligraphic-Regular-3398dd02.woff +0 -0
  115. setta/static/frontend/assets/KaTeX_Caligraphic-Regular-5d53e70a.woff2 +0 -0
  116. setta/static/frontend/assets/KaTeX_Caligraphic-Regular-ed0b7437.ttf +0 -0
  117. setta/static/frontend/assets/KaTeX_Fraktur-Bold-74444efd.woff2 +0 -0
  118. setta/static/frontend/assets/KaTeX_Fraktur-Bold-9163df9c.ttf +0 -0
  119. setta/static/frontend/assets/KaTeX_Fraktur-Bold-9be7ceb8.woff +0 -0
  120. setta/static/frontend/assets/KaTeX_Fraktur-Regular-1e6f9579.ttf +0 -0
  121. setta/static/frontend/assets/KaTeX_Fraktur-Regular-51814d27.woff2 +0 -0
  122. setta/static/frontend/assets/KaTeX_Fraktur-Regular-5e28753b.woff +0 -0
  123. setta/static/frontend/assets/KaTeX_Main-Bold-0f60d1b8.woff2 +0 -0
  124. setta/static/frontend/assets/KaTeX_Main-Bold-138ac28d.ttf +0 -0
  125. setta/static/frontend/assets/KaTeX_Main-Bold-c76c5d69.woff +0 -0
  126. setta/static/frontend/assets/KaTeX_Main-BoldItalic-70ee1f64.ttf +0 -0
  127. setta/static/frontend/assets/KaTeX_Main-BoldItalic-99cd42a3.woff2 +0 -0
  128. setta/static/frontend/assets/KaTeX_Main-BoldItalic-a6f7ec0d.woff +0 -0
  129. setta/static/frontend/assets/KaTeX_Main-Italic-0d85ae7c.ttf +0 -0
  130. setta/static/frontend/assets/KaTeX_Main-Italic-97479ca6.woff2 +0 -0
  131. setta/static/frontend/assets/KaTeX_Main-Italic-f1d6ef86.woff +0 -0
  132. setta/static/frontend/assets/KaTeX_Main-Regular-c2342cd8.woff2 +0 -0
  133. setta/static/frontend/assets/KaTeX_Main-Regular-c6368d87.woff +0 -0
  134. setta/static/frontend/assets/KaTeX_Main-Regular-d0332f52.ttf +0 -0
  135. setta/static/frontend/assets/KaTeX_Math-BoldItalic-850c0af5.woff +0 -0
  136. setta/static/frontend/assets/KaTeX_Math-BoldItalic-dc47344d.woff2 +0 -0
  137. setta/static/frontend/assets/KaTeX_Math-BoldItalic-f9377ab0.ttf +0 -0
  138. setta/static/frontend/assets/KaTeX_Math-Italic-08ce98e5.ttf +0 -0
  139. setta/static/frontend/assets/KaTeX_Math-Italic-7af58c5e.woff2 +0 -0
  140. setta/static/frontend/assets/KaTeX_Math-Italic-8a8d2445.woff +0 -0
  141. setta/static/frontend/assets/KaTeX_SansSerif-Bold-1ece03f7.ttf +0 -0
  142. setta/static/frontend/assets/KaTeX_SansSerif-Bold-e99ae511.woff2 +0 -0
  143. setta/static/frontend/assets/KaTeX_SansSerif-Bold-ece03cfd.woff +0 -0
  144. setta/static/frontend/assets/KaTeX_SansSerif-Italic-00b26ac8.woff2 +0 -0
  145. setta/static/frontend/assets/KaTeX_SansSerif-Italic-3931dd81.ttf +0 -0
  146. setta/static/frontend/assets/KaTeX_SansSerif-Italic-91ee6750.woff +0 -0
  147. setta/static/frontend/assets/KaTeX_SansSerif-Regular-11e4dc8a.woff +0 -0
  148. setta/static/frontend/assets/KaTeX_SansSerif-Regular-68e8c73e.woff2 +0 -0
  149. setta/static/frontend/assets/KaTeX_SansSerif-Regular-f36ea897.ttf +0 -0
  150. setta/static/frontend/assets/KaTeX_Script-Regular-036d4e95.woff2 +0 -0
  151. setta/static/frontend/assets/KaTeX_Script-Regular-1c67f068.ttf +0 -0
  152. setta/static/frontend/assets/KaTeX_Script-Regular-d96cdf2b.woff +0 -0
  153. setta/static/frontend/assets/KaTeX_Size1-Regular-6b47c401.woff2 +0 -0
  154. setta/static/frontend/assets/KaTeX_Size1-Regular-95b6d2f1.ttf +0 -0
  155. setta/static/frontend/assets/KaTeX_Size1-Regular-c943cc98.woff +0 -0
  156. setta/static/frontend/assets/KaTeX_Size2-Regular-2014c523.woff +0 -0
  157. setta/static/frontend/assets/KaTeX_Size2-Regular-a6b2099f.ttf +0 -0
  158. setta/static/frontend/assets/KaTeX_Size2-Regular-d04c5421.woff2 +0 -0
  159. setta/static/frontend/assets/KaTeX_Size3-Regular-500e04d5.ttf +0 -0
  160. setta/static/frontend/assets/KaTeX_Size3-Regular-6ab6b62e.woff +0 -0
  161. setta/static/frontend/assets/KaTeX_Size4-Regular-99f9c675.woff +0 -0
  162. setta/static/frontend/assets/KaTeX_Size4-Regular-a4af7d41.woff2 +0 -0
  163. setta/static/frontend/assets/KaTeX_Size4-Regular-c647367d.ttf +0 -0
  164. setta/static/frontend/assets/KaTeX_Typewriter-Regular-71d517d6.woff2 +0 -0
  165. setta/static/frontend/assets/KaTeX_Typewriter-Regular-e14fed02.woff +0 -0
  166. setta/static/frontend/assets/KaTeX_Typewriter-Regular-f01f3e87.ttf +0 -0
  167. setta/static/frontend/assets/cormorant-garamond-all-700-italic-c9b58582.woff +0 -0
  168. setta/static/frontend/assets/cormorant-garamond-cyrillic-700-italic-9101ad5f.woff2 +0 -0
  169. setta/static/frontend/assets/cormorant-garamond-cyrillic-ext-700-italic-950de0d6.woff2 +0 -0
  170. setta/static/frontend/assets/cormorant-garamond-latin-700-italic-0bc53e12.woff2 +0 -0
  171. setta/static/frontend/assets/cormorant-garamond-latin-ext-700-italic-525738e0.woff2 +0 -0
  172. setta/static/frontend/assets/cormorant-garamond-vietnamese-700-italic-99563037.woff2 +0 -0
  173. setta/static/frontend/assets/erase-5e0448ea.svg +15 -0
  174. setta/static/frontend/assets/index-1d4b4ecf.css +32 -0
  175. setta/static/frontend/assets/index-ee99dc72.js +678 -0
  176. setta/static/frontend/assets/inter-all-400-normal-054f12d0.woff +0 -0
  177. setta/static/frontend/assets/inter-all-600-normal-c03769e5.woff +0 -0
  178. setta/static/frontend/assets/inter-all-800-normal-15dc6e4b.woff +0 -0
  179. setta/static/frontend/assets/inter-cyrillic-400-normal-a4eee61a.woff2 +0 -0
  180. setta/static/frontend/assets/inter-cyrillic-600-normal-8b14f703.woff2 +0 -0
  181. setta/static/frontend/assets/inter-cyrillic-800-normal-e706eaaa.woff2 +0 -0
  182. setta/static/frontend/assets/inter-cyrillic-ext-400-normal-70047a3b.woff2 +0 -0
  183. setta/static/frontend/assets/inter-cyrillic-ext-600-normal-d4ab9bc4.woff2 +0 -0
  184. setta/static/frontend/assets/inter-cyrillic-ext-800-normal-eae7515a.woff2 +0 -0
  185. setta/static/frontend/assets/inter-greek-400-normal-381ea30d.woff2 +0 -0
  186. setta/static/frontend/assets/inter-greek-600-normal-601f93a2.woff2 +0 -0
  187. setta/static/frontend/assets/inter-greek-800-normal-7af4fb64.woff2 +0 -0
  188. setta/static/frontend/assets/inter-greek-ext-400-normal-27027b17.woff2 +0 -0
  189. setta/static/frontend/assets/inter-greek-ext-600-normal-f2ddf9de.woff2 +0 -0
  190. setta/static/frontend/assets/inter-greek-ext-800-normal-4cb6189e.woff2 +0 -0
  191. setta/static/frontend/assets/inter-latin-400-normal-d56fec21.woff2 +0 -0
  192. setta/static/frontend/assets/inter-latin-600-normal-ff769fa6.woff2 +0 -0
  193. setta/static/frontend/assets/inter-latin-800-normal-5eea1309.woff2 +0 -0
  194. setta/static/frontend/assets/inter-latin-ext-400-normal-bb698d85.woff2 +0 -0
  195. setta/static/frontend/assets/inter-latin-ext-600-normal-ca4808f9.woff2 +0 -0
  196. setta/static/frontend/assets/inter-latin-ext-800-normal-ebdacc0f.woff2 +0 -0
  197. setta/static/frontend/assets/logo/logo.svg +8 -0
  198. setta/static/frontend/assets/pen-455d7d8a.svg +19 -0
  199. setta/static/frontend/assets/source-code-pro-all-500-normal-6bdaa03b.woff +0 -0
  200. setta/static/frontend/assets/source-code-pro-cyrillic-500-normal-288a0d68.woff2 +0 -0
  201. setta/static/frontend/assets/source-code-pro-cyrillic-ext-500-normal-b110a13b.woff2 +0 -0
  202. setta/static/frontend/assets/source-code-pro-greek-500-normal-04328acb.woff2 +0 -0
  203. setta/static/frontend/assets/source-code-pro-latin-500-normal-06edef1e.woff2 +0 -0
  204. setta/static/frontend/assets/source-code-pro-latin-ext-500-normal-6dc60d5e.woff2 +0 -0
  205. setta/static/frontend/assets/web-vitals-44a8e082.js +1 -0
  206. setta/static/frontend/assets/work-sans-all-400-normal-38034a3c.woff +0 -0
  207. setta/static/frontend/assets/work-sans-all-500-normal-550d64e5.woff +0 -0
  208. setta/static/frontend/assets/work-sans-all-600-normal-ccf14060.woff +0 -0
  209. setta/static/frontend/assets/work-sans-all-700-normal-494c2971.woff +0 -0
  210. setta/static/frontend/assets/work-sans-latin-400-normal-36735bc1.woff2 +0 -0
  211. setta/static/frontend/assets/work-sans-latin-500-normal-3790bfda.woff2 +0 -0
  212. setta/static/frontend/assets/work-sans-latin-600-normal-5fba494e.woff2 +0 -0
  213. setta/static/frontend/assets/work-sans-latin-700-normal-a5033d0a.woff2 +0 -0
  214. setta/static/frontend/assets/work-sans-latin-ext-400-normal-c20f571a.woff2 +0 -0
  215. setta/static/frontend/assets/work-sans-latin-ext-500-normal-0f5ac96c.woff2 +0 -0
  216. setta/static/frontend/assets/work-sans-latin-ext-600-normal-97a237d1.woff2 +0 -0
  217. setta/static/frontend/assets/work-sans-latin-ext-700-normal-103e112c.woff2 +0 -0
  218. setta/static/frontend/browserconfig.xml +9 -0
  219. setta/static/frontend/favicon-16x16.png +0 -0
  220. setta/static/frontend/favicon-32x32.png +0 -0
  221. setta/static/frontend/favicon.ico +0 -0
  222. setta/static/frontend/index.html +30 -0
  223. setta/static/frontend/manifest.json +25 -0
  224. setta/static/frontend/mstile-144x144.png +0 -0
  225. setta/static/frontend/mstile-150x150.png +0 -0
  226. setta/static/frontend/mstile-310x150.png +0 -0
  227. setta/static/frontend/mstile-310x310.png +0 -0
  228. setta/static/frontend/mstile-70x70.png +0 -0
  229. setta/static/frontend/robots.txt +3 -0
  230. setta/static/frontend/safari-pinned-tab.svg +18 -0
  231. setta/static/frontend/site.webmanifest +19 -0
  232. setta/static/seed/.DS_Store +0 -0
  233. setta/static/seed/examples/.DS_Store +0 -0
  234. setta/tasks/__init__.py +0 -0
  235. setta/tasks/fns/__init__.py +9 -0
  236. setta/tasks/fns/codeAreaAutocomplete.py +209 -0
  237. setta/tasks/fns/codeAreaFindTemplateVars.py +128 -0
  238. setta/tasks/fns/codeAreaInitializeCode.py +98 -0
  239. setta/tasks/fns/findEVRefs.py +236 -0
  240. setta/tasks/fns/parametersRequest.py +71 -0
  241. setta/tasks/fns/textFieldAutocomplete.py +210 -0
  242. setta/tasks/fns/textFieldInitializeCode.py +99 -0
  243. setta/tasks/fns/typeCheck.py +40 -0
  244. setta/tasks/fns/utils.py +134 -0
  245. setta/tasks/task_runner.py +29 -0
  246. setta/tasks/tasks.py +152 -0
  247. setta/tasks/utils.py +178 -0
  248. setta/terminals/__init__.py +0 -0
  249. setta/terminals/terminals.py +242 -0
  250. setta/terminals/utils.py +37 -0
  251. setta/utils/__init__.py +0 -0
  252. setta/utils/constants.py +148 -0
  253. setta/utils/generate_memorable_string.py +431 -0
  254. setta/utils/generate_new_filename.py +80 -0
  255. setta/utils/section_contents.py +133 -0
  256. setta/utils/utils.py +271 -0
  257. setta/utils/websocket_manager.py +91 -0
  258. setta-0.0.2.dev0.dist-info/LICENSE +201 -0
  259. setta-0.0.2.dev0.dist-info/METADATA +24 -0
  260. setta-0.0.2.dev0.dist-info/RECORD +263 -0
  261. {setta-0.0.1.dev0.dist-info → setta-0.0.2.dev0.dist-info}/WHEEL +1 -1
  262. setta-0.0.2.dev0.dist-info/entry_points.txt +2 -0
  263. setta-0.0.1.dev0.dist-info/METADATA +0 -18
  264. setta-0.0.1.dev0.dist-info/RECORD +0 -5
  265. {setta-0.0.1.dev0.dist-info → setta-0.0.2.dev0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,242 @@
1
+ import asyncio
2
+ import errno
3
+ import json
4
+ import logging
5
+ import platform
6
+ import select
7
+ import time
8
+ import traceback
9
+ from asyncio import CancelledError
10
+ from collections import defaultdict, deque
11
+
12
+ import psutil
13
+ from fastapi import WebSocketDisconnect
14
+ from websockets.exceptions import ConnectionClosedOK
15
+
16
+ from setta.code_gen.create_runnable_scripts import runCode
17
+ from setta.utils.constants import USER_SETTINGS, C
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ SETTA_CLEAR_CMD = "SETTA_CLEAR_CMD"
23
+ IS_WINDOWS = platform.system() == "Windows"
24
+ IS_MACOS = platform.system() == "Darwin"
25
+
26
+
27
+ if IS_WINDOWS:
28
+ from winpty import PtyProcess
29
+
30
+ from .utils import windows_has_child_processes as has_child_processes
31
+
32
+ else:
33
+ from ptyprocess import PtyProcessUnicode as PtyProcess
34
+
35
+ from .utils import linux_has_child_processes as has_child_processes
36
+
37
+
38
+ def is_command_running_in_pty(pid):
39
+ try:
40
+ return has_child_processes(pid)
41
+ except psutil.NoSuchProcess:
42
+ return False
43
+
44
+
45
+ def get_terminal_shell():
46
+ if USER_SETTINGS["backend"]["defaultTerminalShell"]:
47
+ return USER_SETTINGS["backend"]["defaultTerminalShell"]
48
+ if IS_WINDOWS:
49
+ return "bash.exe"
50
+ if IS_MACOS:
51
+ return "zsh"
52
+ return "bash"
53
+
54
+
55
+ class TerminalWebsockets:
56
+ def __init__(self):
57
+ self.section_to_socket_ids = defaultdict(set)
58
+ self.sockets = {}
59
+ self.PTY_PIDS = {}
60
+
61
+ def new_terminal(self, projectConfigId, sectionId, isTemporary):
62
+ if sectionId not in self.PTY_PIDS:
63
+ terminal_shell = get_terminal_shell()
64
+ if not IS_WINDOWS:
65
+ terminal_shell = [terminal_shell]
66
+ pty_process = PtyProcess.spawn(terminal_shell)
67
+ self.PTY_PIDS[sectionId] = {
68
+ "pid": pty_process.pid,
69
+ "start": time.time(),
70
+ "projectConfigId": projectConfigId,
71
+ "process": pty_process,
72
+ "history": deque(maxlen=1000),
73
+ "wasJustResized": False,
74
+ "terminalPromptIsReady": asyncio.Event(),
75
+ "isTemporary": isTemporary,
76
+ }
77
+ pty_info = self.PTY_PIDS[sectionId]
78
+ if (
79
+ IS_WINDOWS
80
+ or not USER_SETTINGS["backend"]["clearTerminalBeforeMarkingAsReady"]
81
+ ):
82
+ pty_info["terminalPromptIsReady"].set()
83
+
84
+ logger.debug(f"created new pty_process {sectionId}")
85
+ if not pty_info["terminalPromptIsReady"].is_set():
86
+ pty_process.write(
87
+ f"alias {SETTA_CLEAR_CMD}='clear'\n{SETTA_CLEAR_CMD}\n"
88
+ )
89
+ return True
90
+ return False
91
+
92
+ async def connect(self, websocket, sectionId, id):
93
+ await websocket.accept()
94
+ self.sockets[id] = {"ws": websocket, "sentReadyMsg": False}
95
+ self.section_to_socket_ids[sectionId].add(id)
96
+ await self.PTY_PIDS[sectionId]["terminalPromptIsReady"].wait()
97
+ if not self.sockets[id]["sentReadyMsg"]:
98
+ await websocket.send_text(C.SETTA_TERMINAL_READY)
99
+ self.sockets[id]["sentReadyMsg"] = True
100
+ await websocket.send_text("".join(self.PTY_PIDS[sectionId]["history"]))
101
+
102
+ def disconnect(self, sectionId, id):
103
+ logger.debug(f"disconnecting {id}")
104
+ try:
105
+ del self.sockets[id]
106
+ except KeyError:
107
+ pass
108
+ self.section_to_socket_ids[sectionId].discard(id)
109
+
110
+ async def delete_terminal(self, sectionId):
111
+ logger.debug(f"delete terminal {sectionId}")
112
+ if sectionId in self.PTY_PIDS:
113
+ try:
114
+ await asyncio.to_thread(
115
+ self.PTY_PIDS[sectionId]["process"].terminate, force=True
116
+ )
117
+ del self.PTY_PIDS[sectionId]
118
+ except KeyError:
119
+ pass
120
+
121
+ # make copy to avoid set size changing while iterating
122
+ to_disconnect = set(self.section_to_socket_ids[sectionId])
123
+ for id in to_disconnect:
124
+ self.disconnect(sectionId, id)
125
+
126
+ async def delete_terminals(self, sectionIds):
127
+ await asyncio.gather(*(self.delete_terminal(s) for s in sectionIds))
128
+
129
+ async def delete_all_terminals(self):
130
+ await self.delete_terminals(self.PTY_PIDS.keys())
131
+
132
+ # Function to read from the terminal
133
+ async def read_from_terminal(self, sectionId):
134
+ pty_info = self.PTY_PIDS[sectionId]
135
+ pty_process = pty_info["process"]
136
+ history = pty_info["history"]
137
+ initial_buffer = ""
138
+ while True:
139
+ try:
140
+ output, _, _ = await asyncio.get_running_loop().run_in_executor(
141
+ None,
142
+ select.select,
143
+ [pty_process.fd],
144
+ [],
145
+ [],
146
+ None, # timeout of 0 makes this non-blocking
147
+ )
148
+ if not output:
149
+ continue
150
+ output = pty_process.read(1024)
151
+ if not pty_info["terminalPromptIsReady"].is_set():
152
+ initial_buffer += output
153
+ # We wait for the SETTA_CLEAR_CMD string to appear four times
154
+ # before we consider the terminal ready.
155
+ # This is just to make the terminal look less cluttered and annoying on the frontend.
156
+ if initial_buffer.count(SETTA_CLEAR_CMD) >= 4:
157
+ pty_info["terminalPromptIsReady"].set()
158
+ await self.send_output_to_sectionId(
159
+ sectionId, C.SETTA_TERMINAL_READY, setSentReadyMsg=True
160
+ )
161
+ continue
162
+ if not pty_info["wasJustResized"]:
163
+ history.append(output)
164
+ pty_info["wasJustResized"] = False
165
+ await self.send_output_to_sectionId(sectionId, output)
166
+ except (WebSocketDisconnect, CancelledError, ConnectionClosedOK):
167
+ break
168
+ except EOFError:
169
+ break
170
+ except OSError as e:
171
+ if e.errno == errno.EIO: # Input/output error
172
+ break
173
+ except Exception as e:
174
+ logger.debug(f"Exception details:\n{traceback.format_exc()}")
175
+ logger.debug(e)
176
+ logger.debug("read_from_terminal caught the exception!")
177
+
178
+ # Function to write to the terminal
179
+ async def write_to_terminal(self, websocket, lsp_writers, sectionId):
180
+ pty_info = self.PTY_PIDS[sectionId]
181
+ pty_process = pty_info["process"]
182
+ while True:
183
+ try:
184
+ input_data = await websocket.receive_text()
185
+ try:
186
+ json_val = json.loads(input_data)
187
+ except json.decoder.JSONDecodeError:
188
+ json_val = None
189
+ if isinstance(json_val, dict):
190
+ doResize = json_val["messageType"] == C.WS_TERMINAL_RESIZE
191
+ if doResize:
192
+ pty_process.setwinsize(json_val["rows"], json_val["cols"])
193
+ elif json_val["messageType"] == C.WS_RUN_CODE:
194
+ command = await runCode(json_val, lsp_writers)
195
+ pty_process.write(f"\x15{command}\n")
196
+ self.set_terminal_start_time(sectionId)
197
+ pty_info["wasJustResized"] = doResize
198
+ continue
199
+ elif input_data:
200
+ pty_process.write(input_data)
201
+ self.set_terminal_start_time(sectionId)
202
+ except (WebSocketDisconnect, CancelledError, ConnectionClosedOK):
203
+ break
204
+ except EOFError:
205
+ break
206
+ except OSError as e:
207
+ if e.errno == errno.EIO: # Input/output error
208
+ break
209
+ except Exception as e:
210
+ logger.debug(f"Exception details:\n{traceback.format_exc()}")
211
+ logger.debug(e)
212
+ logger.debug("write_to_terminal caught the exception!")
213
+
214
+ def set_terminal_start_time(self, id):
215
+ self.PTY_PIDS[id]["start"] = time.time()
216
+
217
+ def get_free_terminal(self, projectConfigId):
218
+ for k, v in self.PTY_PIDS.items():
219
+ if (
220
+ v["projectConfigId"] == projectConfigId
221
+ and not is_command_running_in_pty(v["pid"])
222
+ and time.time() - v["start"] > 1
223
+ ):
224
+ return k
225
+ return None
226
+
227
+ def get_existing_terminals(self, projectConfigId):
228
+ output = []
229
+ for k, v in self.PTY_PIDS.items():
230
+ if v["projectConfigId"] == projectConfigId:
231
+ output.append({"id": k, "isTemporary": v["isTemporary"]})
232
+ return output
233
+
234
+ async def send_output_to_sectionId(self, sectionId, output, setSentReadyMsg=False):
235
+ for wsId in self.section_to_socket_ids[sectionId]:
236
+ ws = self.sockets[wsId]["ws"]
237
+ try:
238
+ await ws.send_text(output)
239
+ if setSentReadyMsg:
240
+ self.sockets[wsId]["sentReadyMsg"] = True
241
+ except:
242
+ continue
@@ -0,0 +1,37 @@
1
+ import re
2
+ import subprocess
3
+
4
+ import psutil
5
+
6
+
7
+ def windows_has_child_processes(input_winpid):
8
+ if len(psutil.Process(input_winpid).children()) > 0:
9
+ return True
10
+
11
+ # when running in bash.exe, sometimes the bash process children
12
+ # are not visible when querying using the windows pid
13
+ # so this finds the corresponding bash pid for the input winpid
14
+ # and finds its children
15
+ output = subprocess.check_output("ps", shell=True).decode()
16
+ processes = []
17
+ bash_pid = None
18
+ pid_idx, ppid_idx, winpid_idx = None, None, None
19
+ for i, line in enumerate(output.split("\n")): # Skip the header line
20
+ columns = re.split(r"\s+", line)
21
+ if i == 0:
22
+ pid_idx = columns.index("PID")
23
+ ppid_idx = columns.index("PPID")
24
+ winpid_idx = columns.index("WINPID")
25
+ elif columns != [""]:
26
+ pid = int(columns[pid_idx])
27
+ ppid = int(columns[ppid_idx])
28
+ winpid = int(columns[winpid_idx])
29
+ processes.append({"pid": pid, "ppid": ppid, "winpid": winpid})
30
+ if winpid == input_winpid:
31
+ bash_pid = pid
32
+
33
+ return len([p for p in processes if p["ppid"] == bash_pid]) > 0
34
+
35
+
36
+ def linux_has_child_processes(pid):
37
+ return len(psutil.Process(pid).children()) > 0
File without changes
@@ -0,0 +1,148 @@
1
+ import json
2
+ import logging
3
+ from pathlib import Path
4
+
5
+ from .utils import get_absolute_path, is_dev_mode
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ CONSTANTS_FOLDER = (
10
+ Path("../../../constants") if is_dev_mode() else Path("../static/constants")
11
+ )
12
+ SEED_FOLDER = Path("../../../seed") if is_dev_mode() else Path("../static/seed")
13
+ CODE_FOLDER = "setta_code"
14
+ DB_BACKUP_FOLDER = ".setta_backups"
15
+ CODE_FOLDER_ENV_VARIABLE = "SETTA_CODE_FOLDER"
16
+ HOST_ENV_VARIABLE = "SETTA_HOST"
17
+ PORT_ENV_VARIABLE = "SETTA_PORT"
18
+
19
+
20
+ class Constants:
21
+ def __init__(self):
22
+ self._initialized = False
23
+
24
+ def _ensure_initialized(self):
25
+ if not self._initialized:
26
+ load_constants()
27
+ self._initialized = True
28
+
29
+ def __getattr__(self, name):
30
+ if name == "_initialized":
31
+ return object.__getattribute__(self, name)
32
+ self._ensure_initialized()
33
+ return object.__getattribute__(self, name)
34
+
35
+ @property
36
+ def FRONTEND_ORIGINS(self):
37
+ self._ensure_initialized()
38
+ if is_dev_mode():
39
+ output = [f"http://{self.HOST}:{self.DEV_MODE_FRONTEND_PORT}"]
40
+ else:
41
+ output = [self.BACKEND]
42
+ if self.HOST == "127.0.0.1":
43
+ output.append(output[0].replace("127.0.0.1", "localhost"))
44
+ return output
45
+
46
+ @property
47
+ def BACKEND(self):
48
+ self._ensure_initialized()
49
+ return f"http://{self.HOST}:{self.PORT}"
50
+
51
+ @property
52
+ def WEBSOCKET(self):
53
+ self._ensure_initialized()
54
+ return f"ws://{self.HOST}:{self.PORT}{self.ROUTE_PREFIX}{self.ROUTE_WEBSOCKET_MANAGER}"
55
+
56
+
57
+ C = Constants()
58
+ USER_SETTINGS = {}
59
+ BASE_UI_TYPES = {}
60
+ BASE_UI_TYPE_IDS = {}
61
+ DEFAULT_VALUES = {}
62
+
63
+
64
+ def set_constants(**kwargs):
65
+ for k, v in kwargs.items():
66
+ setattr(C, k.upper(), v)
67
+
68
+
69
+ def load_constants():
70
+ logger.debug("Loading constants")
71
+ with open(
72
+ get_absolute_path(__file__, CONSTANTS_FOLDER / "constants.json"), "r"
73
+ ) as f:
74
+ set_constants(**json.load(f))
75
+
76
+ with open(
77
+ get_absolute_path(__file__, CONSTANTS_FOLDER / "BaseUITypes.json"), "r"
78
+ ) as f:
79
+ BASE_UI_TYPES.update(json.load(f))
80
+ for k, v in BASE_UI_TYPES.items():
81
+ BASE_UI_TYPE_IDS[v["type"]] = k
82
+
83
+ with open(
84
+ get_absolute_path(__file__, CONSTANTS_FOLDER / "defaultValues.json"), "r"
85
+ ) as f:
86
+ DEFAULT_VALUES.update(json.load(f))
87
+
88
+
89
+ def is_from_json_source(id):
90
+ return id and id.startswith(C.JSON_SOURCE_PREFIX)
91
+
92
+
93
+ CODE_INFO_TABLE_DATA_JSON_FIELDS = set(
94
+ (
95
+ "editable",
96
+ "rcType",
97
+ "defaultVal",
98
+ "description",
99
+ "positionalOnly",
100
+ "isPinned",
101
+ "isFrozen",
102
+ )
103
+ )
104
+
105
+ SECTION_TABLE_DATA_JSON_FIELDS = set(
106
+ (
107
+ "social",
108
+ "codeLanguage",
109
+ "configLanguage",
110
+ "runInMemory",
111
+ "isFrozen",
112
+ "jsonSource",
113
+ "hideUnpinnedParams",
114
+ "displayMode",
115
+ "canvasSettings",
116
+ "chartSettings",
117
+ "renderMarkdown",
118
+ "paramFilter",
119
+ "columnWidth",
120
+ "renderedValue",
121
+ "isReadOnlyTerminal",
122
+ )
123
+ )
124
+
125
+ SECTION_CONFIG_TABLE_DATA_JSON_FIELDS = set(
126
+ (
127
+ "size",
128
+ "isHorizontalOrientation",
129
+ "pinnedAreaHeight",
130
+ "isMinimized",
131
+ "positionAndSizeLocked",
132
+ )
133
+ )
134
+
135
+ SECTION_VARIANT_ID_TABLE_DATA_JSON_FIELDS = set(["code", "description", "isFrozen"])
136
+
137
+ SECTION_VARIANT_EV_TABLE_DATA_JSON_FIELDS = set(["value"])
138
+
139
+
140
+ UI_TYPE_TABLE_DATA_JSON_FIELDS = set(
141
+ [
142
+ "name",
143
+ "presetType",
144
+ "config",
145
+ ]
146
+ )
147
+
148
+ PROJECT_CONFIG_TABLE_DATA_JSON_FIELDS = set(["viewport", "previewImgColor"])