Skip to content

Commit 32a0471

Browse files
committed
Refactor Shell-based test classes
1 parent 9e261ff commit 32a0471

File tree

12 files changed

+114
-36
lines changed

12 files changed

+114
-36
lines changed

.idea/ContextShell.iml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contextshell/NodeTreeRoot.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def list_actions(self, path: NodePath) -> List[NodePath]:
9898
else:
9999
return action_paths + self.list_actions(path.base_path)
100100

101-
def is_attribute(self, path: str): # CHECK: is used?
101+
def is_attribute(self, path: str): # CHECK: is this used/needed?
102102
return path.startswith('@')
103103

104104
def install_global_type(self, node_type):
@@ -118,8 +118,10 @@ def find_type(self, target: NodePath, type_name: NodePath): # TODO: add type-hi
118118
return None
119119
return type_node.get()
120120

121-
def execute(self, target: NodePath, action_name: NodePath, args: ActionArgsPack=OrderedDict()):
121+
def execute(self, target: NodePath, action_name: NodePath, args: ActionArgsPack = None):
122122
#print("Execute: {}: {} {}".format(target, action, args))
123+
if not args:
124+
args = OrderedDict()
123125
action_impl = self.find_action(target, action_name)
124126
if action_impl is None:
125127
raise NameError("Could not find action named '{}'".format(action_name))
@@ -128,7 +130,7 @@ def execute(self, target: NodePath, action_name: NodePath, args: ActionArgsPack=
128130
def create_node(self, value):
129131
return Node(value)
130132

131-
def create(self, path: NodePath, initial_value=None):
133+
def create(self, path: NodePath, initial_value = None):
132134
parent = self._create_path(path.base_path)
133135
new_node = self.create_node(initial_value)
134136
parent.append(new_node, path.base_name)

contextshell/TreeRoot.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,22 @@
33
from typing import Dict, Union, Any, Tuple, List
44
from collections import OrderedDict
55

6-
7-
ActionArgsPack = Dict[Union[NodePath, int], Any]
8-
PositionalArguments = List[Any]
9-
KeywordArguments = Dict[str, Any]
6+
ArgumentValue = Any
7+
ActionArgsPack = Dict[Union[NodePath, int], ArgumentValue]
8+
PositionalArguments = List[ArgumentValue]
9+
KeywordArguments = Dict[str, ArgumentValue]
1010

1111

12+
# CHECK: Rename TreeRoot to ActionEndpoint or something more appropriate?
1213
class TreeRoot(ABC):
1314
@abstractmethod
14-
def execute(self, target: NodePath, action: NodePath, args: ActionArgsPack=OrderedDict()):
15+
def execute(self, target: NodePath, action: NodePath, args: ActionArgsPack = None):
1516
raise NotImplementedError()
1617

1718

1819
def unpack_argument_tree(action_args: ActionArgsPack) -> Tuple[PositionalArguments, KeywordArguments]:
19-
args = dict()
20-
kwargs: Dict[str, Any] = OrderedDict()
20+
args: Dict[int, ArgumentValue] = dict()
21+
kwargs: KeywordArguments = OrderedDict()
2122
for key, value in action_args.items():
2223
if isinstance(key, int):
2324
args[key] = value
@@ -29,7 +30,7 @@ def unpack_argument_tree(action_args: ActionArgsPack) -> Tuple[PositionalArgumen
2930

3031

3132
def pack_argument_tree(*args: PositionalArguments, **kwargs: KeywordArguments) -> ActionArgsPack:
32-
pack_list: List[Tuple[Union[NodePath, int], Any]] = []
33+
pack_list: List[Tuple[Union[NodePath, int], ArgumentValue]] = []
3334
for i, arg in enumerate(args):
3435
pack_list.append((i, arg))
3536
for key, value in kwargs.items():
@@ -39,7 +40,7 @@ def pack_argument_tree(*args: PositionalArguments, **kwargs: KeywordArguments) -
3940

4041
def parse_argument_tree(raw_arguments: List[str]) -> ActionArgsPack:
4142
from contextshell.CommandParser import convert_token_type
42-
pack_list: List[Tuple[Union[NodePath, int], Any]] = []
43+
pack_list: List[Tuple[Union[NodePath, int], ArgumentValue]] = []
4344
for i, arg in enumerate(raw_arguments):
4445
if isinstance(arg, str) and '=' in arg:
4546
key, value = arg.split('=')

contextshell/VirtualTree.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,33 @@
44

55

66
class VirtualTree(TreeRoot):
7+
"""Abstract frontend allowing embedding (mounting) of more specific tree roots"""
8+
79
def __init__(self):
810
self.mounts: OrderedDict[NodePath, TreeRoot] = OrderedDict()
911

12+
# TODO: rename to attach/detach
1013
def mount(self, path: NodePath, root: TreeRoot):
1114
if path.is_relative:
1215
raise ValueError("Could not mount relative path")
1316
if path in self.mounts:
1417
raise KeyError("Path '{}' is already provided by {}".format(path, self.mounts[path]))
1518

19+
def path_length_extractor(path_root_pair):
20+
return len(path_root_pair[0])
21+
22+
# CHECK: use bisect module for maintaining mount point list?
1623
updated_items = list(self.mounts.items()) + [(path, root)]
17-
path_length_extractor = lambda pair: len(pair[0])
1824
self.mounts = OrderedDict(sorted(updated_items, key=path_length_extractor, reverse=True))
1925

2026
def umount(self, path: NodePath):
2127
del self.mounts[path]
2228

23-
def execute(self, target: NodePath, action: NodePath, args: ActionArgsPack=OrderedDict()):
29+
def execute(self, target: NodePath, action: NodePath, args: ActionArgsPack = None):
2430
if target.is_relative:
25-
raise ValueError("Could not execute with relative target path")
31+
raise ValueError("Could not invoke action with relative target path")
32+
if not args:
33+
args = OrderedDict()
2634
for path, root in self.mounts.items():
2735
if path.is_parent_of(target):
2836
remapped_target = target.relative_to(path)

contextshell/backends/Filesystem.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from contextshell.TreeRoot import TreeRoot
2+
from contextshell.backends.Module import Module
3+
4+
5+
class FilesystemRoot(TreeRoot):
6+
pass
7+
8+
9+
class FilesystemModule(Module):
10+
pass

contextshell/backends/Module.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
class Module:
3+
def register_actions(self):
4+
raise NotImplementedError()
5+
def unregister_actions(self):
6+
raise NotImplementedError()
7+
8+
#Implement me please and make FilesystemModule loadable

contextshell/backends/__init__.py

Whitespace-only changes.

tests/functional/FilesystemTests.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,51 @@
11
import unittest
2+
import os
3+
import tempfile
4+
from contextshell.TreeRoot import TreeRoot
25
from contextshell.VirtualTree import VirtualTree
36
from contextshell.NodeTreeRoot import NodeTreeRoot
47
from contextshell.NodePath import NodePath
5-
from tests.functional.ShellTestsBase import VirtualTreeTestsBase
8+
from tests.functional.ShellTestsBase import TreeRootTestsBase
69
from tests.functional.TestExecutor import script_test
10+
from contextshell.backends.Filesystem import FilesystemRoot
11+
from contextshell.NodePath import NodePath as np
712

813

9-
class FilesystemTestsBase(VirtualTreeTestsBase):
10-
def configure_virtual_tree(self, virtual_tree: VirtualTree):
11-
# TODO: Create FilesystemTreeNode
12-
pass
14+
class FilesystemTestsBase(TreeRootTestsBase):
15+
test_directory_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_data')
16+
17+
def create_tree_root(self) -> TreeRoot:
18+
self.test_directory = tempfile.TemporaryDirectory(FilesystemTestsBase.__name__)
19+
# return FilesystemRoot(self.test_directory.name) # FIXME: make this work
20+
return None
1321

14-
def configure_node_tree(self, tree: NodeTreeRoot):
15-
def attach_filesystem(target: NodePath, mount_point: NodePath):
16-
tree.create(NodePath(mount_point))
22+
def setUp(self):
23+
super().setUp()
24+
# TODO: create test directory
1725

18-
def detach(target: NodePath):
19-
tree.remove(target)
26+
def tearDown(self):
27+
# TODO: remove test directory
28+
super().tearDown()
2029

21-
from contextshell.CallableAction import action_from_function
22-
tree.install_global_action(action_from_function(attach_filesystem))
23-
tree.install_global_action(action_from_function(detach))
2430

31+
class FilesystemRootTests(FilesystemTestsBase):
32+
def setUp(self):
33+
super().setUp()
34+
# TODO: populate test directory
35+
36+
@script_test
37+
def test_contains_existing_file(self):
38+
"""
39+
$ .: contains test_file
40+
True
41+
"""
42+
43+
44+
@unittest.skip("Those tests utilize attach actions which may not belong to the filesystem module")
45+
class AttachTests(TreeRootTestsBase):
46+
def create_tree_root(self) -> TreeRoot:
47+
pass
2548

26-
@unittest.skip("Re-enable when filesystem module can be installed")
27-
class AttachTests(VirtualTreeTestsBase):
2849
def configure_virtual_tree(self, virtual_tree: VirtualTree):
2950
# TODO: install filesystem module/actions fot attaching
3051
# Note: VirtualTreeRoot *CAN* append data to the invoked commands

tests/functional/ShellTestsBase.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,46 @@
11
import unittest
22
from abc import ABC, abstractmethod
3+
4+
from contextshell.TreeRoot import TreeRoot
35
from contextshell.Shell import Shell
46
from contextshell.NodePath import NodePath
57
from contextshell.CommandInterpreter import CommandInterpreter
68
from contextshell.VirtualTree import VirtualTree
79
from contextshell.NodeTreeRoot import NodeTreeRoot
810

911

10-
class VirtualTreeTestsBase(unittest.TestCase, ABC):
12+
class ShellScriptTestsBase(unittest.TestCase, ABC):
13+
@abstractmethod
14+
def create_shell(self) -> Shell:
15+
raise NotImplementedError()
16+
17+
18+
class TreeRootTestsBase(ShellScriptTestsBase):
19+
@abstractmethod
20+
def create_tree_root(self) -> TreeRoot:
21+
raise NotImplementedError()
22+
1123
def create_shell(self):
12-
self.virtual_tree = VirtualTree()
13-
self.configure_virtual_tree(self.virtual_tree)
24+
self.tree_root = self.create_tree_root()
25+
self.configure_tree_root(self.tree_root)
1426

15-
interpreter = CommandInterpreter(self.virtual_tree)
27+
interpreter = CommandInterpreter(self.tree_root)
1628
shell = Shell(interpreter)
1729
return shell
1830

31+
def configure_tree_root(self, tree_root: TreeRoot):
32+
pass
33+
34+
35+
# TODO: is this class needed when testing single TreeRoot-based class?
36+
class VirtualTreeTestsBase(TreeRootTestsBase):
37+
def create_tree_root(self) -> TreeRoot:
38+
return VirtualTree()
39+
40+
def configure_tree_root(self, tree_root: TreeRoot):
41+
self.configure_virtual_tree(tree_root)
42+
43+
1944
@abstractmethod
2045
def configure_virtual_tree(self, virtual_tree: VirtualTree):
2146
raise NotImplementedError()

tests/functional/backends/FilesystemTests.py

Whitespace-only changes.

0 commit comments

Comments
 (0)