treescript-builder 0.1.6__py3-none-any.whl → 0.1.8__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.
@@ -11,7 +11,6 @@ class PathStack:
11
11
  - push(str)
12
12
  - pop: str?
13
13
  - join_stack: Path
14
- - create_path(str): Path
15
14
  - reduce_depth(int): bool
16
15
  - get_depth: int
17
16
  """
@@ -47,19 +46,6 @@ class PathStack:
47
46
  return Path("./")
48
47
  return Path(f"./{'/'.join(self._stack)}/")
49
48
 
50
- def create_path(self, filename: str) -> Path:
51
- """ Combines all Elements in the Stack and appends a File name.
52
-
53
- **Parameters:**
54
- - filename (str): The name of the file to append to the end of the path.
55
-
56
- **Returns:**
57
- Path - The Path to the file.
58
- """
59
- if type(filename) is not str or len(filename) < 1:
60
- return self.join_stack()
61
- return self.join_stack() / filename
62
-
63
49
  def reduce_depth(self, depth: int) -> bool:
64
50
  """ Reduce the Depth of the Path Stack.
65
51
 
@@ -84,4 +70,4 @@ class PathStack:
84
70
  **Returns:**
85
71
  int - The number of elements in the Path Stack.
86
72
  """
87
- return len(self._stack)
73
+ return len(self._stack)
@@ -102,18 +102,19 @@ class TreeState:
102
102
 
103
103
  def process_stack(self, depth: int) -> Generator[Path, None, None]:
104
104
  """ Pop the Stack to the Desired Depth.
105
+ - Combines all Elements in the Stack into a Directory Path.
105
106
 
106
- Parameters:
107
+ **Parameters:**
107
108
  - depth (int): The depth to process the stack to.
108
109
 
109
- Returns:
110
- Generator[Path] - Provides a Path for each entry in the Stack.
110
+ **Yields:**
111
+ Path - A Path for every Directory in the Stack, from top to bottom.
111
112
  """
112
113
  if depth < 0:
113
- exit('Invalid Depth')
114
+ raise ValueError('Negative Depth.')
114
115
  while depth < self._stack.get_depth():
115
116
  if (entry := self._stack.pop()) is not None:
116
- yield self._stack.create_path(entry)
117
+ yield self._stack.join_stack() / entry
117
118
 
118
119
  def reduce_depth(self, depth: int) -> bool:
119
120
  """ Pop an element from the stack.
@@ -135,7 +136,6 @@ class TreeState:
135
136
  Raises:
136
137
  SystemExit - When the Line Number does not increase.
137
138
  """
138
- if self._prev_line_number < line_number:
139
- self._prev_line_number = line_number
140
- else:
141
- exit("Invalid Tree Data Sequence")
139
+ if self._prev_line_number >= line_number:
140
+ exit("Invalid Tree Data Sequence")
141
+ self._prev_line_number = line_number
@@ -1,10 +1,12 @@
1
- """ Line Reader.
1
+ """ Line Reader Module for Processing TreeScript.
2
2
 
3
3
  The Default Input Reader.
4
4
  - Processes a single line at a time, and determines its key properties.
5
5
  - The Depth is the Integer number of directories between the current line and the root.
6
6
  - The Directory Boolean indicates whether the line represents a Directory.
7
7
  - The Name String is the name of the line.
8
+ - DataLabel is the first word after the Name, and it has a strict set of validation criteria.
9
+ - Comments are filtered out by starting a line with the # character. A comment after a file name is also filtered.
8
10
  Author: DK96-OS 2024 - 2025
9
11
  """
10
12
  from itertools import groupby, takewhile
@@ -12,13 +14,22 @@ from sys import exit
12
14
  from typing import Generator
13
15
 
14
16
  from treescript_builder.data.tree_data import TreeData
15
- from treescript_builder.input.string_validation import validate_dir_name, validate_name
17
+ from treescript_builder.input.string_validation import validate_dir_name, validate_name, validate_data_label
16
18
 
17
19
 
18
20
  SPACE_CHARS = (' ', ' ')
19
21
 
20
22
 
21
- def read_input_tree(input_tree_data: str) -> Generator[TreeData, None, None]:
23
+ _INVALID_DEPTH_ERROR_MSG = "Invalid Depth (Number of Spaces) in Line: "
24
+
25
+ _INVALID_NODE_NAME_ERROR_MSG = "Invalid Name in Line: "
26
+ _INVALID_DATALABEL_ERROR_MSG = "Invalid DataLabel in Line: "
27
+ _MISSING_DATADIR_ERROR_MSG = "Missing DataDirectory for DataLabel in Line: "
28
+
29
+
30
+ def read_input_tree(
31
+ input_tree_data: str,
32
+ ) -> Generator[TreeData, None, None]:
22
33
  """ Generate structured Tree Data from the Input Data String.
23
34
 
24
35
  **Parameters:**
@@ -51,44 +62,59 @@ def _process_line(
51
62
  **Parameters:**
52
63
  - line_number (int): The line-number in the input tree structure, starting from 1.
53
64
  - line (str): A line from the input tree structure.
65
+ - is_data_label_enabled (bool): Whether DataLabels are enabled. If the DataDirectory argument is not provided, DataLabels are disabled.
54
66
 
55
67
  **Returns:**
56
- tuple: (int, bool, str, str) where int is the depth, bool is true when is Directory, and str is name, followed by str data.
68
+ TreeData - A Tree Node Data object.
57
69
 
58
70
  **Raises:**
59
71
  SystemExit - When Line cannot be read successfully.
60
72
  """
73
+ # Depth Depends on Leading Spaces
61
74
  if (depth := _calculate_depth(line)) < 0:
62
- exit(f"Invalid Space Count in Line: {line_number}")
63
- # Remove Space
75
+ exit(_INVALID_DEPTH_ERROR_MSG + str(line_number))
76
+ # Now remove Leading Spaces (and trailing)
64
77
  args = line.strip()
65
- # Try to split line into multiple arguments
78
+ # Try to split line into multiple arguments, on one of the SpaceChars.
66
79
  for space_char in SPACE_CHARS:
67
80
  if space_char in args:
68
81
  args = args.split(space_char)
69
82
  break
70
83
  # Check whether line was split or not
71
84
  if isinstance(args, str):
72
- name = args
73
- data_label = ""
85
+ name = args # Was Not Split
86
+ data_label = ''
74
87
  elif isinstance(args, list) and len(args) >= 2:
75
- name = args[0]
76
- data_label = args[1]
88
+ name = args[0] # First Word is the Tree Node Name.
89
+ # Second Word is the DataLabel.
90
+ data_label = _validate_data_label_argument(line_number, args[1])
91
+ # Additional Words are ignored. Comments after the DataLabel are possible, for now.
92
+ # Alternate LineReader Modules are likely to expand in this area:
77
93
  else:
78
94
  exit(f"Invalid Line: {line_number}")
79
- # Validate the Node Name and Type.
95
+ # Validate the Node Name and Type (is_dir). The tuple is bool first, then node name.
80
96
  if (node_info := _validate_node_name(name)) is None:
81
- exit(f'Invalid Node on Line: {line_number}')
82
- (is_dir, name) = node_info
97
+ exit(_INVALID_NODE_NAME_ERROR_MSG + str(line_number))
83
98
  return TreeData(
84
- line_number,
85
- depth,
86
- is_dir,
87
- name,
88
- data_label
99
+ line_number=line_number,
100
+ depth=depth,
101
+ is_dir=node_info[0],
102
+ name=node_info[1],
103
+ data_label=data_label,
89
104
  )
90
105
 
91
106
 
107
+ def _validate_data_label_argument(
108
+ line_number: int,
109
+ argument: str,
110
+ ) -> str:
111
+ if argument.startswith('#'): # Comment should be ignored.
112
+ return ''
113
+ elif not validate_data_label(argument):
114
+ exit(_INVALID_DATALABEL_ERROR_MSG + str(line_number))
115
+ return argument
116
+
117
+
92
118
  def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
93
119
  """ Determine whether this Tree Node is a Directory, and validate the name.
94
120
 
@@ -96,7 +122,7 @@ def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
96
122
  - node_name (str): The argument received for the node name.
97
123
 
98
124
  **Returns:**
99
- tuple[bool, str] - Node information, first whether it is a directory, then the valid name of the node.
125
+ tuple[bool, str]? - Node information, first whether it is a directory, then the valid name of the node.
100
126
 
101
127
  **Raises:**
102
128
  SystemExit - When the directory name is invalid.
@@ -104,14 +130,14 @@ def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
104
130
  try:
105
131
  # Check if the line contains any slash characters
106
132
  if (dir_name := validate_dir_name(node_name)) is not None:
107
- return (True, dir_name)
133
+ return True, dir_name
108
134
  # Fall-Through to File Node
109
135
  except ValueError:
110
136
  # An error in the dir name, such that it cannot be a file either
111
137
  return None
112
138
  # Is a File
113
139
  if validate_name(node_name):
114
- return (False, node_name)
140
+ return False, node_name
115
141
  return None
116
142
 
117
143
 
@@ -122,7 +148,7 @@ def _calculate_depth(line: str) -> int:
122
148
  - line (str): A line from the tree command output.
123
149
 
124
150
  **Returns:**
125
- int: The depth of the line in the tree structure, or -1 if space count is invalid.
151
+ int - The depth of the line in the tree structure, or -1 if space count is invalid.
126
152
  """
127
153
  space_count = len(list(
128
154
  takewhile(lambda c: c in SPACE_CHARS, line)
@@ -35,6 +35,9 @@ def _validate_trim_generator(
35
35
  ) -> Generator[InstructionData, None, None]:
36
36
  tree_state = TreeState()
37
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}")
38
41
  # Calculate Tree Depth Change
39
42
  if tree_state.validate_tree_data(node) == 1:
40
43
  if node.is_dir:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: treescript-builder
3
- Version: 0.1.6
3
+ Version: 0.1.8
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
@@ -3,24 +3,24 @@ treescript_builder/__main__.py,sha256=IWk1m8kZFyd35b3HLGwcxqczqKWskt1keylKQFV7YN
3
3
  treescript_builder/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  treescript_builder/data/data_directory.py,sha256=eqLLOyV2YTXHv1rU7xsE_Hn4oViJh4SrokRfbKfEgTA,3267
5
5
  treescript_builder/data/instruction_data.py,sha256=VqJ25-1Na0b2KamuKaVDN6qGPn-8Mm89tS1rt7_RzCY,533
6
- treescript_builder/data/path_stack.py,sha256=L_1u6YVM13EO0YLzbmaA_fYCMJeN3vdTzgJBhEJX-hI,2367
6
+ treescript_builder/data/path_stack.py,sha256=2u7MKv57l_-YB1Cgr81woZGJdJCke7hCNR27T9r4za8,1932
7
7
  treescript_builder/data/tree_data.py,sha256=iyo-op0AmM9i_ypGXSROkbdax_YJgGsYLXKIlvmXmQ0,1035
8
- treescript_builder/data/tree_state.py,sha256=EJYSnioAlh4nD44xfeSTQrIY4WjUjckpAQ9m9MQANOo,4473
8
+ treescript_builder/data/tree_state.py,sha256=luWdxLxMrqaDRuNVLz7BKy_ZW4nYrGUymUdshOHmkI0,4553
9
9
  treescript_builder/input/__init__.py,sha256=JONsaG0Iq_w-b9BUpHPpc89DFG8sM8Dxrswb3tWvzY8,921
10
10
  treescript_builder/input/argument_data.py,sha256=PFacb8g-RXh4-RH8foW4eINms6REWpm_knaehYAICfA,806
11
11
  treescript_builder/input/argument_parser.py,sha256=ARPI-EFO5MkXSQqLjyiQPkxg-sB2jP14wf6K4y64Tog,2795
12
12
  treescript_builder/input/file_validation.py,sha256=m0zxntGDkkzWLb3PQKKsxfRSSDgd0dhK35IbaUmN_gw,2404
13
13
  treescript_builder/input/input_data.py,sha256=mP8FAI26UDRwfuEFWXsJJnw77Qxv_yjkuy4NFiTZVOg,479
14
- treescript_builder/input/line_reader.py,sha256=_jRwuODxT4frnQE0GkEPV6uJbUMpwKAc7EsR8mgSCEM,4333
14
+ treescript_builder/input/line_reader.py,sha256=BqsxwxpWndwsOibcm8339q8SPaLgIjueCMPwlErXQEM,5696
15
15
  treescript_builder/input/string_validation.py,sha256=6H17UWamTPp2aBC-EVX1P58E0a-F6eD1--HH8CWrmIQ,5020
16
16
  treescript_builder/tree/__init__.py,sha256=3YgyrVcplTYEtFL9PuEM2k08LM8N8xsdRmNJR0rbA4s,1884
17
17
  treescript_builder/tree/build_validation.py,sha256=huO_FRnq_anqGTaQaDfcmc_zU9pIuVaa0orglNDgQIc,4167
18
18
  treescript_builder/tree/tree_builder.py,sha256=0OiJ_Rjpm9Ux1DXvP4d6lHw9CoUCpu6lTfxTmLVOTfQ,1862
19
19
  treescript_builder/tree/tree_trimmer.py,sha256=4cYrnAPX4WQi9JW60K20KPWb9aAtkPYTZWeZ4scEjps,1581
20
- treescript_builder/tree/trim_validation.py,sha256=1MJjVz2JMNTDIvgJD3BMDwpzOvrKw53XXB2LIRFIWkg,3177
21
- treescript_builder-0.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
22
- treescript_builder-0.1.6.dist-info/METADATA,sha256=vV6W26xZ6NeaDy7sPiyXUXdePqOEXKebE6GqEHbCwzk,5299
23
- treescript_builder-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- treescript_builder-0.1.6.dist-info/entry_points.txt,sha256=eOmYzJQPcGaH2GGBfwwU6UH_33tGtsK_ogxB4DnVrFI,111
25
- treescript_builder-0.1.6.dist-info/top_level.txt,sha256=parytS3LU7PXBsMVe_puiTOva14bUCzvFwcIwF_Y3Ks,19
26
- treescript_builder-0.1.6.dist-info/RECORD,,
20
+ treescript_builder/tree/trim_validation.py,sha256=Q49ufnISQxZDzsnvMWrF5cMxRSZQYAhgpY_2XdIjnzI,3353
21
+ treescript_builder-0.1.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
22
+ treescript_builder-0.1.8.dist-info/METADATA,sha256=QnfZHITKtHGwBGMcjsWPE7Y3kmWcN1rmld6w7H88SHI,5299
23
+ treescript_builder-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ treescript_builder-0.1.8.dist-info/entry_points.txt,sha256=eOmYzJQPcGaH2GGBfwwU6UH_33tGtsK_ogxB4DnVrFI,111
25
+ treescript_builder-0.1.8.dist-info/top_level.txt,sha256=parytS3LU7PXBsMVe_puiTOva14bUCzvFwcIwF_Y3Ks,19
26
+ treescript_builder-0.1.8.dist-info/RECORD,,