treescript-builder 0.1.7__tar.gz → 0.1.9__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 (30) hide show
  1. {treescript_builder-0.1.7/treescript_builder.egg-info → treescript_builder-0.1.9}/PKG-INFO +2 -1
  2. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/setup.py +2 -1
  3. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/path_stack.py +1 -15
  4. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/tree_state.py +9 -9
  5. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/line_reader.py +58 -36
  6. {treescript_builder-0.1.7 → treescript_builder-0.1.9/treescript_builder.egg-info}/PKG-INFO +2 -1
  7. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/LICENSE +0 -0
  8. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/README.md +0 -0
  9. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/setup.cfg +0 -0
  10. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/__init__.py +0 -0
  11. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/__main__.py +0 -0
  12. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/__init__.py +0 -0
  13. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/data_directory.py +0 -0
  14. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/instruction_data.py +0 -0
  15. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/data/tree_data.py +0 -0
  16. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/__init__.py +0 -0
  17. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/argument_data.py +0 -0
  18. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/argument_parser.py +0 -0
  19. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/file_validation.py +0 -0
  20. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/input_data.py +0 -0
  21. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/input/string_validation.py +0 -0
  22. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/tree/__init__.py +0 -0
  23. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/tree/build_validation.py +0 -0
  24. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/tree/tree_builder.py +0 -0
  25. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/tree/tree_trimmer.py +0 -0
  26. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder/tree/trim_validation.py +0 -0
  27. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder.egg-info/SOURCES.txt +0 -0
  28. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder.egg-info/dependency_links.txt +0 -0
  29. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/treescript_builder.egg-info/entry_points.txt +0 -0
  30. {treescript_builder-0.1.7 → treescript_builder-0.1.9}/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.7
3
+ Version: 0.1.9
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
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
19
20
  Requires-Python: >=3.11
20
21
  Description-Content-Type: text/markdown
21
22
  License-File: LICENSE
@@ -5,7 +5,7 @@ from setuptools import find_packages, setup
5
5
 
6
6
  setup(
7
7
  name="treescript-builder",
8
- version="0.1.7",
8
+ version="0.1.9",
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',
@@ -34,5 +34,6 @@ setup(
34
34
  'Programming Language :: Python :: 3.11',
35
35
  'Programming Language :: Python :: 3.12',
36
36
  'Programming Language :: Python :: 3.13',
37
+ 'Programming Language :: Python :: 3.14',
37
38
  ],
38
39
  )
@@ -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,24 +1,34 @@
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
- from itertools import groupby, takewhile
11
12
  from sys import exit
12
13
  from typing import Generator
13
14
 
14
15
  from treescript_builder.data.tree_data import TreeData
15
- from treescript_builder.input.string_validation import validate_dir_name, validate_name
16
+ from treescript_builder.input.string_validation import validate_dir_name, validate_name, validate_data_label
16
17
 
17
18
 
18
19
  SPACE_CHARS = (' ', ' ')
19
20
 
20
21
 
21
- def read_input_tree(input_tree_data: str) -> Generator[TreeData, None, None]:
22
+ _INVALID_DEPTH_ERROR_MSG = "Invalid Depth (Number of Spaces) in Line: "
23
+
24
+ _INVALID_NODE_NAME_ERROR_MSG = "Invalid Name in Line: "
25
+ _INVALID_DATALABEL_ERROR_MSG = "Invalid DataLabel in Line: "
26
+ _MISSING_DATADIR_ERROR_MSG = "Missing DataDirectory for DataLabel in Line: "
27
+
28
+
29
+ def read_input_tree(
30
+ input_tree_data: str,
31
+ ) -> Generator[TreeData, None, None]:
22
32
  """ Generate structured Tree Data from the Input Data String.
23
33
 
24
34
  **Parameters:**
@@ -30,15 +40,10 @@ def read_input_tree(input_tree_data: str) -> Generator[TreeData, None, None]:
30
40
  **Raises:**
31
41
  SystemExit - When any Line cannot be read successfully.
32
42
  """
33
- line_number = 1
34
- for is_newline, group in groupby(input_tree_data, lambda x: x in ["\n", "\r"]):
35
- if is_newline:
36
- line_number += sum(1 for _ in group) # Line number increase by size of group
37
- else:
38
- line = ''.join(group)
39
- if len(lstr := line.lstrip()) == 0 or lstr.startswith('#'):
40
- continue
41
- yield _process_line(line_number, line)
43
+ for line_number, line in enumerate(input_tree_data.splitlines(), start=1):
44
+ if len(lstr := line.lstrip()) == 0 or lstr.startswith('#'):
45
+ continue
46
+ yield _process_line(line_number, line)
42
47
 
43
48
 
44
49
  def _process_line(
@@ -51,44 +56,59 @@ def _process_line(
51
56
  **Parameters:**
52
57
  - line_number (int): The line-number in the input tree structure, starting from 1.
53
58
  - line (str): A line from the input tree structure.
59
+ - is_data_label_enabled (bool): Whether DataLabels are enabled. If the DataDirectory argument is not provided, DataLabels are disabled.
54
60
 
55
61
  **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.
62
+ TreeData - A Tree Node Data object.
57
63
 
58
64
  **Raises:**
59
65
  SystemExit - When Line cannot be read successfully.
60
66
  """
67
+ # Depth Depends on Leading Spaces
61
68
  if (depth := _calculate_depth(line)) < 0:
62
- exit(f"Invalid Space Count in Line: {line_number}")
63
- # Remove Space
69
+ exit(_INVALID_DEPTH_ERROR_MSG + str(line_number))
70
+ # Now remove Leading Spaces (and trailing)
64
71
  args = line.strip()
65
- # Try to split line into multiple arguments
72
+ # Try to split line into multiple arguments, on one of the SpaceChars.
66
73
  for space_char in SPACE_CHARS:
67
74
  if space_char in args:
68
75
  args = args.split(space_char)
69
76
  break
70
77
  # Check whether line was split or not
71
78
  if isinstance(args, str):
72
- name = args
73
- data_label = ""
79
+ name = args # Was Not Split
80
+ data_label = ''
74
81
  elif isinstance(args, list) and len(args) >= 2:
75
- name = args[0]
76
- data_label = args[1]
82
+ name = args[0] # First Word is the Tree Node Name.
83
+ # Second Word is the DataLabel.
84
+ data_label = _validate_data_label_argument(line_number, args[1])
85
+ # Additional Words are ignored. Comments after the DataLabel are possible, for now.
86
+ # Alternate LineReader Modules are likely to expand in this area:
77
87
  else:
78
88
  exit(f"Invalid Line: {line_number}")
79
- # Validate the Node Name and Type.
89
+ # Validate the Node Name and Type (is_dir). The tuple is bool first, then node name.
80
90
  if (node_info := _validate_node_name(name)) is None:
81
- exit(f'Invalid Node on Line: {line_number}')
82
- (is_dir, name) = node_info
91
+ exit(_INVALID_NODE_NAME_ERROR_MSG + str(line_number))
83
92
  return TreeData(
84
- line_number,
85
- depth,
86
- is_dir,
87
- name,
88
- data_label
93
+ line_number=line_number,
94
+ depth=depth,
95
+ is_dir=node_info[0],
96
+ name=node_info[1],
97
+ data_label=data_label,
89
98
  )
90
99
 
91
100
 
101
+ def _validate_data_label_argument(
102
+ line_number: int,
103
+ argument: str,
104
+ ) -> str:
105
+ if argument.startswith('#'): # Comment should be ignored.
106
+ return ''
107
+ elif not validate_data_label(argument):
108
+ exit(_INVALID_DATALABEL_ERROR_MSG + str(line_number))
109
+ return argument
110
+
111
+
92
112
  def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
93
113
  """ Determine whether this Tree Node is a Directory, and validate the name.
94
114
 
@@ -96,7 +116,7 @@ def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
96
116
  - node_name (str): The argument received for the node name.
97
117
 
98
118
  **Returns:**
99
- tuple[bool, str] - Node information, first whether it is a directory, then the valid name of the node.
119
+ tuple[bool, str]? - Node information, first whether it is a directory, then the valid name of the node.
100
120
 
101
121
  **Raises:**
102
122
  SystemExit - When the directory name is invalid.
@@ -104,14 +124,14 @@ def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
104
124
  try:
105
125
  # Check if the line contains any slash characters
106
126
  if (dir_name := validate_dir_name(node_name)) is not None:
107
- return (True, dir_name)
127
+ return True, dir_name
108
128
  # Fall-Through to File Node
109
129
  except ValueError:
110
130
  # An error in the dir name, such that it cannot be a file either
111
131
  return None
112
132
  # Is a File
113
133
  if validate_name(node_name):
114
- return (False, node_name)
134
+ return False, node_name
115
135
  return None
116
136
 
117
137
 
@@ -122,11 +142,13 @@ def _calculate_depth(line: str) -> int:
122
142
  - line (str): A line from the tree command output.
123
143
 
124
144
  **Returns:**
125
- int: The depth of the line in the tree structure, or -1 if space count is invalid.
145
+ int - The depth of the line in the tree structure, or -1 if space count is invalid.
126
146
  """
127
- space_count = len(list(
128
- takewhile(lambda c: c in SPACE_CHARS, line)
129
- ))
147
+ space_count = 0
148
+ for char in line:
149
+ if char not in SPACE_CHARS:
150
+ break
151
+ space_count += 1
130
152
  # Bit Shift Shuffle Equivalence Validation (space_count is divisible by 2)
131
153
  if (depth := space_count >> 1) << 1 == space_count:
132
154
  return depth
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: treescript-builder
3
- Version: 0.1.7
3
+ Version: 0.1.9
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
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
19
20
  Requires-Python: >=3.11
20
21
  Description-Content-Type: text/markdown
21
22
  License-File: LICENSE