jaseci 1.4.0.18__py3-none-any.whl → 1.4.0.20__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 jaseci might be problematic. Click here for more details.

Files changed (42) hide show
  1. jaseci/VERSION +1 -1
  2. jaseci/cli_tools/jsctl.py +41 -2
  3. jaseci/cli_tools/tests/test_jsctl.py +11 -0
  4. jaseci/extens/act_lib/internal.py +2 -1
  5. jaseci/extens/act_lib/std.py +7 -0
  6. jaseci/extens/act_lib/tests/test_std_lib.py +3 -1
  7. jaseci/extens/api/jsorc_api.py +41 -1
  8. jaseci/extens/api/walker_api.py +9 -0
  9. jaseci/jac/interpreter/architype_interp.py +63 -28
  10. jaseci/jac/interpreter/interp.py +54 -158
  11. jaseci/jac/interpreter/sentinel_interp.py +73 -5
  12. jaseci/jac/interpreter/walker_interp.py +27 -38
  13. jaseci/jac/ir/ast.py +9 -1
  14. jaseci/jac/jac.g4 +5 -4
  15. jaseci/jac/jac_parse/jacListener.py +8 -8
  16. jaseci/jac/jac_parse/jacParser.py +1167 -1154
  17. jaseci/jac/machine/jac_scope.py +23 -30
  18. jaseci/jac/machine/machine_state.py +76 -12
  19. jaseci/jsorc/jsorc.py +92 -79
  20. jaseci/jsorc/live_actions.py +29 -24
  21. jaseci/jsorc/redis.py +7 -5
  22. jaseci/prim/{action.py → ability.py} +44 -31
  23. jaseci/prim/architype.py +26 -8
  24. jaseci/prim/obj_mixins.py +5 -0
  25. jaseci/prim/sentinel.py +3 -1
  26. jaseci/prim/walker.py +7 -5
  27. jaseci/tests/jac_test_progs.py +9 -0
  28. jaseci/tests/test_jac.py +3 -3
  29. jaseci/tests/test_node.py +9 -12
  30. jaseci/tests/test_progs.py +16 -1
  31. jaseci/tests/test_stack.py +22 -0
  32. jaseci/utils/actions/actions_optimizer.py +23 -8
  33. jaseci/utils/gprof2dot.py +3786 -0
  34. jaseci/utils/json_handler.py +5 -1
  35. jaseci/utils/utils.py +52 -21
  36. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/METADATA +2 -2
  37. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/RECORD +41 -41
  38. jaseci/prim/item.py +0 -29
  39. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/LICENSE +0 -0
  40. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/WHEEL +0 -0
  41. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/entry_points.txt +0 -0
  42. {jaseci-1.4.0.18.dist-info → jaseci-1.4.0.20.dist-info}/top_level.txt +0 -0
jaseci/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0.18
1
+ 1.4.0.20
jaseci/cli_tools/jsctl.py CHANGED
@@ -17,6 +17,7 @@ from jaseci.utils.utils import copy_func
17
17
  from .book_tools import Book, modifiedBook
18
18
  from jaseci.utils.utils import logger, perf_test_start, perf_test_stop, find_first_api
19
19
  from jaseci.jsorc.jsorc import JsOrc
20
+ from prettytable import PrettyTable
20
21
 
21
22
  session = None
22
23
 
@@ -112,6 +113,39 @@ def resolve_none_type(kwargs):
112
113
  kwargs[i] = None
113
114
 
114
115
 
116
+ def has_profile(output):
117
+ if isinstance(output, dict):
118
+ if "profile" in output.keys():
119
+ if "jac" in output["profile"].keys() and "perf" in output["profile"].keys():
120
+ return True
121
+ return False
122
+
123
+
124
+ def gen_pretty_table(csv_str):
125
+ rows = csv_str.split("\n")
126
+ row_width = len(rows[0].split(","))
127
+ first_row = rows[0].split(",")
128
+ if first_row[2] == "percall":
129
+ first_row[2] = "percall_tot"
130
+ try:
131
+ table = PrettyTable(first_row)
132
+ for i in rows[1:]:
133
+ row = i.split(",")
134
+ if len(row) != row_width:
135
+ continue
136
+ table.add_row(row)
137
+ return table
138
+ except Exception as e:
139
+ click.echo(f"Something went wrong pretty printing profile: {e}")
140
+
141
+
142
+ def pretty_profile(output):
143
+ click.echo("Jac Code Profile:")
144
+ click.echo(gen_pretty_table(output["profile"]["jac"]))
145
+ click.echo("\nInternal Jaseci Profile:")
146
+ click.echo(gen_pretty_table(output["profile"]["perf"]))
147
+
148
+
115
149
  def interface_api(api_name, is_public, is_cli_only, **kwargs):
116
150
  """
117
151
  Interfaces Master apis after processing arguments/parameters
@@ -137,6 +171,7 @@ def interface_api(api_name, is_public, is_cli_only, **kwargs):
137
171
  out = session["master"].public_interface_to_api(kwargs, api_name)
138
172
  else:
139
173
  out = session["master"].general_interface_to_api(kwargs, api_name)
174
+ d_out = out
140
175
  if (
141
176
  isinstance(out, dict)
142
177
  and "report_custom" in out.keys()
@@ -153,6 +188,8 @@ def interface_api(api_name, is_public, is_cli_only, **kwargs):
153
188
  if not session["mem-only"]:
154
189
  with open(session["filename"], "wb") as f:
155
190
  pickle.dump(session, f)
191
+ if has_profile(d_out):
192
+ pretty_profile(d_out)
156
193
 
157
194
 
158
195
  def extract_api_tree():
@@ -384,20 +421,22 @@ def script(filename, profile, output):
384
421
  with open(output, "w") as f:
385
422
  f.write("Multi Command Script Output:\n")
386
423
  for i in cmds:
387
- res = CliRunner(mix_stderr=False).invoke(jsctl, i.split())
424
+ res = CliRunner(mix_stderr=False).invoke(jsctl, i)
388
425
  click.echo(res.stdout)
389
426
  if output:
390
427
  with open(output, "a") as f:
391
428
  f.write(f"Output for {i}:\n")
392
429
  f.write(res.stdout)
393
430
  if profile:
394
- perf = perf_test_stop(prof)
431
+ perf, graph = perf_test_stop(prof)
395
432
  click.echo(perf)
433
+ click.echo(graph)
396
434
  if output:
397
435
  with open(output, "a") as f:
398
436
  if profile:
399
437
  f.write(f"\nProfile:\n")
400
438
  f.write(perf)
439
+ f.write(graph)
401
440
  click.echo(f"[saved to {output}]")
402
441
 
403
442
 
@@ -506,6 +506,17 @@ class JsctlTest(TestCaseHelper, TestCase):
506
506
  ],
507
507
  )
508
508
 
509
+ def test_jsctl_pretty_profiles(self):
510
+ self.call(f"actions load local {self.infer_loc}")
511
+ r = self.call(
512
+ f"sentinel register "
513
+ f"{os.path.dirname(__file__)}/graph_can.jac -name gc -set_active true"
514
+ )
515
+ r = self.call("walker run go -profiling true")
516
+ self.assertIn("walker::go", r)
517
+ self.assertIn("cumtime", r)
518
+ self.assertIn("cum_time", r)
519
+
509
520
 
510
521
  class JsctlTestWithSession(TestCaseHelper, TestCase):
511
522
  """Unit tests for Jac language"""
@@ -14,4 +14,5 @@ def start_perf_test(name: str = "default"):
14
14
  def stop_perf_test(name: str = "default"):
15
15
  if name not in perf_tests.keys():
16
16
  return
17
- return perf_test_stop(perf_tests[name])
17
+ calls, graph = perf_test_stop(perf_tests[name])
18
+ return {"calls": calls, "graph": graph}
@@ -11,6 +11,7 @@ from jaseci.extens.svc.elastic_svc import Elastic
11
11
 
12
12
  import sys
13
13
  import json
14
+ import time
14
15
 
15
16
 
16
17
  @jaseci_action()
@@ -49,6 +50,12 @@ def err(*args):
49
50
  print(*args, file=sys.stderr)
50
51
 
51
52
 
53
+ @jaseci_action()
54
+ def sleep(secs: float):
55
+ """Standard built in for sleep"""
56
+ return time.sleep(secs)
57
+
58
+
52
59
  @jaseci_action()
53
60
  def sort_by_col(lst: list, col_num: int, reverse: bool = False):
54
61
  """
@@ -21,7 +21,9 @@ class StdLibTest(CoreTest):
21
21
  ret = self.call(self.mast, ["walker_run", {"name": "internal_lib"}])
22
22
  self.assertEqual(len(ret["report"]), 1)
23
23
  self.assertTrue(
24
- ret["report"][0].startswith("ncalls,tottime,percall,cumtime,percall,")
24
+ ret["report"][0]["calls"].startswith(
25
+ "ncalls,tottime,percall,cumtime,percall,"
26
+ )
25
27
  )
26
28
 
27
29
  def test_rand_float_round(self):
@@ -88,6 +88,37 @@ class JsOrcApi:
88
88
 
89
89
  return new_config
90
90
 
91
+ @Interface.admin_api()
92
+ def jsorc_refresh(self):
93
+ """
94
+ refreshing jsorc's config.
95
+ """
96
+
97
+ JsOrc.configure()
98
+
99
+ return {
100
+ "running_interval": JsOrc._running_interval,
101
+ "config": JsOrc._config,
102
+ }
103
+
104
+ @Interface.admin_api(cli_args=["name"])
105
+ def service_info(self, name: str):
106
+ """
107
+ getting service's info.
108
+ """
109
+
110
+ # will throw exception if not existing
111
+ svc = JsOrc.svc(name)
112
+
113
+ return {
114
+ "enabled": svc.enabled,
115
+ "automated": svc.automated,
116
+ "quiet": svc.quiet,
117
+ "state": svc.state.name,
118
+ "config": svc.config,
119
+ "error": str(svc.error) if svc.error else None,
120
+ }
121
+
91
122
  @Interface.admin_api(cli_args=["name"])
92
123
  def service_refresh(self, name: str):
93
124
  """
@@ -261,7 +292,16 @@ class JsOrcApi:
261
292
  return {"success": True, "policy": policy}
262
293
 
263
294
  @Interface.admin_api()
264
- def jsorc_loadtest(self, test: str, experiment: str = "", mem: int = 0):
295
+ def jsorc_loadtest(
296
+ self,
297
+ test: str,
298
+ experiment: str = "",
299
+ mem: int = 0,
300
+ policy: str = "all_local",
301
+ experiment_duration: int = 180,
302
+ eval_phase: int = 10,
303
+ perf_phase: int = 100,
304
+ ):
265
305
  """
266
306
  load test API. overwritten in jaseci_serv
267
307
  """
@@ -22,6 +22,11 @@ class WalkerApi:
22
22
  def __init__(self):
23
23
  self.spawned_walker_ids = IdList(self)
24
24
  self.yielded_walkers_ids = IdList(self)
25
+ self.reset_profiling(False)
26
+
27
+ def reset_profiling(self, profiling):
28
+ self._profiling = profiling
29
+ self._jac_profile = {}
25
30
 
26
31
  @Interface.private_api(cli_args=["wlk"])
27
32
  def walker_get(self, wlk: Walker, mode: str = "default", detailed: bool = False):
@@ -64,6 +69,7 @@ class WalkerApi:
64
69
  Creates new instance of walker and returns new walker object
65
70
  """
66
71
  wlk = snt.run_architype(name=name, kind="walker", caller=self, is_async=False)
72
+ wlk.make_persistent()
67
73
  if wlk:
68
74
  if self.spawned_walker_ids.has_obj_by_name(name):
69
75
  self.spawned_walker_ids.destroy_obj_by_name(name)
@@ -165,6 +171,7 @@ class WalkerApi:
165
171
  """
166
172
  Executes walker (assumes walker is primed)
167
173
  """
174
+ self.reset_profiling(profiling)
168
175
  return wlk.run(
169
176
  start_node=prime, prime_ctx=ctx, request_ctx=_req_ctx, profiling=profiling
170
177
  )
@@ -199,6 +206,7 @@ class WalkerApi:
199
206
  Creates walker instance, primes walker on node, executes walker,
200
207
  reports results, and cleans up walker instance.
201
208
  """
209
+ self.reset_profiling(profiling)
202
210
  wlk = self.yielded_walkers_ids.get_obj_by_name(name, silent=True)
203
211
  if wlk is None:
204
212
  wlk = snt.run_architype(
@@ -225,6 +233,7 @@ class WalkerApi:
225
233
  """
226
234
  Walker individual APIs
227
235
  """
236
+ self.reset_profiling(profiling)
228
237
  return self.walker_run(name, nd, ctx, _req_ctx, snt, profiling)
229
238
 
230
239
  @Interface.public_api(cli_args=["wlk"])
@@ -9,6 +9,7 @@ from jaseci.prim.edge import Edge
9
9
  from jaseci.prim.walker import Walker
10
10
  from jaseci.jac.interpreter.interp import Interp
11
11
  from jaseci.jac.machine.jac_scope import JacScope
12
+ from jaseci.jac.machine.jac_value import JacValue
12
13
 
13
14
 
14
15
  class ArchitypeInterp(Interp):
@@ -43,7 +44,7 @@ class ArchitypeInterp(Interp):
43
44
 
44
45
  kid = self.set_cur_ast(jac_ast)
45
46
 
46
- self.push_scope(JacScope(parent=self, has_obj=self, action_sets=[]))
47
+ self.push_scope(JacScope(parent=self, name=f"spawn:{jac_ast.loc_str()}"))
47
48
  if kid[0].name == "KW_NODE":
48
49
  item = Node(
49
50
  m_id=self._m_id,
@@ -78,6 +79,7 @@ class ArchitypeInterp(Interp):
78
79
  )
79
80
  if kid[2].name == "namespaces":
80
81
  item.namespaces = self.run_namespaces(jac_ast.kid[2])
82
+ self.build_object_with_supers(item, kid[-1])
81
83
  elif jac_ast.name == "graph_block": # usedi n jac tests
82
84
  item = self.run_graph_block(jac_ast)
83
85
  self.pop_scope()
@@ -89,6 +91,19 @@ class ArchitypeInterp(Interp):
89
91
  """
90
92
  return self.run_name_list(jac_ast.kid[1])
91
93
 
94
+ def run_walker_block(self, jac_ast, obj):
95
+ """
96
+ walker_block:
97
+ LBRACE attr_stmt* walk_entry_block? (
98
+ statement
99
+ | walk_activity_block
100
+ )* walk_exit_block? RBRACE;
101
+ """
102
+ kid = self.set_cur_ast(jac_ast)
103
+ for i in kid:
104
+ if i.name == "attr_stmt":
105
+ self.run_attr_stmt(jac_ast=i, obj=obj)
106
+
92
107
  def run_attr_block(self, jac_ast, obj):
93
108
  """
94
109
  attr_block:
@@ -101,52 +116,68 @@ class ArchitypeInterp(Interp):
101
116
  if i.name == "attr_stmt":
102
117
  self.run_attr_stmt(i, obj)
103
118
 
104
- def run_struct_block(self, jac_ast):
119
+ def run_attr_stmt(self, jac_ast, obj):
105
120
  """
106
- struct_block: LBRACE (has_stmt)* RBRACE | COLON has_stmt | SEMI;
121
+ attr_stmt: has_stmt | can_stmt;
107
122
  """
108
123
  kid = self.set_cur_ast(jac_ast)
109
- ret = {}
110
- for i in kid:
111
- if i.name == "has_stmt":
112
- self.run_has_stmt(i, ret)
113
- return ret
124
+ if kid[0].name == "has_stmt":
125
+ self.run_has_stmt(kid[0], obj)
126
+ # Can statements in architype handled in architype load
114
127
 
115
- def run_can_block(self, jac_ast):
128
+ def run_has_stmt(self, jac_ast, obj):
116
129
  """
117
- can_block: (can_stmt)*;
130
+ has_stmt: KW_HAS has_assign (COMMA has_assign)* SEMI;
118
131
  """
119
132
  kid = self.set_cur_ast(jac_ast)
120
133
  for i in kid:
121
- if i.name == "can_stmt":
122
- self.run_can_stmt(i, self)
134
+ if i.name == "has_assign":
135
+ self.run_has_assign(i, obj)
123
136
 
124
- def run_graph_block(self, jac_ast):
137
+ def run_has_assign(self, jac_ast, obj):
125
138
  """
126
- graph_block: graph_block_spawn;
139
+ has_assign: KW_PRIVATE? KW_ANCHOR? (NAME | NAME EQ expression);
127
140
  """
128
141
  kid = self.set_cur_ast(jac_ast)
129
- return getattr(self, f"run_{kid[0].name}")(kid[0])
142
+ while kid[0].name in ["KW_PRIVATE", "KW_ANCHOR"]:
143
+ kid = kid[1:]
144
+ var_name = kid[0].token_text()
145
+ var_val = None # jac's null
146
+ if len(kid) > 1:
147
+ self.run_expression(kid[2])
148
+ var_val = self.pop().value
149
+ if isinstance(obj, dict):
150
+ obj[var_name] = var_val
151
+ # Runs only once for walkers
152
+ elif var_name not in obj.context.keys() or obj.j_type != "walker":
153
+ JacValue(
154
+ self, ctx=obj, name=var_name, value=var_val, create_mode=True
155
+ ).write(kid[0], force=True)
130
156
 
131
- def run_graph_block_spawn(self, jac_ast):
157
+ def run_struct_block(self, jac_ast):
158
+ """
159
+ struct_block: LBRACE (has_stmt)* RBRACE | COLON has_stmt | SEMI;
160
+ """
161
+ kid = self.set_cur_ast(jac_ast)
162
+ ret = {}
163
+ for i in kid:
164
+ if i.name == "has_stmt":
165
+ self.run_has_stmt(i, ret)
166
+ return ret
167
+
168
+ def run_graph_block(self, jac_ast):
132
169
  """
133
- graph_block_spawn:
170
+ graph_block:
134
171
  LBRACE has_root can_block KW_SPAWN code_block RBRACE
135
172
  | COLON has_root can_block KW_SPAWN code_block SEMI;
136
173
  """
137
174
  kid = self.set_cur_ast(jac_ast)
138
175
  root_name = self.run_has_root(kid[1])
139
- self.run_can_block(kid[2])
140
- m = Interp(parent_override=self.parent(), caller=self)
141
- m.push_scope(
142
- JacScope(parent=self, has_obj=None, action_sets=[self.activity_action_ids])
143
- )
144
176
  try:
145
- m.run_code_block(kid[4])
177
+ self.run_code_block(kid[4])
146
178
  except Exception as e:
147
- self.rt_error(f"Internal Exception: {e}", m._cur_jac_ast)
148
- local_state = m._jac_scope.local_scope
149
- self.report = self.report + m.report
179
+ self.rt_error(f"Internal Exception: {e}", self._cur_jac_ast)
180
+ local_state = self._jac_scope.local_scope
150
181
  if root_name in local_state.keys():
151
182
  obj = local_state[root_name]
152
183
  if not isinstance(obj, Node):
@@ -173,5 +204,9 @@ class ArchitypeInterp(Interp):
173
204
  .get_jac_ast()
174
205
  .kid[-1]
175
206
  )
176
- self.run_attr_block(super_jac_ast, item)
177
- self.run_attr_block(jac_ast, item)
207
+ self.run_attr_block(super_jac_ast, item) if not isinstance(
208
+ item, Walker
209
+ ) else self.run_walker_block(super_jac_ast, item)
210
+ self.run_attr_block(jac_ast, item) if not isinstance(
211
+ item, Walker
212
+ ) else self.run_walker_block(jac_ast, item)