setta 0.0.1__py3-none-any.whl → 0.0.2__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.dist-info/LICENSE +201 -0
  259. setta-0.0.2.dist-info/METADATA +24 -0
  260. setta-0.0.2.dist-info/RECORD +263 -0
  261. {setta-0.0.1.dist-info → setta-0.0.2.dist-info}/WHEEL +1 -1
  262. setta-0.0.2.dist-info/entry_points.txt +2 -0
  263. setta-0.0.1.dist-info/METADATA +0 -18
  264. setta-0.0.1.dist-info/RECORD +0 -5
  265. {setta-0.0.1.dist-info → setta-0.0.2.dist-info}/top_level.txt +0 -0
setta/database/seed.py ADDED
@@ -0,0 +1,41 @@
1
+ import glob
2
+ import json
3
+
4
+ from setta.database.db.projects.utils import add_defaults_to_project
5
+ from setta.utils.constants import BASE_UI_TYPES, SEED_FOLDER
6
+ from setta.utils.utils import get_absolute_path
7
+
8
+ from .db.projects.save import save_project_details
9
+ from .db.uiTypes.save import save_ui_types
10
+
11
+
12
+ def seed_base_ui_types(db):
13
+ save_ui_types(db, BASE_UI_TYPES)
14
+
15
+
16
+ def seed_examples(db):
17
+ example_jsons = glob.glob(
18
+ str(get_absolute_path(__file__, SEED_FOLDER / "examples/**/*.json"))
19
+ )
20
+ for filepath in example_jsons:
21
+ # if (
22
+ # "reviews" not in filepath
23
+ # and "medical" not in filepath
24
+ # and "financial" not in filepath
25
+ # ):
26
+ # continue
27
+ # if "hf" not in filepath:
28
+ # continue
29
+ # if "img_to_img" not in filepath:
30
+ # continue
31
+ with open(filepath, "r") as f:
32
+ data = json.load(f)
33
+ add_defaults_to_project(data) # json files don't have all the defaults
34
+ save_project_details(db, data)
35
+
36
+
37
+ def seed(db, with_examples=False, with_base_ui_types=False):
38
+ if with_base_ui_types:
39
+ seed_base_ui_types(db)
40
+ if with_examples:
41
+ seed_examples(db)
@@ -0,0 +1,118 @@
1
+ import json
2
+ import logging
3
+ import os
4
+
5
+ from setta.code_gen.export_selected import get_selected_section_variant
6
+ from setta.database.db.projects.utils import (
7
+ add_defaults_to_project_and_load_json_sources,
8
+ filter_data_for_json_export,
9
+ )
10
+ from setta.database.db.sections.jsonSource import (
11
+ remove_json_source_data,
12
+ save_json_source_data,
13
+ )
14
+ from setta.utils.constants import CONSTANTS_FOLDER, USER_SETTINGS
15
+ from setta.utils.utils import get_absolute_path, save_json_to_file
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class SettingsFile:
21
+ def __init__(self):
22
+ self.meta_settings_file = MetaSettingsFile()
23
+ self.load_settings()
24
+
25
+ def save_settings(self, settings):
26
+ logger.debug("Saving settings")
27
+ paths = self.meta_settings_file.get_settings_paths()
28
+ to_be_saved = {}
29
+ for settings_slice, path in paths.items():
30
+ if path not in to_be_saved:
31
+ to_be_saved[path] = {}
32
+ to_be_saved[path].update({settings_slice: settings[settings_slice]})
33
+
34
+ for filename, data in to_be_saved.items():
35
+ save_json_to_file(filename, data)
36
+
37
+ USER_SETTINGS.update(settings)
38
+
39
+ def load_settings(self):
40
+ logger.debug("Loading settings")
41
+ paths = self.meta_settings_file.get_settings_paths()
42
+ output = {}
43
+ for settings_slice, path in paths.items():
44
+ with open(path, "r") as f:
45
+ output[settings_slice] = json.load(f)[settings_slice]
46
+
47
+ USER_SETTINGS.update(output)
48
+ return output
49
+
50
+ def load_settings_project(self):
51
+ return self.meta_settings_file.load_settings_project()
52
+
53
+ def save_settings_project(self, p):
54
+ self.meta_settings_file.save_settings_project(p)
55
+ return self.load_settings()
56
+
57
+
58
+ class MetaSettingsFile:
59
+ def __init__(self):
60
+ self.path_seed_settings = get_absolute_path(
61
+ __file__, CONSTANTS_FOLDER / "Settings.json"
62
+ )
63
+ self.path_seed_meta_settings = get_absolute_path(
64
+ __file__, CONSTANTS_FOLDER / "settingsProject.json"
65
+ )
66
+ self.path_default_settings = "setta-settings.json"
67
+ self.path_meta_settings = "setta-meta-settings.json"
68
+ self.load_seed_files()
69
+
70
+ def get_settings_paths(self):
71
+ settings_slice_to_path = {}
72
+ p = self.load_meta_settings()
73
+ for k in self.obj_seed_settings.keys():
74
+ path = self.find_path_for_settings_slice(p, k)
75
+ if not path:
76
+ self.seed_settings(self.path_default_settings)
77
+ elif not os.path.exists(path):
78
+ self.seed_settings(path)
79
+ settings_slice_to_path[k] = path
80
+ return settings_slice_to_path
81
+
82
+ def find_path_for_settings_slice(self, p, slice):
83
+ for sectionId, section in p["sections"].items():
84
+ if section["jsonSourceKeys"] == [slice]:
85
+ variant = get_selected_section_variant(p, sectionId)
86
+ return variant["name"]
87
+ return None
88
+
89
+ def seed_settings(self, path):
90
+ if not os.path.exists(path):
91
+ save_json_to_file(path, self.obj_seed_settings)
92
+
93
+ def seed_meta_settings(self):
94
+ if not os.path.exists(self.path_meta_settings):
95
+ save_json_to_file(self.path_meta_settings, self.obj_seed_meta_settings)
96
+
97
+ def load_meta_settings(self):
98
+ logger.debug("Loading meta settings")
99
+ self.seed_meta_settings()
100
+ with open(self.path_meta_settings, "r") as f:
101
+ return json.load(f)
102
+
103
+ def load_settings_project(self):
104
+ p = self.load_meta_settings()
105
+ add_defaults_to_project_and_load_json_sources(p)
106
+ return p
107
+
108
+ def load_seed_files(self):
109
+ with open(self.path_seed_settings, "r") as f:
110
+ self.obj_seed_settings = json.load(f)
111
+ with open(self.path_seed_meta_settings, "r") as f:
112
+ self.obj_seed_meta_settings = json.load(f)
113
+
114
+ def save_settings_project(self, p):
115
+ save_json_source_data(p)
116
+ remove_json_source_data(p, keepCodeInfoThatHaveUITypes=False)
117
+ filter_data_for_json_export(p)
118
+ save_json_to_file(self.path_meta_settings, p)
@@ -0,0 +1,32 @@
1
+ import copy
2
+ from uuid import uuid4
3
+
4
+
5
+ def create_new_id():
6
+ return str(uuid4())
7
+
8
+
9
+ def maybe_new_id(x):
10
+ return x if x else create_new_id()
11
+
12
+
13
+ def rename_keys(x, to_rename):
14
+ output = copy.deepcopy(x)
15
+ for old_key in to_rename.keys():
16
+ new_key = to_rename[old_key]
17
+ if old_key in output and new_key != old_key:
18
+ output[new_key] = output[old_key]
19
+ del output[old_key]
20
+ return output
21
+
22
+
23
+ def create_id_map(old_ids):
24
+ return dict((x, create_new_id()) for x in old_ids)
25
+
26
+
27
+ def remap_ids(x, old_ids=None):
28
+ if old_ids is None:
29
+ old_ids = list(x.keys())
30
+ id_map = create_id_map(old_ids)
31
+ new_obj = rename_keys(x, id_map)
32
+ return new_obj, id_map
setta/lsp/__init__.py ADDED
File without changes
@@ -0,0 +1,113 @@
1
+ import asyncio
2
+ import os
3
+ import site
4
+ from pathlib import Path
5
+ from typing import Set
6
+
7
+ from watchdog.events import FileSystemEvent, FileSystemEventHandler
8
+ from watchdog.observers import Observer
9
+
10
+
11
+ class LSPFileWatcher:
12
+ def __init__(self, notify_callback):
13
+ """
14
+ Initialize the file watcher.
15
+
16
+ Args:
17
+ notify_callback: Callback function that sends notifications to the LSP server.
18
+ Should accept FileSystemEvent as parameter.
19
+ """
20
+ self.observer = Observer()
21
+ self.watched_paths: Set[str] = set()
22
+ self.handler = LSPEventHandler(notify_callback, asyncio.get_event_loop())
23
+
24
+ def add_workspace_folder(self, path: str) -> None:
25
+ """
26
+ Add a workspace folder to watch.
27
+
28
+ Args:
29
+ path: Path to the workspace folder
30
+ """
31
+ if not os.path.exists(path):
32
+ raise ValueError(f"Path does not exist: {path}")
33
+
34
+ absolute_path = os.path.abspath(path)
35
+ if absolute_path not in self.watched_paths:
36
+ self.watched_paths.add(absolute_path)
37
+ self.observer.schedule(self.handler, absolute_path, recursive=True)
38
+
39
+ def add_python_site_packages(self) -> None:
40
+ """Add Python site-packages directories to watched paths."""
41
+ for path in site.getsitepackages():
42
+ try:
43
+ self.add_workspace_folder(path)
44
+ except ValueError:
45
+ continue # Skip if path doesn't exist
46
+
47
+ def start(self) -> None:
48
+ """Start the file watcher."""
49
+ self.observer.start()
50
+
51
+ def stop(self) -> None:
52
+ """Stop the file watcher."""
53
+ self.observer.stop()
54
+ self.observer.join()
55
+
56
+ def is_watching(self, path: str) -> bool:
57
+ """
58
+ Check if a path is being watched.
59
+
60
+ Args:
61
+ path: Path to check
62
+
63
+ Returns:
64
+ bool: True if the path is being watched
65
+ """
66
+ absolute_path = os.path.abspath(path)
67
+ return any(
68
+ absolute_path.startswith(watched_path)
69
+ for watched_path in self.watched_paths
70
+ )
71
+
72
+
73
+ class LSPEventHandler(FileSystemEventHandler):
74
+ def __init__(self, callback, loop):
75
+ self.callback = callback
76
+ self.loop = loop
77
+
78
+ def on_any_event(self, event: FileSystemEvent):
79
+ if event.is_directory:
80
+ return
81
+
82
+ changes = [
83
+ {
84
+ "uri": self._path_to_uri(event.src_path),
85
+ "type": self._get_change_type(event),
86
+ }
87
+ ]
88
+
89
+ if asyncio.iscoroutinefunction(self.callback):
90
+ self.loop.call_soon_threadsafe(
91
+ lambda: self.loop.create_task(self.callback(changes))
92
+ )
93
+ else:
94
+ self.callback(changes)
95
+
96
+ def _path_to_uri(self, path: str) -> str:
97
+ """Convert file path to URI format."""
98
+ return Path(path).as_uri()
99
+
100
+ def _get_change_type(self, event: FileSystemEvent) -> int:
101
+ """
102
+ Convert watchdog event type to LSP change type.
103
+ 1: Created
104
+ 2: Changed
105
+ 3: Deleted
106
+ """
107
+ if event.event_type == "created":
108
+ return 1
109
+ elif event.event_type == "modified":
110
+ return 2
111
+ elif event.event_type == "deleted":
112
+ return 3
113
+ return 2 # Default to changed
setta/lsp/reader.py ADDED
@@ -0,0 +1,184 @@
1
+ import asyncio
2
+ import json
3
+ import logging
4
+
5
+ from setta.lsp.reader_fns.completion import process_completion_response
6
+ from setta.lsp.reader_fns.definition import process_definition_response
7
+ from setta.lsp.reader_fns.diagnostics import process_diagnostics_response
8
+ from setta.lsp.reader_fns.documentHighlight import process_document_highlight_response
9
+ from setta.lsp.reader_fns.references import process_references_response
10
+ from setta.lsp.reader_fns.signatureHelp import process_signature_help_response
11
+ from setta.utils.constants import C
12
+
13
+ from .server import LanguageServerInteractor
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class LanguageServerReader(LanguageServerInteractor):
19
+ def __init__(self, server, websocket_manager):
20
+ self.server = server
21
+ self.websocket_manager = websocket_manager
22
+ self.stop_event = asyncio.Event()
23
+ self.started = asyncio.Event()
24
+ self.reader_task = None
25
+
26
+ async def start_listener(self):
27
+ logger.debug(f"Starting {self.server.name} language server reader")
28
+ self.stop_event.clear() # Reset the stop event
29
+ self.reader_task = asyncio.create_task(self.read_response())
30
+ await self.started.wait()
31
+
32
+ async def stop(self):
33
+ logger.debug(f"Stopping {self.server.name} language server reader")
34
+ self.stop_event.set()
35
+ self.started.clear()
36
+ if self.reader_task:
37
+ self.reader_task.cancel()
38
+ try:
39
+ await self.reader_task
40
+ except asyncio.CancelledError:
41
+ pass
42
+
43
+ async def read_response(self):
44
+ self.started.set()
45
+ while not self.stop_event.is_set():
46
+ try:
47
+ await self.read_and_process_message()
48
+ except Exception as e:
49
+ logging.error(f"Error reading from language server: {e}")
50
+ # Optional: add a small delay to prevent tight loop if there's a persistent error
51
+ await asyncio.sleep(0.1)
52
+
53
+ async def read_and_process_message(self):
54
+ headers = b""
55
+ while not self.stop_event.is_set():
56
+ chunk = await self.server.stdout.read(1)
57
+ if not chunk:
58
+ # Server stdout closed/EOF reached
59
+ self.stop_event.set() # Signal to stop
60
+ return
61
+ headers += chunk
62
+ if headers.endswith(b"\r\n\r\n"):
63
+ break
64
+
65
+ if self.stop_event.is_set():
66
+ return
67
+
68
+ headers_str = headers.decode("utf-8")
69
+ header_parts = headers_str.split("\r\n")
70
+ content_length = 0
71
+ for header in header_parts:
72
+ if header.startswith("Content-Length:"):
73
+ content_length = int(header.split(":")[1].strip())
74
+ break
75
+
76
+ response = b""
77
+ while len(response) < content_length and not self.stop_event.is_set():
78
+ chunk = await self.server.stdout.read(content_length - len(response))
79
+ if not chunk:
80
+ # Server stdout closed/EOF reached
81
+ self.stop_event.set() # Signal to stop
82
+ return
83
+ response += chunk
84
+
85
+ if self.stop_event.is_set():
86
+ return
87
+
88
+ try:
89
+ response = json.loads(response.decode("utf-8"))
90
+ await self.process_response(response)
91
+ except json.JSONDecodeError as e:
92
+ logger.debug(f"Error decoding JSON response: {e}")
93
+ return
94
+ except Exception as e:
95
+ logger.debug(f"Error processing response: {e}")
96
+ return
97
+
98
+ async def process_response(self, response):
99
+ logger.debug(f"Processing response: {response}")
100
+ id = response.get("id", None)
101
+ method = response.get("method", None)
102
+ if id:
103
+ output = self.process_response_with_id(id, method, response)
104
+ else:
105
+ output = self.process_response_without_id(method, response)
106
+
107
+ if id in self.pending_requests:
108
+ self.pending_requests[id].set_result(output["content"])
109
+ elif output["websocket_method"] == "return_to_requester":
110
+ await self.websocket_manager.send_message_to_requester(
111
+ output["websocket_return_id"], output["content"]
112
+ )
113
+ elif output["websocket_method"] == "broadcast":
114
+ await self.websocket_manager.broadcast(
115
+ {
116
+ "messageType": output["websocket_message_type"],
117
+ "content": output["content"],
118
+ }
119
+ )
120
+
121
+ def process_response_with_id(self, id, method, response):
122
+ metadata = self.msg_id_to_metadata.pop(id, {})
123
+ method = method if method else metadata["method"]
124
+ content = None
125
+ websocket_return_id = id
126
+ websocket_method = None
127
+ websocket_message_type = None
128
+ if (
129
+ not self.server.is_initialized
130
+ and id == self.server.initialization_request_id
131
+ ):
132
+ self.server.is_initialized = True
133
+ content = "Initialized"
134
+ websocket_method = "broadcast"
135
+ websocket_message_type = C.WS_LSP_STATUS
136
+ elif method == "textDocument/completion":
137
+ content = process_completion_response(response, metadata)
138
+ websocket_method = "return_to_requester"
139
+ elif method == "textDocument/signatureHelp":
140
+ content = process_signature_help_response(response)
141
+ websocket_method = "return_to_requester"
142
+ elif method == "textDocument/references":
143
+ content, websocket_return_id = process_references_response(
144
+ response, metadata
145
+ )
146
+ websocket_method = "return_to_requester"
147
+ elif method == "textDocument/documentHighlight":
148
+ content, websocket_return_id = process_document_highlight_response(
149
+ response, metadata
150
+ )
151
+ websocket_method = "return_to_requester"
152
+ elif method == "textDocument/definition":
153
+ content = process_definition_response(response)
154
+ websocket_method = "return_to_requester"
155
+
156
+ content = {"data": content, "otherData": metadata.get("otherData")}
157
+
158
+ return {
159
+ "content": content,
160
+ "websocket_return_id": websocket_return_id,
161
+ "websocket_method": websocket_method,
162
+ "websocket_message_type": websocket_message_type,
163
+ }
164
+
165
+ def process_response_without_id(self, method, response):
166
+ content = None
167
+ websocket_return_id = None
168
+ websocket_method = None
169
+ websocket_message_type = None
170
+
171
+ if method == "textDocument/publishDiagnostics":
172
+ content, needsDiagnostics = process_diagnostics_response(
173
+ response, self.get_code_metadata
174
+ )
175
+ if needsDiagnostics:
176
+ websocket_method = "broadcast"
177
+ websocket_message_type = C.WS_LSP_DIAGNOSTICS
178
+
179
+ return {
180
+ "content": content,
181
+ "websocket_return_id": websocket_return_id,
182
+ "websocket_method": websocket_method,
183
+ "websocket_message_type": websocket_message_type,
184
+ }
File without changes
@@ -0,0 +1,84 @@
1
+ from setta.code_gen.python.position_line_col import line_col_to_position_batch
2
+
3
+
4
+ def process_completion_response(response, metadata):
5
+ content = []
6
+ if response["result"] and response["result"]["items"]:
7
+ code = metadata["code"]
8
+ content = process_completion(
9
+ code,
10
+ response["result"]["items"],
11
+ metadata["generated_var_names"],
12
+ metadata["referencable_var_names"],
13
+ metadata["cursor_offset"],
14
+ )
15
+ return content
16
+
17
+
18
+ def process_completion(
19
+ code, items, generated_var_names, referencable_var_names, cursor_offset
20
+ ):
21
+ content = []
22
+ line_cols = []
23
+ content_idx_with_text_edit = {}
24
+ for x in items:
25
+ if x["label"] in generated_var_names:
26
+ continue
27
+ c = {"label": x["label"], "type": type_mapping[x["kind"]]}
28
+ if "textEdit" in x:
29
+ content_idx_with_text_edit[len(content)] = len(line_cols)
30
+ r = x["textEdit"]["range"]
31
+ line_cols.append(
32
+ (
33
+ r["start"]["line"],
34
+ r["start"]["character"],
35
+ )
36
+ )
37
+ line_cols.append((r["end"]["line"], r["end"]["character"]))
38
+
39
+ content.append(c)
40
+
41
+ if len(line_cols) > 0:
42
+ # use the raw line/character values because the code
43
+ # contains generated code
44
+ positions = line_col_to_position_batch(code, line_cols)
45
+ for i, j in content_idx_with_text_edit.items():
46
+ # shift it back by cursor_offset so that it's ready
47
+ # for the frontend
48
+ content[i]["from"] = positions[j] - cursor_offset
49
+ content[i]["to"] = positions[j + 1] - cursor_offset
50
+
51
+ for x in referencable_var_names:
52
+ content.append({"label": x, "type": "variable"})
53
+
54
+ return content
55
+
56
+
57
+ type_mapping = {
58
+ 1: "File",
59
+ 2: "Module",
60
+ 3: "Namespace",
61
+ 4: "Package",
62
+ 5: "Class",
63
+ 6: "Method",
64
+ 7: "Property",
65
+ 8: "Field",
66
+ 9: "Constructor",
67
+ 10: "Enum",
68
+ 11: "Interface",
69
+ 12: "Function",
70
+ 13: "Variable",
71
+ 14: "Constant",
72
+ 15: "String",
73
+ 16: "Number",
74
+ 17: "Boolean",
75
+ 18: "Array",
76
+ 19: "Object",
77
+ 20: "Key",
78
+ 21: "Null",
79
+ 22: "EnumMember",
80
+ 23: "Struct",
81
+ 24: "Event",
82
+ 25: "Operator",
83
+ 26: "TypeParameter",
84
+ }
@@ -0,0 +1,2 @@
1
+ def process_definition_response(response):
2
+ return bool(response["result"])
@@ -0,0 +1,99 @@
1
+ import re
2
+
3
+ from setta.code_gen.export_selected import get_gen_code_template_var
4
+ from setta.code_gen.python.position_line_col import line_col_to_position_batch
5
+
6
+
7
+ def process_diagnostics_response(response, get_code_metadata):
8
+ params = response["params"]
9
+ metadata = get_code_metadata(params["uri"])
10
+ if not metadata["needsDiagnostics"] or metadata["version"] != params["version"]:
11
+ return None, False
12
+
13
+ convert_diagnostic_line_cols_to_positions(metadata["code"], params["diagnostics"])
14
+
15
+ code_split = metadata["code"].split("\n")
16
+ diagnostics = process_diagnostics(
17
+ params["diagnostics"],
18
+ code_split,
19
+ metadata["codeJson"],
20
+ metadata["ref_template_var_positions"],
21
+ )
22
+
23
+ return {
24
+ "projectConfigId": metadata["projectConfigId"],
25
+ "codeSectionId": metadata["codeSectionId"],
26
+ "diagnostics": diagnostics,
27
+ }, True
28
+
29
+
30
+ def process_diagnostics(diagnostics, code_split, codeJson, ref_template_var_positions):
31
+ output = []
32
+ gen_code_template_var = get_gen_code_template_var(
33
+ ref_template_var_positions["templateVars"]
34
+ )
35
+ if gen_code_template_var:
36
+ gen_code_start = gen_code_template_var["startPos"]
37
+ gen_code_end = gen_code_start + len(gen_code_template_var["value"])
38
+ for d in diagnostics:
39
+ start, end = d["range"]["start"], d["range"]["end"]
40
+ if gen_code_template_var and gen_code_start <= start["position"] < gen_code_end:
41
+ result = process_gen_code_diagnostic(d, code_split, codeJson, start, end)
42
+ output.extend(result)
43
+ # TODO: process diagnostics for non-generated code:
44
+ # else:
45
+ # output.append(d)
46
+
47
+ return output
48
+
49
+
50
+ def process_gen_code_diagnostic(d, code_split, codeJson, start, end):
51
+ if "code" not in d or not codeJson:
52
+ return []
53
+ if d["code"] == "reportArgumentType":
54
+ problem_var = code_split[start["line"]][
55
+ start["character"] : end["character"]
56
+ ].strip()
57
+ return [get_message_with_ids(codeJson, problem_var, d["message"])]
58
+ elif d["code"] == "reportCallIssue" and "missing" in d["message"]:
59
+ missing_params = extract_parameters(d["message"])
60
+ # get variable to the left of the equal sign
61
+ assigned_to = code_split[start["line"]].split("=")[0].strip()
62
+ unusedParams = codeJson[assigned_to]["value"]["unusedParams"]
63
+ output = []
64
+ for potential_problem_var in unusedParams:
65
+ if codeJson[potential_problem_var]["name"] in missing_params:
66
+ output.append(
67
+ get_message_with_ids(codeJson, potential_problem_var, d["message"])
68
+ )
69
+ return output
70
+ return []
71
+
72
+
73
+ def get_message_with_ids(code_json, problem_var, message):
74
+ section_id, param_info_id = (
75
+ code_json[problem_var]["sectionId"],
76
+ code_json[problem_var]["paramInfoId"],
77
+ )
78
+ return {"sectionId": section_id, "paramInfoId": param_info_id, "message": message}
79
+
80
+
81
+ def extract_parameters(error_string):
82
+ pattern = r'"([^"]+)"'
83
+ parameters = re.findall(pattern, error_string)
84
+ return parameters
85
+
86
+
87
+ def convert_diagnostic_line_cols_to_positions(code, diagnostics):
88
+ line_cols = []
89
+ for d in diagnostics:
90
+ x = d["range"]["start"]
91
+ line_cols.append((x["line"], x["character"]))
92
+ x = d["range"]["end"]
93
+ line_cols.append((x["line"], x["character"]))
94
+
95
+ positions = line_col_to_position_batch(code, line_cols)
96
+
97
+ for i, d in enumerate(diagnostics):
98
+ d["range"]["start"]["position"] = positions[i * 2]
99
+ d["range"]["end"]["position"] = positions[(i * 2) + 1]