jaclang 0.7.25__py3-none-any.whl → 0.7.27__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 jaclang might be problematic. Click here for more details.
- jaclang/compiler/absyntree.py +27 -18
- jaclang/compiler/jac.lark +4 -1
- jaclang/compiler/parser.py +37 -20
- jaclang/compiler/passes/main/def_impl_match_pass.py +50 -13
- jaclang/compiler/passes/main/def_use_pass.py +1 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +46 -20
- jaclang/compiler/passes/main/pyast_load_pass.py +20 -6
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -2
- jaclang/compiler/passes/main/tests/fixtures/uninitialized_hasvars.jac +26 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +36 -29
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +3 -3
- jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- jaclang/compiler/tests/test_parser.py +7 -1
- jaclang/plugin/default.py +64 -18
- jaclang/plugin/feature.py +16 -1
- jaclang/plugin/spec.py +14 -2
- jaclang/plugin/tests/fixtures/graph_purger.jac +101 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +19 -0
- jaclang/plugin/tests/fixtures/savable_object.jac +84 -0
- jaclang/plugin/tests/test_jaseci.py +214 -6
- jaclang/runtimelib/architype.py +29 -1
- jaclang/runtimelib/memory.py +27 -8
- jaclang/runtimelib/utils.py +16 -0
- jaclang/tests/fixtures/architype_def_bug.jac +17 -0
- jaclang/tests/fixtures/decl_defn_param_name.jac +19 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +19 -0
- jaclang/tests/test_cli.py +18 -0
- jaclang/tests/test_language.py +43 -0
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/METADATA +1 -1
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/RECORD +34 -28
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/WHEEL +0 -0
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/entry_points.txt +0 -0
jaclang/plugin/default.py
CHANGED
|
@@ -11,7 +11,7 @@ from collections import OrderedDict
|
|
|
11
11
|
from dataclasses import field
|
|
12
12
|
from functools import wraps
|
|
13
13
|
from logging import getLogger
|
|
14
|
-
from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union
|
|
14
|
+
from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union, cast
|
|
15
15
|
from uuid import UUID
|
|
16
16
|
|
|
17
17
|
from jaclang.compiler.constant import colors
|
|
@@ -41,6 +41,7 @@ from jaclang.runtimelib.constructs import (
|
|
|
41
41
|
)
|
|
42
42
|
from jaclang.runtimelib.importer import ImportPathSpec, JacImporter, PythonImporter
|
|
43
43
|
from jaclang.runtimelib.machine import JacMachine, JacProgram
|
|
44
|
+
from jaclang.runtimelib.memory import Shelf, ShelfStorage
|
|
44
45
|
from jaclang.runtimelib.utils import collect_node_connections, traverse_graph
|
|
45
46
|
|
|
46
47
|
|
|
@@ -50,9 +51,30 @@ hookimpl = pluggy.HookimplMarker("jac")
|
|
|
50
51
|
logger = getLogger(__name__)
|
|
51
52
|
|
|
52
53
|
|
|
54
|
+
class JacCallableImplementation:
|
|
55
|
+
"""Callable Implementations."""
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def get_object(id: str) -> Architype | None:
|
|
59
|
+
"""Get object by id."""
|
|
60
|
+
if id == "root":
|
|
61
|
+
return Jac.get_context().root.architype
|
|
62
|
+
elif obj := Jac.get_context().mem.find_by_id(UUID(id)):
|
|
63
|
+
return obj.architype
|
|
64
|
+
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
53
68
|
class JacAccessValidationImpl:
|
|
54
69
|
"""Jac Access Validation Implementations."""
|
|
55
70
|
|
|
71
|
+
@staticmethod
|
|
72
|
+
@hookimpl
|
|
73
|
+
def elevate_root() -> None:
|
|
74
|
+
"""Elevate context root to system_root."""
|
|
75
|
+
jctx = Jac.get_context()
|
|
76
|
+
jctx.root = jctx.system_root
|
|
77
|
+
|
|
56
78
|
@staticmethod
|
|
57
79
|
@hookimpl
|
|
58
80
|
def allow_root(
|
|
@@ -379,7 +401,8 @@ class JacWalkerImpl:
|
|
|
379
401
|
if walker.next:
|
|
380
402
|
current_node = walker.next[-1].architype
|
|
381
403
|
for i in warch._jac_entry_funcs_:
|
|
382
|
-
|
|
404
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
405
|
+
if not trigger:
|
|
383
406
|
if i.func:
|
|
384
407
|
i.func(warch, current_node)
|
|
385
408
|
else:
|
|
@@ -387,7 +410,8 @@ class JacWalkerImpl:
|
|
|
387
410
|
while len(walker.next):
|
|
388
411
|
if current_node := walker.next.pop(0).architype:
|
|
389
412
|
for i in current_node._jac_entry_funcs_:
|
|
390
|
-
|
|
413
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
414
|
+
if not trigger or isinstance(warch, trigger):
|
|
391
415
|
if i.func:
|
|
392
416
|
i.func(current_node, warch)
|
|
393
417
|
else:
|
|
@@ -395,27 +419,30 @@ class JacWalkerImpl:
|
|
|
395
419
|
if walker.disengaged:
|
|
396
420
|
return warch
|
|
397
421
|
for i in warch._jac_entry_funcs_:
|
|
398
|
-
|
|
399
|
-
|
|
422
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
423
|
+
if not trigger or isinstance(current_node, trigger):
|
|
424
|
+
if i.func and trigger:
|
|
400
425
|
i.func(warch, current_node)
|
|
401
|
-
elif not
|
|
426
|
+
elif not trigger:
|
|
402
427
|
continue
|
|
403
428
|
else:
|
|
404
429
|
raise ValueError(f"No function {i.name} to call.")
|
|
405
430
|
if walker.disengaged:
|
|
406
431
|
return warch
|
|
407
432
|
for i in warch._jac_exit_funcs_:
|
|
408
|
-
|
|
409
|
-
|
|
433
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
434
|
+
if not trigger or isinstance(current_node, trigger):
|
|
435
|
+
if i.func and trigger:
|
|
410
436
|
i.func(warch, current_node)
|
|
411
|
-
elif not
|
|
437
|
+
elif not trigger:
|
|
412
438
|
continue
|
|
413
439
|
else:
|
|
414
440
|
raise ValueError(f"No function {i.name} to call.")
|
|
415
441
|
if walker.disengaged:
|
|
416
442
|
return warch
|
|
417
443
|
for i in current_node._jac_exit_funcs_:
|
|
418
|
-
|
|
444
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
445
|
+
if not trigger or isinstance(warch, trigger):
|
|
419
446
|
if i.func:
|
|
420
447
|
i.func(current_node, warch)
|
|
421
448
|
else:
|
|
@@ -423,7 +450,8 @@ class JacWalkerImpl:
|
|
|
423
450
|
if walker.disengaged:
|
|
424
451
|
return warch
|
|
425
452
|
for i in warch._jac_exit_funcs_:
|
|
426
|
-
|
|
453
|
+
trigger = i.get_funcparam_annotations(i.func)
|
|
454
|
+
if not trigger:
|
|
427
455
|
if i.func:
|
|
428
456
|
i.func(warch, current_node)
|
|
429
457
|
else:
|
|
@@ -562,14 +590,32 @@ class JacFeatureImpl(
|
|
|
562
590
|
|
|
563
591
|
@staticmethod
|
|
564
592
|
@hookimpl
|
|
565
|
-
def
|
|
566
|
-
"""
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
593
|
+
def reset_graph(root: Optional[Root] = None) -> int:
|
|
594
|
+
"""Purge current or target graph."""
|
|
595
|
+
ctx = Jac.get_context()
|
|
596
|
+
mem = cast(ShelfStorage, ctx.mem)
|
|
597
|
+
ranchor = root.__jac__ if root else ctx.root
|
|
598
|
+
|
|
599
|
+
deleted_count = 0
|
|
600
|
+
for anchor in (
|
|
601
|
+
anchors.values()
|
|
602
|
+
if isinstance(anchors := mem.__shelf__, Shelf)
|
|
603
|
+
else mem.__mem__.values()
|
|
604
|
+
):
|
|
605
|
+
if anchor == ranchor or anchor.root != ranchor.id:
|
|
606
|
+
continue
|
|
571
607
|
|
|
572
|
-
|
|
608
|
+
if loaded_anchor := mem.find_by_id(anchor.id):
|
|
609
|
+
deleted_count += 1
|
|
610
|
+
Jac.destroy(loaded_anchor)
|
|
611
|
+
|
|
612
|
+
return deleted_count
|
|
613
|
+
|
|
614
|
+
@staticmethod
|
|
615
|
+
@hookimpl
|
|
616
|
+
def get_object_func() -> Callable[[str], Architype | None]:
|
|
617
|
+
"""Get object by id func."""
|
|
618
|
+
return JacCallableImplementation.get_object
|
|
573
619
|
|
|
574
620
|
@staticmethod
|
|
575
621
|
@hookimpl
|
jaclang/plugin/feature.py
CHANGED
|
@@ -41,6 +41,11 @@ from jaclang.plugin.spec import (
|
|
|
41
41
|
class JacAccessValidation:
|
|
42
42
|
"""Jac Access Validation Specs."""
|
|
43
43
|
|
|
44
|
+
@staticmethod
|
|
45
|
+
def elevate_root() -> None:
|
|
46
|
+
"""Elevate context root to system_root."""
|
|
47
|
+
plugin_manager.hook.elevate_root()
|
|
48
|
+
|
|
44
49
|
@staticmethod
|
|
45
50
|
def allow_root(
|
|
46
51
|
architype: Architype,
|
|
@@ -254,10 +259,20 @@ class JacFeature(
|
|
|
254
259
|
"""Get current execution context."""
|
|
255
260
|
return plugin_manager.hook.get_context()
|
|
256
261
|
|
|
262
|
+
@staticmethod
|
|
263
|
+
def reset_graph(root: Optional[Root] = None) -> int:
|
|
264
|
+
"""Purge current or target graph."""
|
|
265
|
+
return plugin_manager.hook.reset_graph(root=root)
|
|
266
|
+
|
|
257
267
|
@staticmethod
|
|
258
268
|
def get_object(id: str) -> Architype | None:
|
|
259
269
|
"""Get object given id."""
|
|
260
|
-
return plugin_manager.hook.
|
|
270
|
+
return plugin_manager.hook.get_object_func()(id=id)
|
|
271
|
+
|
|
272
|
+
@staticmethod
|
|
273
|
+
def get_object_func() -> Callable[[str], Architype | None]:
|
|
274
|
+
"""Get object given id."""
|
|
275
|
+
return plugin_manager.hook.get_object_func()
|
|
261
276
|
|
|
262
277
|
@staticmethod
|
|
263
278
|
def object_ref(obj: Architype) -> str:
|
jaclang/plugin/spec.py
CHANGED
|
@@ -46,6 +46,12 @@ P = ParamSpec("P")
|
|
|
46
46
|
class JacAccessValidationSpec:
|
|
47
47
|
"""Jac Access Validation Specs."""
|
|
48
48
|
|
|
49
|
+
@staticmethod
|
|
50
|
+
@hookspec(firstresult=True)
|
|
51
|
+
def elevate_root() -> None:
|
|
52
|
+
"""Elevate context root to system_root."""
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
49
55
|
@staticmethod
|
|
50
56
|
@hookspec(firstresult=True)
|
|
51
57
|
def allow_root(
|
|
@@ -246,8 +252,14 @@ class JacFeatureSpec(
|
|
|
246
252
|
|
|
247
253
|
@staticmethod
|
|
248
254
|
@hookspec(firstresult=True)
|
|
249
|
-
def
|
|
250
|
-
"""
|
|
255
|
+
def reset_graph(root: Optional[Root]) -> int:
|
|
256
|
+
"""Purge current or target graph."""
|
|
257
|
+
raise NotImplementedError
|
|
258
|
+
|
|
259
|
+
@staticmethod
|
|
260
|
+
@hookspec(firstresult=True)
|
|
261
|
+
def get_object_func() -> Callable[[str], Architype | None]:
|
|
262
|
+
"""Get object by id func."""
|
|
251
263
|
raise NotImplementedError
|
|
252
264
|
|
|
253
265
|
@staticmethod
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
node A {
|
|
2
|
+
has id: int;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
node B {
|
|
6
|
+
has id: int;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
node C {
|
|
10
|
+
has id: int;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
node D {
|
|
14
|
+
has id: int;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
node E {
|
|
18
|
+
has id: int;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
walker populate {
|
|
23
|
+
can setup1 with `root entry {
|
|
24
|
+
for i in range(2) {
|
|
25
|
+
here ++> A(id=i);
|
|
26
|
+
}
|
|
27
|
+
visit [-->];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
can setup2 with A entry {
|
|
31
|
+
for i in range(2) {
|
|
32
|
+
here ++> B(id=i);
|
|
33
|
+
}
|
|
34
|
+
visit [-->];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
can setup3 with B entry {
|
|
38
|
+
for i in range(2) {
|
|
39
|
+
here ++> C(id=i);
|
|
40
|
+
}
|
|
41
|
+
visit [-->];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
can setup4 with C entry {
|
|
45
|
+
for i in range(2) {
|
|
46
|
+
here ++> D(id=i);
|
|
47
|
+
}
|
|
48
|
+
visit [-->];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
can setup5 with D entry {
|
|
52
|
+
for i in range(2) {
|
|
53
|
+
here ++> E(id=i);
|
|
54
|
+
}
|
|
55
|
+
visit [-->];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
walker traverse {
|
|
60
|
+
can enter1 with `root entry {
|
|
61
|
+
print(here);
|
|
62
|
+
visit [-->];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
can enter2 with A entry {
|
|
66
|
+
print(here);
|
|
67
|
+
visit [-->];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
can enter3 with B entry {
|
|
71
|
+
print(here);
|
|
72
|
+
visit [-->];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
can enter4 with C entry {
|
|
76
|
+
print(here);
|
|
77
|
+
visit [-->];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
can enter5 with D entry {
|
|
81
|
+
print(here);
|
|
82
|
+
visit [-->];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
can enter6 with E entry {
|
|
86
|
+
print(here);
|
|
87
|
+
visit [-->];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
walker purge {
|
|
92
|
+
can purge with `root entry {
|
|
93
|
+
print(Jac.reset_graph());
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
walker check {
|
|
98
|
+
can enter with `root entry {
|
|
99
|
+
print(len(Jac.get_context().mem.__shelf__.values()));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -23,6 +23,25 @@ walker update_node {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
walker update_target_node {
|
|
27
|
+
has val: int;
|
|
28
|
+
has node_id: str;
|
|
29
|
+
|
|
30
|
+
can enter with `root entry {
|
|
31
|
+
target_node = &(self.node_id);
|
|
32
|
+
target_node.val = self.val;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
walker update_node_forced {
|
|
37
|
+
has val: int;
|
|
38
|
+
|
|
39
|
+
can enter2 with A entry {
|
|
40
|
+
Jac.elevate_root();
|
|
41
|
+
here.val = self.val;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
walker create_node {
|
|
27
46
|
has val: int;
|
|
28
47
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
enum Enum {
|
|
2
|
+
A = "a",
|
|
3
|
+
B = "b",
|
|
4
|
+
C = "c"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
obj Child {
|
|
8
|
+
has val: int, arr: list[int], json: dict[str, int], enum_field: Enum;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
obj Parent:Child: {
|
|
12
|
+
has child: Child;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
obj SavableObject {
|
|
16
|
+
has val: int, arr: list[int], json: dict[str, int], parent: Parent, enum_field: Enum;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
walker create_custom_object {
|
|
20
|
+
can enter1 with `root entry {
|
|
21
|
+
o = SavableObject(
|
|
22
|
+
val=0,
|
|
23
|
+
arr=[],
|
|
24
|
+
json={},
|
|
25
|
+
parent=Parent(
|
|
26
|
+
val=1,
|
|
27
|
+
arr=[1],
|
|
28
|
+
json={"a": 1},
|
|
29
|
+
child=Child(
|
|
30
|
+
val=2,
|
|
31
|
+
arr=[1, 2],
|
|
32
|
+
json={"a": 1, "b": 2},
|
|
33
|
+
enum_field = Enum.C
|
|
34
|
+
),
|
|
35
|
+
enum_field = Enum.B
|
|
36
|
+
),
|
|
37
|
+
enum_field = Enum.A
|
|
38
|
+
);
|
|
39
|
+
Jac.save(o);
|
|
40
|
+
print(jid(o));
|
|
41
|
+
print(o);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
walker get_custom_object {
|
|
46
|
+
has object_id: str;
|
|
47
|
+
|
|
48
|
+
can enter1 with `root entry {
|
|
49
|
+
try {
|
|
50
|
+
print(&(self.object_id));
|
|
51
|
+
} except Exception as e {
|
|
52
|
+
print(None);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
walker update_custom_object {
|
|
58
|
+
has object_id: str;
|
|
59
|
+
|
|
60
|
+
can enter1 with `root entry {
|
|
61
|
+
savable_object = &(self.object_id);
|
|
62
|
+
savable_object.parent.child.json["c"] = 3;
|
|
63
|
+
savable_object.parent.child.arr.append(3);
|
|
64
|
+
savable_object.parent.child.val = 3;
|
|
65
|
+
savable_object.parent.child.enum_field = Enum.A;
|
|
66
|
+
savable_object.parent.json["b"] = 2;
|
|
67
|
+
savable_object.parent.arr.append(2);
|
|
68
|
+
savable_object.parent.val = 2;
|
|
69
|
+
savable_object.parent.enum_field = Enum.C;
|
|
70
|
+
savable_object.json["a"] = 1;
|
|
71
|
+
savable_object.arr.append(1);
|
|
72
|
+
savable_object.val = 1;
|
|
73
|
+
savable_object.enum_field = Enum.B;
|
|
74
|
+
print(savable_object);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
walker delete_custom_object {
|
|
79
|
+
has object_id: str;
|
|
80
|
+
|
|
81
|
+
can enter1 with `root entry {
|
|
82
|
+
Jac.destroy(&(self.object_id));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -269,6 +269,75 @@ class TestJaseciPlugin(TestCase):
|
|
|
269
269
|
)
|
|
270
270
|
self._del_session(session)
|
|
271
271
|
|
|
272
|
+
def test_walker_purger(self) -> None:
|
|
273
|
+
"""Test simple persistent object."""
|
|
274
|
+
session = self.fixture_abs_path("test_walker_purger.session")
|
|
275
|
+
self._output2buffer()
|
|
276
|
+
cli.enter(
|
|
277
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
278
|
+
session=session,
|
|
279
|
+
entrypoint="populate",
|
|
280
|
+
args=[],
|
|
281
|
+
)
|
|
282
|
+
cli.enter(
|
|
283
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
284
|
+
session=session,
|
|
285
|
+
entrypoint="traverse",
|
|
286
|
+
args=[],
|
|
287
|
+
)
|
|
288
|
+
cli.enter(
|
|
289
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
290
|
+
session=session,
|
|
291
|
+
entrypoint="check",
|
|
292
|
+
args=[],
|
|
293
|
+
)
|
|
294
|
+
cli.enter(
|
|
295
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
296
|
+
session=session,
|
|
297
|
+
entrypoint="purge",
|
|
298
|
+
args=[],
|
|
299
|
+
)
|
|
300
|
+
output = self.capturedOutput.getvalue().strip()
|
|
301
|
+
self.assertEqual(
|
|
302
|
+
output,
|
|
303
|
+
(
|
|
304
|
+
"Root()\n"
|
|
305
|
+
"A(id=0)\nA(id=1)\n"
|
|
306
|
+
"B(id=0)\nB(id=1)\nB(id=0)\nB(id=1)\n"
|
|
307
|
+
"C(id=0)\nC(id=1)\nC(id=0)\nC(id=1)\nC(id=0)\nC(id=1)\nC(id=0)\nC(id=1)\n"
|
|
308
|
+
"D(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\n"
|
|
309
|
+
"D(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\nD(id=0)\nD(id=1)\n"
|
|
310
|
+
"E(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\n"
|
|
311
|
+
"E(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\n"
|
|
312
|
+
"E(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\n"
|
|
313
|
+
"E(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\nE(id=0)\nE(id=1)\n"
|
|
314
|
+
"125\n124"
|
|
315
|
+
),
|
|
316
|
+
)
|
|
317
|
+
self._output2buffer()
|
|
318
|
+
cli.enter(
|
|
319
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
320
|
+
session=session,
|
|
321
|
+
entrypoint="traverse",
|
|
322
|
+
args=[],
|
|
323
|
+
)
|
|
324
|
+
cli.enter(
|
|
325
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
326
|
+
session=session,
|
|
327
|
+
entrypoint="check",
|
|
328
|
+
args=[],
|
|
329
|
+
)
|
|
330
|
+
cli.enter(
|
|
331
|
+
filename=self.fixture_abs_path("graph_purger.jac"),
|
|
332
|
+
session=session,
|
|
333
|
+
entrypoint="purge",
|
|
334
|
+
args=[],
|
|
335
|
+
)
|
|
336
|
+
output = self.capturedOutput.getvalue().strip()
|
|
337
|
+
self.assertEqual(output, "Root()\n1\n0")
|
|
338
|
+
|
|
339
|
+
self._del_session(session)
|
|
340
|
+
|
|
272
341
|
def trigger_access_validation_test(
|
|
273
342
|
self, give_access_to_full_graph: bool, via_all: bool = False
|
|
274
343
|
) -> None:
|
|
@@ -316,6 +385,22 @@ class TestJaseciPlugin(TestCase):
|
|
|
316
385
|
node=self.nodes[0],
|
|
317
386
|
)
|
|
318
387
|
|
|
388
|
+
cli.enter(
|
|
389
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
390
|
+
entrypoint="update_target_node",
|
|
391
|
+
args=[20, self.nodes[1]],
|
|
392
|
+
session=session,
|
|
393
|
+
root=self.roots[0],
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
cli.enter(
|
|
397
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
398
|
+
entrypoint="update_target_node",
|
|
399
|
+
args=[10, self.nodes[0]],
|
|
400
|
+
session=session,
|
|
401
|
+
root=self.roots[1],
|
|
402
|
+
)
|
|
403
|
+
|
|
319
404
|
cli.enter(
|
|
320
405
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
321
406
|
entrypoint="check_node",
|
|
@@ -340,6 +425,55 @@ class TestJaseciPlugin(TestCase):
|
|
|
340
425
|
self.assertEqual(archs[0], "A(val=2)")
|
|
341
426
|
self.assertEqual(archs[1], "A(val=1)")
|
|
342
427
|
|
|
428
|
+
##############################################
|
|
429
|
+
# WITH READ ACCESS BUT ELEVATED #
|
|
430
|
+
##############################################
|
|
431
|
+
|
|
432
|
+
self._output2buffer()
|
|
433
|
+
|
|
434
|
+
cli.enter(
|
|
435
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
436
|
+
entrypoint="update_node_forced",
|
|
437
|
+
args=[20],
|
|
438
|
+
session=session,
|
|
439
|
+
root=self.roots[0],
|
|
440
|
+
node=self.nodes[1],
|
|
441
|
+
)
|
|
442
|
+
cli.enter(
|
|
443
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
444
|
+
entrypoint="update_node_forced",
|
|
445
|
+
args=[10],
|
|
446
|
+
session=session,
|
|
447
|
+
root=self.roots[1],
|
|
448
|
+
node=self.nodes[0],
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
cli.enter(
|
|
452
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
453
|
+
entrypoint="check_node",
|
|
454
|
+
args=[],
|
|
455
|
+
session=session,
|
|
456
|
+
root=self.roots[0],
|
|
457
|
+
node=self.nodes[1],
|
|
458
|
+
)
|
|
459
|
+
cli.enter(
|
|
460
|
+
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
461
|
+
entrypoint="check_node",
|
|
462
|
+
args=[],
|
|
463
|
+
session=session,
|
|
464
|
+
root=self.roots[1],
|
|
465
|
+
node=self.nodes[0],
|
|
466
|
+
)
|
|
467
|
+
archs = self.capturedOutput.getvalue().strip().split("\n")
|
|
468
|
+
self.assertTrue(len(archs) == 2)
|
|
469
|
+
|
|
470
|
+
# ---------- UPDATE SHOULD HAPPEN ---------- #
|
|
471
|
+
|
|
472
|
+
self.assertEqual(archs[0], "A(val=20)")
|
|
473
|
+
self.assertEqual(archs[1], "A(val=10)")
|
|
474
|
+
|
|
475
|
+
# ---------- DISALLOW READ ACCESS ---------- #
|
|
476
|
+
|
|
343
477
|
self._output2buffer()
|
|
344
478
|
cli.enter(
|
|
345
479
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
@@ -400,7 +534,7 @@ class TestJaseciPlugin(TestCase):
|
|
|
400
534
|
cli.enter(
|
|
401
535
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
402
536
|
entrypoint="update_node",
|
|
403
|
-
args=[
|
|
537
|
+
args=[200],
|
|
404
538
|
root=self.roots[0],
|
|
405
539
|
node=self.nodes[1],
|
|
406
540
|
session=session,
|
|
@@ -408,7 +542,7 @@ class TestJaseciPlugin(TestCase):
|
|
|
408
542
|
cli.enter(
|
|
409
543
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
410
544
|
entrypoint="update_node",
|
|
411
|
-
args=[
|
|
545
|
+
args=[100],
|
|
412
546
|
session=session,
|
|
413
547
|
root=self.roots[1],
|
|
414
548
|
node=self.nodes[0],
|
|
@@ -433,10 +567,12 @@ class TestJaseciPlugin(TestCase):
|
|
|
433
567
|
archs = self.capturedOutput.getvalue().strip().split("\n")
|
|
434
568
|
self.assertTrue(len(archs) == 2)
|
|
435
569
|
|
|
436
|
-
#
|
|
570
|
+
# ---------- UPDATE SHOULD HAPPEN ---------- #
|
|
437
571
|
|
|
438
|
-
self.assertEqual(archs[0], "A(val=
|
|
439
|
-
self.assertEqual(archs[1], "A(val=
|
|
572
|
+
self.assertEqual(archs[0], "A(val=200)")
|
|
573
|
+
self.assertEqual(archs[1], "A(val=100)")
|
|
574
|
+
|
|
575
|
+
# ---------- DISALLOW WRITE ACCESS --------- #
|
|
440
576
|
|
|
441
577
|
self._output2buffer()
|
|
442
578
|
cli.enter(
|
|
@@ -474,7 +610,7 @@ class TestJaseciPlugin(TestCase):
|
|
|
474
610
|
)
|
|
475
611
|
self.assertFalse(self.capturedOutput.getvalue().strip())
|
|
476
612
|
|
|
477
|
-
#
|
|
613
|
+
# ---------- ROOTS RESET OWN NODE ---------- #
|
|
478
614
|
|
|
479
615
|
cli.enter(
|
|
480
616
|
filename=self.fixture_abs_path("other_root_access.jac"),
|
|
@@ -608,3 +744,75 @@ class TestJaseciPlugin(TestCase):
|
|
|
608
744
|
)
|
|
609
745
|
|
|
610
746
|
self._del_session(session)
|
|
747
|
+
|
|
748
|
+
def test_savable_object(self) -> None:
|
|
749
|
+
"""Test ObjectAnchor save."""
|
|
750
|
+
global session
|
|
751
|
+
session = self.fixture_abs_path("other_root_access.session")
|
|
752
|
+
|
|
753
|
+
self._output2buffer()
|
|
754
|
+
|
|
755
|
+
cli.enter(
|
|
756
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
757
|
+
entrypoint="create_custom_object",
|
|
758
|
+
args=[],
|
|
759
|
+
session=session,
|
|
760
|
+
)
|
|
761
|
+
|
|
762
|
+
prints = self.capturedOutput.getvalue().strip().split("\n")
|
|
763
|
+
id = prints[0]
|
|
764
|
+
|
|
765
|
+
self.assertEqual(
|
|
766
|
+
"SavableObject(val=0, arr=[], json={}, parent=Parent(val=1, arr=[1], json"
|
|
767
|
+
"={'a': 1}, enum_field=<Enum.B: 'b'>, child=Child(val=2, arr=[1, 2], json"
|
|
768
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>)), enum_field=<Enum.A: 'a'>)",
|
|
769
|
+
prints[1],
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
self._output2buffer()
|
|
773
|
+
|
|
774
|
+
cli.enter(
|
|
775
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
776
|
+
entrypoint="get_custom_object",
|
|
777
|
+
args=[id],
|
|
778
|
+
session=session,
|
|
779
|
+
)
|
|
780
|
+
self.assertEqual(
|
|
781
|
+
"SavableObject(val=0, arr=[], json={}, parent=Parent(val=1, arr=[1], json"
|
|
782
|
+
"={'a': 1}, enum_field=<Enum.B: 'b'>, child=Child(val=2, arr=[1, 2], json"
|
|
783
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>)), enum_field=<Enum.A: 'a'>)",
|
|
784
|
+
self.capturedOutput.getvalue().strip(),
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
self._output2buffer()
|
|
788
|
+
|
|
789
|
+
cli.enter(
|
|
790
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
791
|
+
entrypoint="update_custom_object",
|
|
792
|
+
args=[id],
|
|
793
|
+
session=session,
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
self.assertEqual(
|
|
797
|
+
"SavableObject(val=1, arr=[1], json={'a': 1}, parent=Parent(val=2, arr=[1, 2], json"
|
|
798
|
+
"={'a': 1, 'b': 2}, enum_field=<Enum.C: 'c'>, child=Child(val=3, arr=[1, 2, 3], json"
|
|
799
|
+
"={'a': 1, 'b': 2, 'c': 3}, enum_field=<Enum.A: 'a'>)), enum_field=<Enum.B: 'b'>)",
|
|
800
|
+
self.capturedOutput.getvalue().strip(),
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
self._output2buffer()
|
|
804
|
+
|
|
805
|
+
cli.enter(
|
|
806
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
807
|
+
entrypoint="delete_custom_object",
|
|
808
|
+
args=[id],
|
|
809
|
+
session=session,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
cli.enter(
|
|
813
|
+
filename=self.fixture_abs_path("savable_object.jac"),
|
|
814
|
+
entrypoint="get_custom_object",
|
|
815
|
+
args=[id],
|
|
816
|
+
session=session,
|
|
817
|
+
)
|
|
818
|
+
self.assertEqual("None", self.capturedOutput.getvalue().strip())
|