treescript-builder 0.1.5__tar.gz → 0.1.7__tar.gz

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.
Files changed (31) hide show
  1. {treescript_builder-0.1.5/treescript_builder.egg-info → treescript_builder-0.1.7}/PKG-INFO +1 -1
  2. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/setup.py +1 -1
  3. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/__main__.py +4 -2
  4. treescript_builder-0.1.7/treescript_builder/data/data_directory.py +90 -0
  5. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/data/path_stack.py +2 -4
  6. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/data/tree_data.py +12 -3
  7. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/data/tree_state.py +3 -3
  8. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/line_reader.py +6 -9
  9. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/tree/build_validation.py +8 -8
  10. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/tree/trim_validation.py +10 -10
  11. {treescript_builder-0.1.5 → treescript_builder-0.1.7/treescript_builder.egg-info}/PKG-INFO +1 -1
  12. treescript_builder-0.1.5/treescript_builder/data/data_directory.py +0 -89
  13. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/LICENSE +0 -0
  14. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/README.md +0 -0
  15. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/setup.cfg +0 -0
  16. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/__init__.py +0 -0
  17. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/data/__init__.py +0 -0
  18. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/data/instruction_data.py +0 -0
  19. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/__init__.py +0 -0
  20. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/argument_data.py +0 -0
  21. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/argument_parser.py +0 -0
  22. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/file_validation.py +0 -0
  23. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/input_data.py +0 -0
  24. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/input/string_validation.py +0 -0
  25. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/tree/__init__.py +0 -0
  26. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/tree/tree_builder.py +0 -0
  27. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder/tree/tree_trimmer.py +0 -0
  28. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder.egg-info/SOURCES.txt +0 -0
  29. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder.egg-info/dependency_links.txt +0 -0
  30. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder.egg-info/entry_points.txt +0 -0
  31. {treescript_builder-0.1.5 → treescript_builder-0.1.7}/treescript_builder.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: treescript-builder
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: Builds File Trees from TreeScript. If DataLabels are present in TreeScript, a DataDirectory argument is required.
5
5
  Home-page: https://github.com/DK96-OS/treescript-builder
6
6
  Author: DK96-OS
@@ -5,7 +5,7 @@ from setuptools import find_packages, setup
5
5
 
6
6
  setup(
7
7
  name="treescript-builder",
8
- version="0.1.5",
8
+ version="0.1.7",
9
9
  description='Builds File Trees from TreeScript. If DataLabels are present in TreeScript, a DataDirectory argument is required.',
10
10
  long_description=open('README.md').read(),
11
11
  long_description_content_type='text/markdown',
@@ -3,10 +3,12 @@
3
3
 
4
4
  def main():
5
5
  # Author: DK96-OS 2024 - 2025
6
+ from sys import argv
6
7
  from treescript_builder.input import validate_input_arguments
8
+ input_data = validate_input_arguments(argv[1:])
9
+ #
7
10
  from treescript_builder.tree import build_tree
8
- from sys import argv
9
- build_tree(validate_input_arguments(argv[1:]))
11
+ build_tree(input_data)
10
12
 
11
13
 
12
14
  if __name__ == "__main__":
@@ -0,0 +1,90 @@
1
+ """ Data Directory Management.
2
+ Author: DK96-OS 2024 - 2025
3
+ """
4
+ from pathlib import Path
5
+ from sys import exit
6
+
7
+ from treescript_builder.data.tree_data import TreeData
8
+ from treescript_builder.input.string_validation import validate_data_label
9
+
10
+
11
+ class DataDirectory:
12
+ """ Manages Access to the Data Directory.
13
+ - Search for a Data Label, and obtain the Path to the Data File.
14
+
15
+ **Method Summary:**
16
+ - validate_build(TreeData): Path?
17
+ - validate_trim(TreeData): Path?
18
+ """
19
+
20
+ def __init__(self, data_dir: Path):
21
+ if not isinstance(data_dir, Path) or not data_dir.exists():
22
+ exit('The Data Directory must be a Path that Exists!')
23
+ self._data_dir: Path = data_dir
24
+ self._expected_trim_data: list[str] = []
25
+
26
+ def validate_build(self, node: TreeData) -> Path | None:
27
+ """ Determine if the Data File supporting this Tree node is available.
28
+
29
+ **Parameters:**
30
+ - node (TreeData): The TreeData to validate.
31
+
32
+ **Returns:**
33
+ Path? - The Path to the Data File in the Data Directory.
34
+
35
+ **Raises:**
36
+ SystemExit - When the Data label is invalid, or the Data File does not exist.
37
+ """
38
+ if node.data_label == '': # For compatibility with 0.1.x
39
+ return None
40
+ if not validate_data_label(data_label := node.get_data_label()):
41
+ exit(f'Invalid Data Label on line: {node.line_number}')
42
+ # Search in the DataDir for this Data File.
43
+ if (data_path := self._search_label(data_label)) is None:
44
+ exit(f'Label ({node.data_label}) not found in DataDirectory on Line: {node.line_number}')
45
+ return data_path
46
+
47
+ def validate_trim(self, node: TreeData) -> Path | None:
48
+ """ Determine if the File already exists in the Data Directory.
49
+
50
+ **Parameters:**
51
+ - node (TreeData): The TreeData to validate.
52
+
53
+ **Returns:**
54
+ Path? - The Path to a new File in the Data Directory.
55
+
56
+ **Raises:**
57
+ SystemExit - When the Data label is invalid, or the Data File already exists.
58
+ """
59
+ if node.data_label == '': # For compatibility with 0.1.x
60
+ return None
61
+ if not validate_data_label(data_label := node.get_data_label()):
62
+ exit(f'Invalid Data Label on line: {node.line_number}')
63
+ # Check if another TreeData Node has this DataLabel
64
+ if data_label in self._expected_trim_data:
65
+ exit(f"Duplicate DataLabels in Trim Operation on Line: {node.line_number}")
66
+ # Check if the Data File already exists
67
+ if self._search_label(data_label) is not None:
68
+ exit(f'Data File already exists!\n({data_label}) on Line: {node.line_number}')
69
+ # Add the new DataLabel to the collection
70
+ self._expected_trim_data.append(data_label)
71
+ # Return the DataLabel Path
72
+ return self._data_dir / data_label
73
+
74
+ def _search_label(self, data_label: str) -> Path | None:
75
+ """ Search for a Data Label in this Data Directory.
76
+
77
+ **Parameters:**
78
+ - data_label (str): The Data Label to search for.
79
+
80
+ **Returns:**
81
+ Path? - The Path to the Data File, or None.
82
+ """
83
+ # Find the Data Label File
84
+ data_files = self._data_dir.glob(data_label)
85
+ try:
86
+ return next(data_files)
87
+ except StopIteration:
88
+ return None
89
+ except OSError:
90
+ return None
@@ -17,8 +17,7 @@ class PathStack:
17
17
  """
18
18
 
19
19
  def __init__(self):
20
- # The Stack of Directories in the Path.
21
- self._stack = []
20
+ self._stack: list[str] = []
22
21
 
23
22
  def push(self, directory_name: str):
24
23
  """ Push a directory to the Path Stack.
@@ -70,8 +69,7 @@ class PathStack:
70
69
  **Returns:**
71
70
  boolean - Whether the Reduction was successful, ie 0 or more Stack pops.
72
71
  """
73
- current_depth = self.get_depth()
74
- if current_depth < depth or depth < 0:
72
+ if depth < 0 or (current_depth := self.get_depth()) < depth:
75
73
  return False
76
74
  if current_depth == depth:
77
75
  return True
@@ -1,4 +1,4 @@
1
- """Tree Node DataClass.
1
+ """ Tree Node DataClass.
2
2
  Author: DK96-OS 2024 - 2025
3
3
  """
4
4
  from dataclasses import dataclass
@@ -15,9 +15,18 @@ Fields:
15
15
  - name (str): The Name of the Tree Node.
16
16
  - data_label (str): The Data Label, may be empty string.
17
17
  """
18
-
19
18
  line_number: int
20
19
  depth: int
21
20
  is_dir: bool
22
21
  name: str
23
- data_label: str = ''
22
+ data_label: str = ''
23
+
24
+ def get_data_label(self) -> str:
25
+ """ Obtain the string DataLabel for this TreeData Node.
26
+ - Contains the relation between these two Fields: name, data_label.
27
+ - If the DataLabel is the exclamation point !, then use the name as DataLabel.
28
+
29
+ **Returns:**
30
+ str - The DataLabel string to use for this TreeData Node. It may not have been validated.
31
+ """
32
+ return self.name if self.data_label == '!' else self.data_label
@@ -24,9 +24,9 @@ class TreeState:
24
24
  """
25
25
 
26
26
  def __init__(self):
27
- self._stack = PathStack()
28
- self._queue = []
29
- self._prev_line_number = 0
27
+ self._stack: PathStack = PathStack()
28
+ self._queue: list = []
29
+ self._prev_line_number: int = 0
30
30
 
31
31
  def validate_tree_data(self, node: TreeData) -> int:
32
32
  """ Ensure that the next TreeData is valid, relative to current state.
@@ -7,14 +7,15 @@ The Default Input Reader.
7
7
  - The Name String is the name of the line.
8
8
  Author: DK96-OS 2024 - 2025
9
9
  """
10
- from itertools import groupby
10
+ from itertools import groupby, takewhile
11
11
  from sys import exit
12
12
  from typing import Generator
13
13
 
14
14
  from treescript_builder.data.tree_data import TreeData
15
15
  from treescript_builder.input.string_validation import validate_dir_name, validate_name
16
16
 
17
- SPACE_CHARS = (' ', ' ', ' ', ' ')
17
+
18
+ SPACE_CHARS = (' ', ' ')
18
19
 
19
20
 
20
21
  def read_input_tree(input_tree_data: str) -> Generator[TreeData, None, None]:
@@ -57,9 +58,7 @@ def _process_line(
57
58
  **Raises:**
58
59
  SystemExit - When Line cannot be read successfully.
59
60
  """
60
- # Calculate the Depth
61
- depth = _calculate_depth(line)
62
- if depth < 0:
61
+ if (depth := _calculate_depth(line)) < 0:
63
62
  exit(f"Invalid Space Count in Line: {line_number}")
64
63
  # Remove Space
65
64
  args = line.strip()
@@ -78,8 +77,7 @@ def _process_line(
78
77
  else:
79
78
  exit(f"Invalid Line: {line_number}")
80
79
  # Validate the Node Name and Type.
81
- node_info = _validate_node_name(name)
82
- if node_info is None:
80
+ if (node_info := _validate_node_name(name)) is None:
83
81
  exit(f'Invalid Node on Line: {line_number}')
84
82
  (is_dir, name) = node_info
85
83
  return TreeData(
@@ -126,11 +124,10 @@ def _calculate_depth(line: str) -> int:
126
124
  **Returns:**
127
125
  int: The depth of the line in the tree structure, or -1 if space count is invalid.
128
126
  """
129
- from itertools import takewhile
130
127
  space_count = len(list(
131
128
  takewhile(lambda c: c in SPACE_CHARS, line)
132
129
  ))
133
130
  # Bit Shift Shuffle Equivalence Validation (space_count is divisible by 2)
134
131
  if (depth := space_count >> 1) << 1 == space_count:
135
132
  return depth
136
- return -1 # Invalid Space Count! Someone made an off-by-one whitespace mistake!
133
+ return -1 # Invalid Space Count! Someone made an off-by-one whitespace mistake!
@@ -1,4 +1,4 @@
1
- """Tree Validation Methods for the Build Operation.
1
+ """ Tree Validation Methods for the Build Operation.
2
2
  Author: DK96-OS 2024 - 2025
3
3
  """
4
4
  from pathlib import Path
@@ -23,11 +23,11 @@ def validate_build(
23
23
  **Returns:**
24
24
  tuple[InstructionData] - A generator that yields Instructions.
25
25
  """
26
- if data_dir_path is None:
27
- return tuple(iter(_validate_build_generator(tree_data)))
28
- else:
29
- data = DataDirectory(data_dir_path)
30
- return tuple(iter(_validate_build_generator_data(tree_data, data)))
26
+ return tuple(
27
+ _validate_build_generator(tree_data)
28
+ if data_dir_path is None else
29
+ _validate_build_generator_data(tree_data, DataDirectory(data_dir_path))
30
+ )
31
31
 
32
32
 
33
33
  def _validate_build_generator(
@@ -37,7 +37,7 @@ def _validate_build_generator(
37
37
  for node in tree_data:
38
38
  # Error if any Nodes have Data Labels
39
39
  if node.data_label != '':
40
- exit(f"Found Data Label on Line {node.line_number} with no Data Directory: {node.data_label}")
40
+ exit(f"No DataDirectory provided, but DataLabel found on Line: {node.line_number}")
41
41
  # Calculate Tree Depth Change
42
42
  if tree_state.validate_tree_data(node) == 0:
43
43
  if node.is_dir:
@@ -104,4 +104,4 @@ def _validate_build_generator_data(
104
104
  )
105
105
  # Always Finish Build Sequence with ProcessQueue
106
106
  if (dir := tree_state.process_queue()) is not None:
107
- yield InstructionData(True, dir)
107
+ yield InstructionData(True, dir)
@@ -19,16 +19,15 @@ def validate_trim(
19
19
  **Parameters:**
20
20
  - tree_data (Generator[TreeData]): The Generator that provides TreeData.
21
21
  - data_dir_path (Path?): The optional Path to a Data Directory. Default: None.
22
- - verbose (bool): Whether to print DataDirectory information during validation.
23
22
 
24
23
  **Returns:**
25
- tuple[InstructionData] - A generator that yields Instructions.
24
+ tuple[InstructionData] - A tuple of InstructionData.
26
25
  """
27
- if data_dir_path is None:
28
- return tuple(iter(_validate_trim_generator(tree_data)))
29
- else:
30
- data = DataDirectory(data_dir_path)
31
- return tuple(iter(_validate_trim_generator_data(tree_data, data)))
26
+ return tuple(
27
+ _validate_trim_generator(tree_data)
28
+ if data_dir_path is None else
29
+ _validate_trim_generator_data(tree_data, DataDirectory(data_dir_path))
30
+ )
32
31
 
33
32
 
34
33
  def _validate_trim_generator(
@@ -36,6 +35,9 @@ def _validate_trim_generator(
36
35
  ) -> Generator[InstructionData, None, None]:
37
36
  tree_state = TreeState()
38
37
  for node in tree_data:
38
+ # Error if any Nodes have Data Labels
39
+ if node.data_label != '':
40
+ exit(f"No DataDirectory provided, but DataLabel found on Line: {node.line_number}")
39
41
  # Calculate Tree Depth Change
40
42
  if tree_state.validate_tree_data(node) == 1:
41
43
  if node.is_dir:
@@ -48,7 +50,6 @@ def _validate_trim_generator(
48
50
  # Pop Stack to required Depth
49
51
  for i in tree_state.process_stack(node.depth):
50
52
  yield InstructionData(True, i)
51
- # Dir or File
52
53
  if node.is_dir:
53
54
  tree_state.add_to_stack(node.name)
54
55
  else:
@@ -80,7 +81,6 @@ def _validate_trim_generator_data(
80
81
  # Pop Stack to required Depth
81
82
  for i in tree_state.process_stack(node.depth):
82
83
  yield InstructionData(True, i)
83
- # Dir or File
84
84
  if node.is_dir:
85
85
  tree_state.add_to_stack(node.name)
86
86
  else:
@@ -91,4 +91,4 @@ def _validate_trim_generator_data(
91
91
  )
92
92
  # Finish Trim Sequence with Pop Stack
93
93
  for i in tree_state.process_stack(0):
94
- yield InstructionData(True, i)
94
+ yield InstructionData(True, i)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: treescript-builder
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: Builds File Trees from TreeScript. If DataLabels are present in TreeScript, a DataDirectory argument is required.
5
5
  Home-page: https://github.com/DK96-OS/treescript-builder
6
6
  Author: DK96-OS
@@ -1,89 +0,0 @@
1
- """Data Directory Management.
2
- Author: DK96-OS 2024 - 2025
3
- """
4
- from pathlib import Path
5
- from sys import exit
6
-
7
- from treescript_builder.data.tree_data import TreeData
8
- from treescript_builder.input.string_validation import validate_data_label
9
-
10
-
11
- class DataDirectory:
12
- """ Manages Access to the Data Directory.
13
- - Search for a Data Label, and obtain the Path to the Data File.
14
-
15
- **Method Summary:**
16
- - validate_build(TreeData): Path?
17
- - validate_trim(TreeData): Path?
18
- """
19
-
20
- def __init__(self, data_dir: Path):
21
- if not isinstance(data_dir, Path) or not data_dir.exists():
22
- exit('The Data Directory must be a Path that Exists!')
23
- self._data_dir = data_dir
24
- # todo: Create a map of used Data Labels
25
-
26
- def validate_build(self, node: TreeData) -> Path | None:
27
- """ Determine if the Data File supporting this Tree node is available.
28
-
29
- Parameters:
30
- - node (TreeData): The TreeData to validate.
31
-
32
- Returns:
33
- Path - The Path to the Data File in the Data Directory.
34
-
35
- Raises:
36
- SystemExit - When the Data label is invalid, or the Data File does not exist.
37
- """
38
- if node.data_label == '' or node.is_dir:
39
- return None
40
- if node.data_label == '!':
41
- data_path = self._search_label(node.name)
42
- else:
43
- data_path = self._search_label(node.data_label)
44
- if data_path is None:
45
- exit(f'Data Label ({node.data_label}) not found in Data Directory on line: {node.line_number}')
46
- return data_path
47
-
48
- def validate_trim(self, node: TreeData) -> Path | None:
49
- """ Determine if the File already exists in the Data Directory.
50
-
51
- Parameters:
52
- - node (TreeData): The TreeData to validate.
53
-
54
- Returns:
55
- Path - The Path to a new File in the Data Directory.
56
-
57
- Raises:
58
- SystemExit - When the Data label is invalid, or the Data File already exists.
59
- """
60
- # Ensure that the name of the Label is valid
61
- if node.data_label == '' or node.is_dir:
62
- return None
63
- data_label = node.name if node.data_label == '!' else node.data_label
64
- if not validate_data_label(data_label):
65
- exit(f'Invalid Data Label on line: {node.line_number}')
66
- # Check if the Data File already exists
67
- data_path = self._search_label(data_label)
68
- if data_path is not None:
69
- exit(f'Data File already exists!\n({data_label}) on line: {node.line_number}')
70
- # Create the Data Label Path in the Directory
71
- return self._data_dir / data_label
72
-
73
- def _search_label(self, data_label: str) -> Path | None:
74
- """ Search for a Data Label in this Data Directory.
75
-
76
- Parameters:
77
- - data_label (str): The Data Label to search for.
78
-
79
- Returns:
80
- Path (optional) - The Path to the Data File, or None.
81
- """
82
- if not validate_data_label(data_label):
83
- return None
84
- # Find the Data Label File
85
- data_files = self._data_dir.glob(data_label)
86
- try:
87
- return next(data_files)
88
- except StopIteration:
89
- return None