Skip to content

Commit

Permalink
migration
Browse files Browse the repository at this point in the history
  • Loading branch information
amadolid committed Sep 16, 2024
1 parent 78726cf commit 382f6cd
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 209 deletions.
4 changes: 3 additions & 1 deletion jac/jaclang/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,9 @@ def enter(

jctx.set_entry_node(node)

if isinstance(architype, WalkerArchitype) and jctx.validate_access():
if isinstance(architype, WalkerArchitype) and Jac.check_read_access(
jctx.entry_node
):
Jac.spawn_call(jctx.entry_node.architype, architype)

jctx.close()
Expand Down
117 changes: 109 additions & 8 deletions jac/jaclang/plugin/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
)
from jaclang.runtimelib.importer import ImportPathSpec, JacImporter, PythonImporter
from jaclang.runtimelib.machine import JacMachine, JacProgram
from jaclang.runtimelib.utils import traverse_graph
from jaclang.runtimelib.utils import collect_node_connections, traverse_graph


import pluggy
Expand All @@ -54,6 +54,47 @@
class JacAccessValidationImpl:
"""Jac Access Validation Implementations."""

@staticmethod
@hookimpl
def allow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow all access from target root graph to current Architype."""
level = AccessLevel.cast(level)
access = anchor.access.roots

_root_id = str(root_id)
if level != access.anchors.get(_root_id, AccessLevel.NO_ACCESS):
access.anchors[_root_id] = level

@staticmethod
@hookimpl
def disallow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Disallow all access from target root graph to current Architype."""
level = AccessLevel.cast(level)
access = anchor.access.roots

access.anchors.pop(str(root_id), None)

@staticmethod
@hookimpl
def unrestrict(
anchor: Anchor, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow everyone to access current Architype."""
level = AccessLevel.cast(level)
if level != anchor.access.all:
anchor.access.all = level

@staticmethod
@hookimpl
def restrict(anchor: Anchor) -> None:
"""Disallow others to access current Architype."""
if anchor.access.all > AccessLevel.NO_ACCESS:
anchor.access.all = AccessLevel.NO_ACCESS

@staticmethod
@hookimpl
def check_read_access(to: Anchor) -> bool:
Expand Down Expand Up @@ -129,6 +170,31 @@ def check_access_level(to: Anchor) -> AccessLevel:
class JacNodeImpl:
"""Jac Node Operations."""

@staticmethod
@hookimpl
def node_dot(node: NodeArchitype, dot_file: Optional[str] = None) -> str:
"""Generate Dot file for visualizing nodes and edges."""
visited_nodes: set[NodeAnchor] = set()
connections: set[tuple[NodeArchitype, NodeArchitype, str]] = set()
unique_node_id_dict = {}

collect_node_connections(node.__jac__, visited_nodes, connections)
dot_content = 'digraph {\nnode [style="filled", shape="ellipse", fillcolor="invis", fontcolor="black"];\n'
for idx, i in enumerate([nodes_.architype for nodes_ in visited_nodes]):
unique_node_id_dict[i] = (i.__class__.__name__, str(idx))
dot_content += f'{idx} [label="{i}"];\n'
dot_content += 'edge [color="gray", style="solid"];\n'

for pair in list(set(connections)):
dot_content += (
f"{unique_node_id_dict[pair[0]][1]} -> {unique_node_id_dict[pair[1]][1]}"
f' [label="{pair[2]}"];\n'
)
if dot_file:
with open(dot_file, "w") as f:
f.write(dot_content + "}")
return dot_content + "}"

@staticmethod
@hookimpl
def get_edges(
Expand Down Expand Up @@ -763,15 +829,15 @@ def disconnect(
and target.architype in right
and Jac.check_write_access(target)
):
anchor.destroy() if anchor.persistent else Jac.detach(anchor)
Jac.destroy(anchor) if anchor.persistent else Jac.detach(anchor)
disconnect_occurred = True
if (
dir in [EdgeDir.IN, EdgeDir.ANY]
and node == target
and source.architype in right
and Jac.check_write_access(source)
):
anchor.destroy() if anchor.persistent else Jac.detach(anchor)
Jac.destroy(anchor) if anchor.persistent else Jac.detach(anchor)
disconnect_occurred = True

return disconnect_occurred
Expand Down Expand Up @@ -812,9 +878,13 @@ def build_edge(

def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
edge = conn_type() if isinstance(conn_type, type) else conn_type
edge.__attach__(source, target, is_undirected)

eanch = edge.__jac__
eanch = edge.__jac__ = EdgeAnchor(
architype=edge,
source=source,
target=target,
is_undirected=is_undirected,
)
source.edges.append(eanch)
target.edges.append(eanch)

Expand All @@ -825,13 +895,44 @@ def builder(source: NodeAnchor, target: NodeAnchor) -> EdgeArchitype:
else:
raise ValueError(f"Invalid attribute: {fld}")
if source.persistent or target.persistent:
eanch.save()
target.save()
source.save()
Jac.save(eanch)
Jac.save(target)
Jac.save(source)
return edge

return builder

@staticmethod
@hookimpl
def save(obj: Architype | Anchor) -> None:
"""Destroy object."""
anchor = obj.__jac__ if isinstance(obj, Architype) else obj

jctx = Jac.get_context()

anchor.persistent = True
anchor.root = jctx.root.id

jctx.mem.set(anchor.id, anchor)

@staticmethod
@hookimpl
def destroy(obj: Architype | Anchor) -> None:
"""Destroy object."""
anchor = obj.__jac__ if isinstance(obj, Architype) else obj

if Jac.check_write_access(anchor):
match anchor:
case NodeAnchor():
for edge in anchor.edges:
Jac.destroy(edge)
case EdgeAnchor():
Jac.detach(anchor)
case _:
pass

Jac.get_context().mem.remove(anchor.id)

@staticmethod
@hookimpl
def get_semstr_type(
Expand Down
46 changes: 46 additions & 0 deletions jac/jaclang/plugin/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import ast as ast3
import types
from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union
from uuid import UUID

from jaclang.plugin.spec import (
AccessLevel,
Expand All @@ -30,6 +31,32 @@
class JacAccessValidation:
"""Jac Access Validation Specs."""

@staticmethod
def allow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow all access from target root graph to current Architype."""
hookmanager.hook.allow_root(anchor=anchor, root_id=root_id, level=level)

@staticmethod
def disallow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Disallow all access from target root graph to current Architype."""
hookmanager.hook.disallow_root(anchor=anchor, root_id=root_id, level=level)

@staticmethod
def unrestrict(
anchor: Anchor, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow everyone to access current Architype."""
hookmanager.hook.unrestrict(anchor=anchor, level=level)

@staticmethod
def restrict(anchor: Anchor) -> None:
"""Disallow others to access current Architype."""
hookmanager.hook.restrict(anchor=anchor)

@staticmethod
def check_read_access(to: Anchor) -> bool:
"""Read Access Validation."""
Expand All @@ -54,6 +81,11 @@ def check_access_level(to: Anchor) -> AccessLevel:
class JacNode:
"""Jac Node Operations."""

@staticmethod
def node_dot(node: NodeArchitype, dot_file: Optional[str] = None) -> str:
"""Generate Dot file for visualizing nodes and edges."""
return hookmanager.hook.node_dot(node=node, dot_file=dot_file)

@staticmethod
def get_edges(
node: NodeAnchor,
Expand Down Expand Up @@ -344,6 +376,20 @@ def build_edge(
is_undirected=is_undirected, conn_type=conn_type, conn_assign=conn_assign
)

@staticmethod
def save(
obj: Architype | Anchor,
) -> None:
"""Destroy object."""
hookmanager.hook.save(obj=obj)

@staticmethod
def destroy(
obj: Architype | Anchor,
) -> None:
"""Destroy object."""
hookmanager.hook.destroy(obj=obj)

@staticmethod
def get_semstr_type(
file_loc: str, scope: str, attr: str, return_semstr: bool
Expand Down
53 changes: 53 additions & 0 deletions jac/jaclang/plugin/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
TypeVar,
Union,
)
from uuid import UUID

from jaclang.compiler import absyntree as ast
from jaclang.compiler.constant import EdgeDir
Expand Down Expand Up @@ -45,6 +46,36 @@
class JacAccessValidationSpec:
"""Jac Access Validation Specs."""

@staticmethod
@hookspec(firstresult=True)
def allow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow all access from target root graph to current Architype."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def disallow_root(
anchor: Anchor, root_id: UUID, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Disallow all access from target root graph to current Architype."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def unrestrict(
anchor: Anchor, level: AccessLevel | int | str = AccessLevel.READ
) -> None:
"""Allow everyone to access current Architype."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def restrict(anchor: Anchor) -> None:
"""Disallow others to access current Architype."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def check_read_access(to: Anchor) -> bool:
Expand Down Expand Up @@ -73,6 +104,12 @@ def check_access_level(to: Anchor) -> AccessLevel:
class JacNodeSpec:
"""Jac Node Operations."""

@staticmethod
@hookspec(firstresult=True)
def node_dot(node: NodeArchitype, dot_file: Optional[str] = None) -> str:
"""Generate Dot file for visualizing nodes and edges."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def get_edges(
Expand Down Expand Up @@ -356,6 +393,22 @@ def build_edge(
"""Jac's root getter."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def save(
obj: Architype | Anchor,
) -> None:
"""Destroy object."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def destroy(
obj: Architype | Anchor,
) -> None:
"""Destroy object."""
raise NotImplementedError

@staticmethod
@hookspec(firstresult=True)
def get_semstr_type(
Expand Down
18 changes: 9 additions & 9 deletions jac/jaclang/plugin/tests/fixtures/other_root_access.jac
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ walker create_node {
walker create_other_root {
can enter with `root entry {
other_root = `root().__jac__;
other_root.save();
Jac.save(other_root);
print(other_root.id);
}
}
Expand All @@ -46,17 +46,17 @@ walker allow_other_root_access {

can enter_root with `root entry {
if self.via_all {
here.__jac__.unrestrict(self.level);
Jac.unrestrict(here.__jac__, self.level);
} else {
here.__jac__.allow_root(UUID(self.root_id), self.level);
Jac.allow_root(here.__jac__, UUID(self.root_id), self.level);
}
}

can enter_nested with A entry {
if self.via_all {
here.__jac__.unrestrict(self.level);
Jac.unrestrict(here.__jac__, self.level);
} else {
here.__jac__.allow_root(UUID(self.root_id), self.level);
Jac.allow_root(here.__jac__, UUID(self.root_id), self.level);
}
}
}
Expand All @@ -66,17 +66,17 @@ walker disallow_other_root_access {

can enter_root with `root entry {
if self.via_all {
here.__jac__.restrict();
Jac.restrict(here.__jac__);
} else {
here.__jac__.disallow_root(UUID(self.root_id));
Jac.disallow_root(here.__jac__, UUID(self.root_id));
}
}

can enter_nested with A entry {
if self.via_all {
here.__jac__.restrict();
Jac.restrict(here.__jac__);
} else {
here.__jac__.disallow_root(UUID(self.root_id));
Jac.disallow_root(here.__jac__, UUID(self.root_id));
}
}
}
Loading

0 comments on commit 382f6cd

Please sign in to comment.