setta 0.0.3.dev3__py3-none-any.whl → 0.0.3.dev5__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.

Potentially problematic release.


This version of setta might be problematic. Click here for more details.

@@ -15,8 +15,8 @@
15
15
 
16
16
 
17
17
  <title>setta.dev</title>
18
- <script type="module" crossorigin src="/static/assets/index-73adf0a9.js"></script>
19
- <link rel="stylesheet" href="/static/assets/index-1d4b4ecf.css">
18
+ <script type="module" crossorigin src="/static/assets/index-1f218da9.js"></script>
19
+ <link rel="stylesheet" href="/static/assets/index-af271c9f.css">
20
20
  </head>
21
21
  <body>
22
22
  <noscript>You need to enable JavaScript to run this app.</noscript>
setta/tasks/tasks.py CHANGED
@@ -1,10 +1,9 @@
1
1
  import asyncio
2
2
  import logging
3
- import queue
4
- import threading
5
3
  from typing import Dict
6
4
 
7
5
  from setta.database.utils import create_new_id
6
+ from setta.utils.constants import C
8
7
 
9
8
  from . import fns
10
9
  from .fns.utils import TaskDefinition, TaskMessage
@@ -20,75 +19,31 @@ class Tasks:
20
19
  self.task_runner = TaskRunner()
21
20
  self.cache = {}
22
21
  self.fns: Dict[str, TaskDefinition] = {}
23
- self.in_memory_subprocess = SettaInMemoryFnSubprocess()
24
- self.websockets = [] # Store the websocket connections
22
+ self.in_memory_subprocesses = {}
23
+ self.websockets = []
24
+ self.stop_event = asyncio.Event()
25
25
  add_fns_from_module(self.fns, fns)
26
26
 
27
- # Start stdout listener thread
28
- self._stop_event = asyncio.Event()
29
- self.stdout_queue = queue.Queue() # regular Queue
30
- self._stdout_processor_task = None
31
- self.stdout_thread = threading.Thread(target=self._stdout_listener, daemon=True)
32
- self.stdout_thread.start()
33
-
34
- # Backend Changes (Tasks class)
35
27
  async def connect(self, websocket):
36
28
  # Accept the new connection
37
29
  await websocket.accept()
38
30
  self.websockets.append(websocket)
39
-
40
- # Start the processor task if it's not running
41
- if self._stdout_processor_task is None or self._stdout_processor_task.done():
42
- self._stdout_processor_task = asyncio.create_task(
43
- self._process_stdout_queue()
44
- )
31
+ for k, v in self.in_memory_subprocesses.items():
32
+ v["subprocess"].start_stdout_processor_task()
33
+ logger.debug(f"listening to subprocess {k}")
45
34
 
46
35
  async def disconnect(self, websocket):
47
36
  self.websockets.remove(websocket)
48
37
  if len(self.websockets) == 0:
49
- # Cancel the processor task
50
- if self._stdout_processor_task and not self._stdout_processor_task.done():
51
- self._stdout_processor_task.cancel()
52
- try:
53
- await self._stdout_processor_task
54
- except asyncio.CancelledError:
55
- pass
56
- self._stdout_processor_task = None
57
-
58
- def _stdout_listener(self):
59
- while not self._stop_event.is_set():
60
- try:
61
- stdout_data = self.in_memory_subprocess.stdout_parent_conn.recv()
62
- self.stdout_queue.put(stdout_data) # simple put, no async needed
63
- except Exception as e:
64
- if self._stop_event.is_set():
65
- break
66
- logger.debug(f"Error in stdout listener: {e}")
67
-
68
- async def _process_stdout_queue(self):
69
- while not self._stop_event.is_set():
70
- try:
71
- if self._stop_event.is_set():
72
- break
73
- if len(self.websockets) > 0:
74
- stdout_data = self.stdout_queue.get_nowait()
75
- stdout_data = stdout_data.replace("\n", "\r\n")
76
- for w in self.websockets:
77
- await w.send_text(stdout_data)
78
- self.stdout_queue.task_done()
79
- except queue.Empty:
80
- await asyncio.sleep(0.1) # Check for connection every 100ms
81
- except asyncio.CancelledError:
82
- break
83
- except Exception as e:
84
- if self._stop_event.is_set():
85
- break
86
- logger.debug(f"Error processing stdout: {e}")
87
-
88
- async def __call__(self, fn_name, message: TaskMessage):
89
- if fn_name in self.fns:
90
- return await self.call_regular_fn(fn_name, message)
91
- return await self.call_in_memory_subprocess_fn(fn_name, message)
38
+ for v in self.in_memory_subprocesses.values():
39
+ await v["subprocess"].stop_stdout_processor_task()
40
+
41
+ async def __call__(
42
+ self, message_type, message: TaskMessage, websocket_manager=None
43
+ ):
44
+ if message_type == "inMemoryFn":
45
+ return await self.call_in_memory_subprocess_fn(message, websocket_manager)
46
+ return await self.call_regular_fn(message_type, message)
92
47
 
93
48
  async def call_regular_fn(self, fn_name, message: TaskMessage):
94
49
  fn = self.fns[fn_name]
@@ -101,52 +56,104 @@ class Tasks:
101
56
  result["messageType"] = fn.return_message_type
102
57
  return result
103
58
 
104
- async def call_in_memory_subprocess_fn(self, fn_name, message: TaskMessage):
105
- self.in_memory_subprocess.parent_conn.send(
106
- {"type": "call", "fn_name": fn_name, "message": message}
107
- )
108
- result = await self.task_runner.run(
109
- self.in_memory_subprocess.parent_conn.recv, [], RunType.THREAD
110
- )
111
- # if result["status"] == "success":
112
- # for x in result["content"]:
113
- # x.setdefault("sectionType", default_section_type(x["type"]))
114
- if result["status"] != "success":
115
- result["content"] = {}
116
-
117
- return {"content": result["content"], "messageType": result["messageType"]}
118
-
119
- async def add_custom_fns(self, code_list, to_cache):
120
- error_msgs = {}
121
- task_metadata = {}
122
- initial_content = []
123
- for c in code_list:
124
- # Send import request to subprocess
125
- self.in_memory_subprocess.parent_conn.send(
59
+ async def call_in_memory_subprocess_fn(
60
+ self, message: TaskMessage, websocket_manager=None, call_all=False
61
+ ):
62
+ # Create a list of tasks to run concurrently
63
+ tasks = []
64
+ results = []
65
+
66
+ for sp_info in self.in_memory_subprocesses.values():
67
+ for fn_name, dependencies in sp_info["dependencies"].items():
68
+ if (
69
+ call_all
70
+ or None in dependencies
71
+ or any(k in dependencies for k in message.content.keys())
72
+ ):
73
+ # Send message to subprocess
74
+ sp_info["subprocess"].parent_conn.send(
75
+ {"type": "call", "fn_name": fn_name, "message": message}
76
+ )
77
+
78
+ # Create task for receiving response
79
+ task = asyncio.create_task(
80
+ self._handle_subprocess_response(
81
+ message.id,
82
+ sp_info["subprocess"].parent_conn.recv,
83
+ websocket_manager,
84
+ results,
85
+ )
86
+ )
87
+ tasks.append(task)
88
+
89
+ # Wait for all tasks to complete concurrently
90
+ if tasks:
91
+ await asyncio.gather(*tasks)
92
+
93
+ if websocket_manager:
94
+ return {}
95
+
96
+ content = []
97
+ for r in results:
98
+ if r["content"]:
99
+ content.extend(r["content"])
100
+ return {"content": content, "messageType": C.WS_IN_MEMORY_FN_RETURN}
101
+
102
+ async def _handle_subprocess_response(
103
+ self, msg_id, recv_fn, websocket_manager, results
104
+ ):
105
+ # Run the receive function in a thread
106
+ result = await self.task_runner.run(recv_fn, [], RunType.THREAD)
107
+ if result["status"] == "success":
108
+ if websocket_manager is not None and result["content"]:
109
+ await websocket_manager.send_message_to_requester(
110
+ msg_id, result["content"], result["messageType"]
111
+ )
112
+ else:
113
+ results.append(result)
114
+
115
+ async def add_custom_fns(self, code_graph, to_cache):
116
+ for c in code_graph:
117
+ subprocess_key = c["subprocess_key"]
118
+ module_name = c["module_name"]
119
+ sp = self.in_memory_subprocesses.get(subprocess_key, {}).get("subprocess")
120
+ if not sp:
121
+ logger.debug(f"Creating new subprocess for {module_name}")
122
+ sp = SettaInMemoryFnSubprocess(self.stop_event, self.websockets)
123
+ self.in_memory_subprocesses[subprocess_key] = {
124
+ "subprocess": sp,
125
+ "dependencies": {},
126
+ }
127
+
128
+ sp.parent_conn.send(
126
129
  {
127
130
  "type": "import",
128
131
  "code": c["code"],
129
- "module_name": c["module_name"],
132
+ "module_name": module_name,
130
133
  "to_cache": to_cache,
131
134
  }
132
135
  )
133
- result = await self.task_runner.run(
134
- self.in_memory_subprocess.parent_conn.recv, [], RunType.THREAD
135
- )
136
+ result = await self.task_runner.run(sp.parent_conn.recv, [], RunType.THREAD)
137
+ sp_info = self.in_memory_subprocesses[subprocess_key]
138
+
136
139
  if result["status"] == "success":
137
- task_metadata.update(result["content"])
140
+ sp_info["dependencies"].update(result["content"])
138
141
  else:
139
- error_msgs[c["module_name"]] = result["error"]
142
+ # TODO: store error message and display on frontend?
143
+ pass
140
144
 
141
- for k in task_metadata.keys():
142
- task_output = await self(k, TaskMessage(id=create_new_id(), content={}))
143
- initial_content.extend(task_output["content"])
145
+ all_dependencies = set.union(*sp_info["dependencies"].values())
146
+ initial_result = await self.call_in_memory_subprocess_fn(
147
+ TaskMessage(id=create_new_id(), content={}), call_all=True
148
+ )
149
+
150
+ logger.debug(
151
+ f"self.in_memory_subprocesses keys: {self.in_memory_subprocesses.keys()}"
152
+ )
144
153
 
145
- return task_metadata, error_msgs, initial_content
154
+ return all_dependencies, initial_result["content"]
146
155
 
147
156
  def close(self):
148
- self._stop_event.set()
149
- self.in_memory_subprocess.close()
150
- self.stdout_thread.join()
151
- if self._stdout_processor_task:
152
- self._stdout_processor_task.cancel()
157
+ self.stop_event.set()
158
+ for v in self.in_memory_subprocesses.values():
159
+ v["subprocess"].close()
setta/tasks/utils.py CHANGED
@@ -1,7 +1,11 @@
1
+ import asyncio
1
2
  import importlib.util
2
3
  import json
4
+ import logging
3
5
  import multiprocessing
6
+ import queue
4
7
  import sys
8
+ import threading
5
9
  import traceback
6
10
  import uuid
7
11
 
@@ -9,6 +13,8 @@ from setta.tasks.fns.utils import TaskDefinition
9
13
  from setta.utils.constants import CWD
10
14
  from setta.utils.utils import nested_access
11
15
 
16
+ logger = logging.getLogger(__name__)
17
+
12
18
 
13
19
  def import_code_from_string(code_string, module_name=None, add_to_sys_modules=True):
14
20
  # Generate a unique module name if one isn't provided
@@ -16,9 +22,8 @@ def import_code_from_string(code_string, module_name=None, add_to_sys_modules=Tr
16
22
  module_name = f"setta_dynamic_module_{uuid.uuid4().hex}"
17
23
 
18
24
  # Add current directory to sys.path if it's not already there
19
- current_dir = CWD
20
- if current_dir not in sys.path:
21
- sys.path.insert(0, current_dir)
25
+ if CWD not in sys.path:
26
+ sys.path.insert(0, CWD)
22
27
 
23
28
  spec = importlib.util.spec_from_loader(module_name, loader=None)
24
29
 
@@ -40,13 +45,23 @@ def import_code_from_string(code_string, module_name=None, add_to_sys_modules=Tr
40
45
 
41
46
 
42
47
  class SettaInMemoryFnSubprocess:
43
- def __init__(self):
48
+ def __init__(self, stop_event, websockets):
44
49
  self.parent_conn, self.child_conn = multiprocessing.Pipe()
45
50
  self.process = multiprocessing.Process(target=self._subprocess_main)
46
51
  self.stdout_parent_conn, self.stdout_child_conn = multiprocessing.Pipe()
47
52
  self.process.daemon = True # Ensure process dies with parent
48
53
  self.process.start()
49
54
 
55
+ self.stop_event = stop_event
56
+ self.websockets = websockets
57
+ self.stdout_queue = queue.Queue()
58
+ self.stdout_processor_task = None
59
+ self.stdout_thread = threading.Thread(target=self.stdout_listener, daemon=True)
60
+ self.stdout_thread.start()
61
+
62
+ if len(self.websockets) > 0:
63
+ self.start_stdout_processor_task()
64
+
50
65
  def _subprocess_main(self):
51
66
  """Main loop in subprocess that handles all requests"""
52
67
  # Initialize store for imported modules
@@ -137,6 +152,10 @@ class SettaInMemoryFnSubprocess:
137
152
  self.stdout_parent_conn.close()
138
153
  self.stdout_child_conn.close()
139
154
 
155
+ self.stdout_thread.join()
156
+ if self.stdout_processor_task:
157
+ self.stdout_processor_task.cancel()
158
+
140
159
  def process_message(self, fn_name, message, cache):
141
160
  if fn_name in cache:
142
161
  exporter_obj = cache[fn_name]
@@ -147,6 +166,51 @@ class SettaInMemoryFnSubprocess:
147
166
  message.content = exporter_obj.output
148
167
  return message.content
149
168
 
169
+ def start_stdout_processor_task(self):
170
+ if self.stdout_processor_task is None or self.stdout_processor_task.done():
171
+ self.stdout_processor_task = asyncio.create_task(
172
+ self.process_stdout_queue()
173
+ )
174
+
175
+ async def stop_stdout_processor_task(self):
176
+ if self.stdout_processor_task and not self.stdout_processor_task.done():
177
+ self.stdout_processor_task.cancel()
178
+ try:
179
+ await self.stdout_processor_task
180
+ except asyncio.CancelledError:
181
+ pass
182
+ self.stdout_processor_task = None
183
+
184
+ async def process_stdout_queue(self):
185
+ while not self.stop_event.is_set():
186
+ try:
187
+ if self.stop_event.is_set():
188
+ break
189
+ if len(self.websockets) > 0:
190
+ stdout_data = self.stdout_queue.get_nowait()
191
+ stdout_data = stdout_data.replace("\n", "\r\n")
192
+ for w in self.websockets:
193
+ await w.send_text(stdout_data)
194
+ self.stdout_queue.task_done()
195
+ except queue.Empty:
196
+ await asyncio.sleep(0.1) # Check for connection every 100ms
197
+ except asyncio.CancelledError:
198
+ break
199
+ except Exception as e:
200
+ if self.stop_event.is_set():
201
+ break
202
+ logger.debug(f"Error processing stdout: {e}")
203
+
204
+ def stdout_listener(self):
205
+ while not self.stop_event.is_set():
206
+ try:
207
+ stdout_data = self.stdout_parent_conn.recv()
208
+ self.stdout_queue.put(stdout_data) # simple put, no async needed
209
+ except Exception as e:
210
+ if self._stop_event.is_set():
211
+ break
212
+ logger.debug(f"Error in stdout listener: {e}")
213
+
150
214
 
151
215
  def add_fns_from_module(fns_dict, module, module_name=None):
152
216
  count = 1
@@ -168,11 +232,11 @@ def add_fns_from_module(fns_dict, module, module_name=None):
168
232
  def get_task_metadata(in_memory_fn, exporter_obj):
169
233
  # None means run the task on every change
170
234
  if in_memory_fn.dependencies is None:
171
- dependencies = None
235
+ dependencies = set([None])
172
236
  # Empty array means only run when the task imported.
173
237
  # Non-empty array means run when specified dependencies update.
174
238
  else:
175
- dependencies = [
239
+ dependencies = set(
176
240
  exporter_obj.var_name_reverse_mapping[d] for d in in_memory_fn.dependencies
177
- ]
178
- return {"dependencies": dependencies}
241
+ )
242
+ return dependencies
@@ -43,7 +43,9 @@ class WebsocketManager:
43
43
  if wid == self.server_cli_id:
44
44
  # process task and send any results back to requester
45
45
  result = await tasks(
46
- message["messageType"], TaskMessage.parse_obj(message)
46
+ message["messageType"],
47
+ TaskMessage.parse_obj(message),
48
+ websocket_manager=self,
47
49
  )
48
50
  if "content" in result:
49
51
  websocket = self.sockets[fromWebsocketId]["websocket"]
@@ -64,10 +66,13 @@ class WebsocketManager:
64
66
  if "location" in message:
65
67
  self.sockets[fromWebsocketId]["location"] = message["location"]
66
68
 
67
- async def send_message_to_requester(self, id, content):
69
+ async def send_message_to_requester(self, id, content, messageType=None):
68
70
  # just send data to target websocket
69
71
  websocket = self.sockets[self.message_id_to_sender_id[id]]["websocket"]
70
- await websocket.send_text(json.dumps({"id": id, "content": content}))
72
+ return_val = {"id": id, "content": content}
73
+ if messageType:
74
+ return_val["messageType"] = messageType
75
+ await websocket.send_text(json.dumps(return_val))
71
76
 
72
77
  async def send_message_to_location(self, content, messageType, location):
73
78
  for w in self.sockets.values():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: setta
3
- Version: 0.0.3.dev3
3
+ Version: 0.0.3.dev5
4
4
  Home-page: https://setta.dev
5
5
  Project-URL: GitHub, https://github.com/settadev/setta
6
6
  License-File: LICENSE
@@ -1,11 +1,11 @@
1
- setta/__init__.py,sha256=aHK3nTsHMoeeQG7I2k8wIkeT23k43hNfu2Y2-cgOh8c,27
1
+ setta/__init__.py,sha256=kH8A5OhSz91E7LZXLnQ3CnbIZBoobjt8lmTWUyCqnuw,27
2
2
  setta/server.py,sha256=P78BMFvcCokVhjnVlNIKcmpCSvmzSqt-33bx4bhOe6Y,4626
3
3
  setta/start.py,sha256=jEeSiocLeBitvg48fa6k1CpLnPI63JHkQ8O-WVM6ch8,3078
4
- setta/cli/__init__.py,sha256=8NFfvFBHtD0oNwSZYPSaHjQTEQxZmCMgCdHtG2Mq160,47
4
+ setta/cli/__init__.py,sha256=UxZG_VOMuF6lEBT3teUgTS9ulsK3wt3Gu3BbAQiAmt8,47
5
5
  setta/cli/connect.py,sha256=Pj2Ten7CQcLQGNnyi5Y-vYslQDN3J8csPcWetlvu_J0,1273
6
6
  setta/cli/logger.py,sha256=M-gGOcYt8Xj7ldNGBAUfA9yL1nX4UpBuQR1lkg_qiSs,6130
7
7
  setta/code_gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- setta/code_gen/create_runnable_scripts.py,sha256=uZ2l5F0PlldPMD51i0FWiqjLpAMAugrmftKTGaRFjEo,15948
8
+ setta/code_gen/create_runnable_scripts.py,sha256=LXRu8ErO3_e5HCNomnlgfsyxKp2h-Pmm2VFXzBgDDhA,17444
9
9
  setta/code_gen/export_selected.py,sha256=Hpa2uYFxTtxG0R9szY3WQA2Hj6XoejYVT53ET1l7Qmg,26883
10
10
  setta/code_gen/find_placeholders.py,sha256=xWEVVPmyeEhPwoMsCnmMkd-ox3rd50jRur3uxfCqB30,601
11
11
  setta/code_gen/utils.py,sha256=ArBPYA__ekeHjZVUDXanlMEnqCX5-Z_R1rMM-1UbEV0,4088
@@ -87,7 +87,7 @@ setta/routers/artifact.py,sha256=9wHdreg5DsLshhET-6gEDw2Apw_-r8bRF1x3-_dD9mU,266
87
87
  setta/routers/code_info.py,sha256=rDBLkr5VQOlktap3hWA73ls0VrBi5y4mc_SfWzw9ad0,857
88
88
  setta/routers/dependencies.py,sha256=lQDZFcXw-jUXK1q8yglUg3jY9dKoE-xvVcWckKqmOr4,1126
89
89
  setta/routers/in_memory_fn_stdout_websocket.py,sha256=T2BpLzh6PwYQP0qIkFS4r_VfEKBlwl4gkwIaq6r6Phs,604
90
- setta/routers/interactive.py,sha256=WRDG7WHkUMxVddylBhR5v1IU_Qg8vqVIdt2AMkBKCwo,3626
90
+ setta/routers/interactive.py,sha256=juUtPmCyqHSnIb5k6iOYUtfmukp1Z6x25wISlANgUic,4385
91
91
  setta/routers/lsp.py,sha256=DAZqdiRKDWJ9ikjwQetV4_8s9U-EDC91ToJA3u57qnU,385
92
92
  setta/routers/projects.py,sha256=p3zPD3jobYOxBGJSSIYS1Aqu1w-PrJCcEN6dPJ0DT6E,5255
93
93
  setta/routers/reference_renaming.py,sha256=Ec1hz2Nz_hYqk8GyGmUcWKvXo-lVEDbIIK2YbX-wi00,3598
@@ -108,7 +108,7 @@ setta/static/frontend/browserconfig.xml,sha256=w0iw1t89kA7-965LTfyLYrFzewTQnUWE_
108
108
  setta/static/frontend/favicon-16x16.png,sha256=q67Crpy8s3wryu7Y3kffPeysN99Lt4XeFygXhPKize8,740
109
109
  setta/static/frontend/favicon-32x32.png,sha256=4NKXYticYdMrRHmVveHjxqnBU1HWgBT5JyJG8lx3BNE,1027
110
110
  setta/static/frontend/favicon.ico,sha256=02qhEBLsvsgBTZX6dcZElMyivlvrR7Yr6wB8ItEZFsc,15086
111
- setta/static/frontend/index.html,sha256=_bxzxQWKiqvui-oY6epsNEdoYd00oU-Cyi7Ntth1ZMQ,1296
111
+ setta/static/frontend/index.html,sha256=4d4CugkQWpyw6EozUuo1rnSN81dqwLxqea3sWNSeT4w,1296
112
112
  setta/static/frontend/manifest.json,sha256=ULPYw5A68_eNhxuUVXqxT045yhkurKPSz6hjyGcnmhQ,492
113
113
  setta/static/frontend/mstile-144x144.png,sha256=wQqckmRWre2NCCevevI3rv4j0tcduVMkpYr2tPj73cs,2692
114
114
  setta/static/frontend/mstile-150x150.png,sha256=FUwy6PipTofnhmJB5CdXWYgwy-2inq_sIOdOwdDklcY,2674
@@ -184,8 +184,8 @@ setta/static/frontend/assets/cormorant-garamond-latin-700-italic-0bc53e12.woff2,
184
184
  setta/static/frontend/assets/cormorant-garamond-latin-ext-700-italic-525738e0.woff2,sha256=Ulc44CPXdUiI5dY86W76HLk7801Fm9_QywCV-8GRtFU,17240
185
185
  setta/static/frontend/assets/cormorant-garamond-vietnamese-700-italic-99563037.woff2,sha256=mVYwN54qI0RLXqyrDGPUNpBHWSJDKjgUyBRWa2FJ_ao,5248
186
186
  setta/static/frontend/assets/erase-5e0448ea.svg,sha256=XgRI6pChr392LJ-pGbwqqkN8OWcJMEtRGX-Gv-90qjw,872
187
- setta/static/frontend/assets/index-1d4b4ecf.css,sha256=HUtOz9lZUrcZrQMc4nQsS5ixI6ukEUF2qGsCy_F_0DU,232608
188
- setta/static/frontend/assets/index-73adf0a9.js,sha256=VRiK4VG6jp9Z4TKkmNLQaO9WAw_oyj_3MZYA1IwIo7I,2847508
187
+ setta/static/frontend/assets/index-1f218da9.js,sha256=GEYeMbQIVHiDWM2sapWp1VSxuzoVe9sC2IJtNP5021k,2847446
188
+ setta/static/frontend/assets/index-af271c9f.css,sha256=ryccn_uul30_aMdIhgzMlq6GcE0D6x8fyfneCdgaY9o,232608
189
189
  setta/static/frontend/assets/inter-all-400-normal-054f12d0.woff,sha256=BU8S0GmcIMyYte4ESEdQJO-WvL2Rb-38m1n0ujdbYxI,128624
190
190
  setta/static/frontend/assets/inter-all-600-normal-c03769e5.woff,sha256=wDdp5VNyQL_IbxcPThD2qI-ETg_QKj7AmCwMCjqDfLE,139072
191
191
  setta/static/frontend/assets/inter-all-800-normal-15dc6e4b.woff,sha256=FdxuS9xuVumB5nbVcCXyt3IWqzS4Z75qiRz_0FV5al0,139120
@@ -232,8 +232,8 @@ setta/static/seed/.DS_Store,sha256=ENxJvDQd7Te_U8gExcXtHE-mAeBUYOHELRfDWgN1NmA,6
232
232
  setta/static/seed/examples/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
233
233
  setta/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
234
234
  setta/tasks/task_runner.py,sha256=gMXpfZWFMQbix2MfrHVCKB7BxQCjO8JH2P8cxUmt1ms,849
235
- setta/tasks/tasks.py,sha256=ImZ6cSQj4HBDP41V9Uf3elxm9JSYxRONu8iSvYzwlOw,5910
236
- setta/tasks/utils.py,sha256=4yZkDa6vmeYncejCN_o4afBb7uJ8Sn5X4svdQOFrw0g,6126
235
+ setta/tasks/tasks.py,sha256=dR02kybZnwiGKt3YhlfWgx0fDUPCoDeslrnm8mJcr74,5956
236
+ setta/tasks/utils.py,sha256=D_M5rZRu0N4z21mM2jyrKBSUCCFT6LrQgegr3uf1NgM,8545
237
237
  setta/tasks/fns/__init__.py,sha256=JhGzzQGaT9BWtF3pOmguh6pzIF9kdG3jdDNLyYZ2w7g,461
238
238
  setta/tasks/fns/codeAreaAutocomplete.py,sha256=gJ5JbjkWDyTothr-UF-YlOxrbVzj2iyOVK7XD3lfhSQ,6416
239
239
  setta/tasks/fns/codeAreaFindTemplateVars.py,sha256=vD9rY8VNPavv6VKa1bnxRPPRDNvFQy6mPIZRl-_3GnY,3708
@@ -253,10 +253,10 @@ setta/utils/generate_memorable_string.py,sha256=ZIn8gQm3cpMuqTCRgAPXAm5VdbWW7O3f
253
253
  setta/utils/generate_new_filename.py,sha256=KBLX6paDmTvXR-027TpqQkfijIXc7mCfhen-u1WZARA,3067
254
254
  setta/utils/section_contents.py,sha256=V2HQPik6DfSXw4j7IalbP5AZ3OEGCbtL5ub3xL-Q_Qo,4141
255
255
  setta/utils/utils.py,sha256=KjzcvgM3Ab3IcE8vaWYtgBpwzPLKg0LmblnHLoYZJHM,9164
256
- setta/utils/websocket_manager.py,sha256=5k_GkOSKT9e40fiu6-PpkRrrlr3LOlqDshF73jdpwlg,3581
257
- setta-0.0.3.dev3.dist-info/LICENSE,sha256=us9fuCq9wmiZVzayjKxNZ2iJYF6dROe0Qp57ToCO7XU,11361
258
- setta-0.0.3.dev3.dist-info/METADATA,sha256=OlP6-QgmDne-62YAol-nXurqCByDSoZYscT_8y3ahc0,829
259
- setta-0.0.3.dev3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
260
- setta-0.0.3.dev3.dist-info/entry_points.txt,sha256=P0qCESy9fWF2q1EQ9JufGldCSnPHplDPn8J6Bgk5hB0,42
261
- setta-0.0.3.dev3.dist-info/top_level.txt,sha256=8G4lmRzVOnJ11_DescPVHE6MQZH-o06A0nGsDDV2ngY,6
262
- setta-0.0.3.dev3.dist-info/RECORD,,
256
+ setta/utils/websocket_manager.py,sha256=S2lEGZsc2OhW0yKLW9VEcH7wi7ppzTfDMQa_hxf3ovc,3772
257
+ setta-0.0.3.dev5.dist-info/LICENSE,sha256=us9fuCq9wmiZVzayjKxNZ2iJYF6dROe0Qp57ToCO7XU,11361
258
+ setta-0.0.3.dev5.dist-info/METADATA,sha256=IWvmVuV-CtMykwttA1EMFK8RuFQEbFMBfVS3gvL5SIs,829
259
+ setta-0.0.3.dev5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
260
+ setta-0.0.3.dev5.dist-info/entry_points.txt,sha256=P0qCESy9fWF2q1EQ9JufGldCSnPHplDPn8J6Bgk5hB0,42
261
+ setta-0.0.3.dev5.dist-info/top_level.txt,sha256=8G4lmRzVOnJ11_DescPVHE6MQZH-o06A0nGsDDV2ngY,6
262
+ setta-0.0.3.dev5.dist-info/RECORD,,