treescript-builder 0.1.2__tar.gz → 0.1.4__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 (32) hide show
  1. {treescript_builder-0.1.2/treescript_builder.egg-info → treescript_builder-0.1.4}/PKG-INFO +58 -20
  2. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/README.md +56 -18
  3. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/setup.py +2 -2
  4. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/data_directory.py +1 -1
  5. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/input/__init__.py +1 -1
  6. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/input/argument_parser.py +3 -5
  7. treescript_builder-0.1.4/treescript_builder/input/file_validation.py +75 -0
  8. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/input/line_reader.py +1 -1
  9. treescript_builder-0.1.4/treescript_builder/input/string_validation.py +144 -0
  10. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/tree/build_validation.py +0 -4
  11. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/tree/tree_builder.py +2 -2
  12. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/tree/tree_trimmer.py +5 -6
  13. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/tree/trim_validation.py +0 -3
  14. {treescript_builder-0.1.2 → treescript_builder-0.1.4/treescript_builder.egg-info}/PKG-INFO +58 -20
  15. treescript_builder-0.1.2/treescript_builder/input/file_validation.py +0 -52
  16. treescript_builder-0.1.2/treescript_builder/input/string_validation.py +0 -130
  17. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/LICENSE +0 -0
  18. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/setup.cfg +0 -0
  19. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/__init__.py +0 -0
  20. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/__main__.py +0 -0
  21. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/__init__.py +0 -0
  22. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/instruction_data.py +0 -0
  23. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/path_stack.py +0 -0
  24. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/tree_data.py +0 -0
  25. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/data/tree_state.py +0 -0
  26. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/input/argument_data.py +0 -0
  27. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/input/input_data.py +0 -0
  28. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder/tree/__init__.py +0 -0
  29. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder.egg-info/SOURCES.txt +0 -0
  30. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder.egg-info/dependency_links.txt +0 -0
  31. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/treescript_builder.egg-info/entry_points.txt +0 -0
  32. {treescript_builder-0.1.2 → treescript_builder-0.1.4}/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.2
3
+ Version: 0.1.4
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
@@ -34,27 +34,70 @@ Dynamic: summary
34
34
  Script for Building File Trees.
35
35
  - Makes your dreams come true.
36
36
 
37
- ## How To
38
- 1. Prepare Your TreeScript Designs.
39
- - Initial and Final TreeScripts.
40
- - Build New Project Package/Module.
41
- 2. Logical Order of TreeScript Builder Operations.
42
- 3. Run TreeScript Builder from the CommandLine.
43
- - Apply combinations of Operations to build TreeScript Workflows.
44
-
45
- # Project Technical Details:
37
+ ## How To Make The Most Of TreeScript
38
+ 1. Think in File Trees:
39
+ - Initial and Final Trees.
40
+ - Tree Templates for New Modules, Packages, Apps.
41
+ - Data Directory and Data Labels.
42
+ 2. Prepare Your TreeScript Designs.
43
+ - New Project in any language you want.
44
+ - New Feature in a New Module File Tree.
45
+ 3. Plan TreeScript Operations.
46
+ - Split Larger Trees into multiple TreeScript Files.
47
+ - Combine Trim and Build Operations in a Sequence to meet Workflow requirements.
48
+ - Apply other TreeScript Packages to your Workflow:
49
+ - [TreeScript-Diff] : Difference between two TreeScript files.
50
+ - [TreeScript-Files] : Convert TreeScript into a list of File Paths.
51
+ - [TreeScriptify] : Create TreeScript from existing File Trees.
52
+ 4. Run TreeScript, as part of your Workflow.
53
+ - Install; add aliases to your terminal config file, if desired.
54
+
55
+ ## Script Structure
56
+ - Directory names contain a slash char.
57
+ - The Indentation is 2 spaces per level.
58
+
59
+ ### Directory Slash Chars
60
+ - Both directions are accepted: `\`, `/`
61
+ - Start or End of the Directory Name: `\src` or `src/`
62
+ - No spaces between Name and char.
63
+
64
+ ### Example
65
+
66
+ ```treescript
67
+ src/
68
+ __init__.py
69
+ dir/
70
+ ```
71
+
72
+ # Project Technical Details
46
73
 
47
74
  ## File Tree Builder
48
75
  Execute the File Tree Builder with the `ftb` command.
49
76
  - Creates Files and Directories
50
77
  - If DataLabels are present, a DataDirectory is required.
51
78
 
52
- ### File Tree Trimmer (Remover)
79
+ ## File Tree Trimmer (Remover)
53
80
  Execute the File Tree Remover by adding the `--trim` argument.
54
81
  - Removes Files and Empty Directories.
55
82
  - DataLabels require DataDirectory.
56
83
  - Files are exported to the DataDirectory.
57
84
 
85
+ ### Builder DataLabel
86
+ A `DataLabel` is a link to Text content to be inserted into the file.
87
+ - DataLabel must be present in the DataDirectory, if present in the TreeScript File.
88
+ - DataDirectory contents are checked during the Tree Validation phase of program execution.
89
+
90
+ #### Valid DataLabels
91
+ The range of accepted DataLabel characters has been narrowed to reduce risk.
92
+ - Letters: A - z
93
+ - Numbers: 0 - 9
94
+ - Punctuation: -_.
95
+
96
+ #### Invalid DataLabels
97
+ The dot directories are invalid.
98
+ - Current Dir: .
99
+ - Parent Dir: ..
100
+
58
101
  ## Default Input Reader
59
102
  Before the Reader receives TreeScript, the input is filtered so comments and empty lines are not ever seen by the Reader.
60
103
  The Default Input Reader processes one line at a time and calculates multiple file tree node properties that it stores in dataclass objects.
@@ -65,23 +108,18 @@ It calculates for each node:
65
108
  - Depth in tree
66
109
  - (optional) DataArgument
67
110
 
68
- ## Builder Data Feature
69
- The Builder provides one additional feature that goes beyond creation of the File Tree. This feature enables Files to be created with data inserted immediately.
70
-
71
111
  ### Input Data Argument
72
112
  The Data Argument specifies what will be inserted into the file that is created. The Data Argument is provided in the Input File, immediately after the File Name (separated by a space). There are two types of Data Arguments:
73
113
  - DataLabel
74
114
  - InlineContent
75
115
 
76
- ### Builder DataLabel Feature
77
- A `DataLabel` is a link to Text content to be inserted into the file.
78
- - DataLabel is present in both the DataDirectory, and the TreeScript File.
79
-
80
116
  ## Tree Trim Data Directory Feature
81
117
  The Remover provides an additional feature beyond the removal of files in the Tree. This feature enables Files to be saved to a Data Directory when they are removed. Rather than destroying the file data, it is moved to a new directory.
82
118
 
83
-
84
119
  ## To-Do Features
120
+ - Append/Prepend
121
+ - Overwrite Prevention
122
+ - Inline Content
85
123
 
86
124
  ### Builder File Inline Content (TODO)
87
125
  `Inline Content` is written in the Tree Node Structure Input file itself. To distinguish `DataContent` from a `DataLabel`, the Content must begin with a special character.
@@ -94,7 +132,7 @@ This feature is a neat mid-sized improvement that may open up opportunities for
94
132
  - Adding a new file late in the process.
95
133
  - such as after data directory is already prepared, and you review TS and notice a little thing missing.
96
134
  - value-adding option that helps you build files faster, more convenient than the DataDirectory.
97
- - Workflows that use TreeScript.
135
+ - Workflows that use TreeScript:
98
136
  - Easier To Plan, and Communicate What You Did.
99
137
  - Package Restructuring, Migrations.
100
138
  - Test Environment Setup
@@ -2,27 +2,70 @@
2
2
  Script for Building File Trees.
3
3
  - Makes your dreams come true.
4
4
 
5
- ## How To
6
- 1. Prepare Your TreeScript Designs.
7
- - Initial and Final TreeScripts.
8
- - Build New Project Package/Module.
9
- 2. Logical Order of TreeScript Builder Operations.
10
- 3. Run TreeScript Builder from the CommandLine.
11
- - Apply combinations of Operations to build TreeScript Workflows.
5
+ ## How To Make The Most Of TreeScript
6
+ 1. Think in File Trees:
7
+ - Initial and Final Trees.
8
+ - Tree Templates for New Modules, Packages, Apps.
9
+ - Data Directory and Data Labels.
10
+ 2. Prepare Your TreeScript Designs.
11
+ - New Project in any language you want.
12
+ - New Feature in a New Module File Tree.
13
+ 3. Plan TreeScript Operations.
14
+ - Split Larger Trees into multiple TreeScript Files.
15
+ - Combine Trim and Build Operations in a Sequence to meet Workflow requirements.
16
+ - Apply other TreeScript Packages to your Workflow:
17
+ - [TreeScript-Diff] : Difference between two TreeScript files.
18
+ - [TreeScript-Files] : Convert TreeScript into a list of File Paths.
19
+ - [TreeScriptify] : Create TreeScript from existing File Trees.
20
+ 4. Run TreeScript, as part of your Workflow.
21
+ - Install; add aliases to your terminal config file, if desired.
12
22
 
13
- # Project Technical Details:
23
+ ## Script Structure
24
+ - Directory names contain a slash char.
25
+ - The Indentation is 2 spaces per level.
26
+
27
+ ### Directory Slash Chars
28
+ - Both directions are accepted: `\`, `/`
29
+ - Start or End of the Directory Name: `\src` or `src/`
30
+ - No spaces between Name and char.
31
+
32
+ ### Example
33
+
34
+ ```treescript
35
+ src/
36
+ __init__.py
37
+ dir/
38
+ ```
39
+
40
+ # Project Technical Details
14
41
 
15
42
  ## File Tree Builder
16
43
  Execute the File Tree Builder with the `ftb` command.
17
44
  - Creates Files and Directories
18
45
  - If DataLabels are present, a DataDirectory is required.
19
46
 
20
- ### File Tree Trimmer (Remover)
47
+ ## File Tree Trimmer (Remover)
21
48
  Execute the File Tree Remover by adding the `--trim` argument.
22
49
  - Removes Files and Empty Directories.
23
50
  - DataLabels require DataDirectory.
24
51
  - Files are exported to the DataDirectory.
25
52
 
53
+ ### Builder DataLabel
54
+ A `DataLabel` is a link to Text content to be inserted into the file.
55
+ - DataLabel must be present in the DataDirectory, if present in the TreeScript File.
56
+ - DataDirectory contents are checked during the Tree Validation phase of program execution.
57
+
58
+ #### Valid DataLabels
59
+ The range of accepted DataLabel characters has been narrowed to reduce risk.
60
+ - Letters: A - z
61
+ - Numbers: 0 - 9
62
+ - Punctuation: -_.
63
+
64
+ #### Invalid DataLabels
65
+ The dot directories are invalid.
66
+ - Current Dir: .
67
+ - Parent Dir: ..
68
+
26
69
  ## Default Input Reader
27
70
  Before the Reader receives TreeScript, the input is filtered so comments and empty lines are not ever seen by the Reader.
28
71
  The Default Input Reader processes one line at a time and calculates multiple file tree node properties that it stores in dataclass objects.
@@ -33,23 +76,18 @@ It calculates for each node:
33
76
  - Depth in tree
34
77
  - (optional) DataArgument
35
78
 
36
- ## Builder Data Feature
37
- The Builder provides one additional feature that goes beyond creation of the File Tree. This feature enables Files to be created with data inserted immediately.
38
-
39
79
  ### Input Data Argument
40
80
  The Data Argument specifies what will be inserted into the file that is created. The Data Argument is provided in the Input File, immediately after the File Name (separated by a space). There are two types of Data Arguments:
41
81
  - DataLabel
42
82
  - InlineContent
43
83
 
44
- ### Builder DataLabel Feature
45
- A `DataLabel` is a link to Text content to be inserted into the file.
46
- - DataLabel is present in both the DataDirectory, and the TreeScript File.
47
-
48
84
  ## Tree Trim Data Directory Feature
49
85
  The Remover provides an additional feature beyond the removal of files in the Tree. This feature enables Files to be saved to a Data Directory when they are removed. Rather than destroying the file data, it is moved to a new directory.
50
86
 
51
-
52
87
  ## To-Do Features
88
+ - Append/Prepend
89
+ - Overwrite Prevention
90
+ - Inline Content
53
91
 
54
92
  ### Builder File Inline Content (TODO)
55
93
  `Inline Content` is written in the Tree Node Structure Input file itself. To distinguish `DataContent` from a `DataLabel`, the Content must begin with a special character.
@@ -62,7 +100,7 @@ This feature is a neat mid-sized improvement that may open up opportunities for
62
100
  - Adding a new file late in the process.
63
101
  - such as after data directory is already prepared, and you review TS and notice a little thing missing.
64
102
  - value-adding option that helps you build files faster, more convenient than the DataDirectory.
65
- - Workflows that use TreeScript.
103
+ - Workflows that use TreeScript:
66
104
  - Easier To Plan, and Communicate What You Did.
67
105
  - Package Restructuring, Migrations.
68
106
  - Test Environment Setup
@@ -5,7 +5,7 @@ from setuptools import find_packages, setup
5
5
 
6
6
  setup(
7
7
  name="treescript-builder",
8
- version="0.1.2",
8
+ version="0.1.4",
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',
@@ -13,7 +13,7 @@ setup(
13
13
  url='https://github.com/DK96-OS/treescript-builder',
14
14
  project_urls={
15
15
  "Issues": "https://github.com/DK96-OS/treescript-builder/issues",
16
- "Source Code": "https://github.com/DK96-OS/treescript-builder"
16
+ "Source Code": "https://github.com/DK96-OS/treescript-builder",
17
17
  },
18
18
  license="GPLv3",
19
19
  packages=find_packages(exclude=['test', 'test.*']),
@@ -85,5 +85,5 @@ class DataDirectory:
85
85
  data_files = self._data_dir.glob(data_label)
86
86
  try:
87
87
  return next(data_files)
88
- except StopIteration as s:
88
+ except StopIteration:
89
89
  return None
@@ -25,4 +25,4 @@ def validate_input_arguments(arguments: list[str]) -> InputData:
25
25
  validate_input_file(arg_data.input_file_path_str),
26
26
  validate_directory(arg_data.data_dir_path_str),
27
27
  arg_data.is_reversed
28
- )
28
+ )
@@ -25,7 +25,7 @@ def parse_arguments(
25
25
  exit("No Arguments given.")
26
26
  try: # Initialize the Parser and Parse Immediately
27
27
  parsed_args = _define_arguments().parse_args(args)
28
- except SystemExit as e:
28
+ except SystemExit:
29
29
  exit("Unable to Parse Arguments.")
30
30
  return _validate_arguments(
31
31
  parsed_args.tree_file_name,
@@ -55,9 +55,7 @@ def _validate_arguments(
55
55
  if not validate_name(tree_file_name):
56
56
  exit("The Tree File argument was invalid.")
57
57
  # Validate Data Directory Name Syntax if Present
58
- if data_dir_name is None:
59
- pass
60
- elif not validate_name(data_dir_name):
58
+ if data_dir_name is not None and not validate_name(data_dir_name):
61
59
  exit("The Data Directory argument was invalid.")
62
60
  return ArgumentData(
63
61
  tree_file_name,
@@ -96,4 +94,4 @@ def _define_arguments() -> ArgumentParser:
96
94
  default=False,
97
95
  help='Flag to reverse the File Tree Operation'
98
96
  )
99
- return parser
97
+ return parser
@@ -0,0 +1,75 @@
1
+ """ File Validation Methods.
2
+ - These Methods all raise SystemExit exceptions.
3
+ Author: DK96-OS 2024 - 2025
4
+ """
5
+ from pathlib import Path
6
+ from stat import S_ISLNK
7
+ from sys import exit
8
+
9
+ from treescript_builder.input.string_validation import validate_name
10
+
11
+
12
+ _FILE_SIZE_LIMIT = 32 * 1024 # 32 KB
13
+ _FILE_SIZE_LIMIT_ERROR_MSG = "File larger than 32 KB Limit."
14
+ _FILE_SYMLINK_DISABLED_MSG = "Symlink file paths are disabled."
15
+
16
+ _FILE_DOES_NOT_EXIST_MSG = "The File does not Exist."
17
+ _FILE_READ_OSERROR_MSG = "Failed to Read from File."
18
+ _FILE_VALIDATION_ERROR_MSG = "Invalid Input File Contents."
19
+
20
+ _NOT_A_DIR_ERROR_MSG = "Not a Directory."
21
+ _DIR_DOES_NOT_EXIST_MSG = "The Directory does not exist."
22
+
23
+
24
+ def validate_input_file(file_name: str) -> str | None:
25
+ """ Read the Input File, Validate (non-blank) data, and return Input str.
26
+ - Max FileSize is 32 KB.
27
+ - Symlink type file paths are disabled.
28
+
29
+ **Parameters:**
30
+ - file_name (str): The Name of the Input File.
31
+
32
+ **Returns:**
33
+ str - The String Contents of the Input File.
34
+
35
+ **Raises:**
36
+ SystemExit - If the File does not exist, or is empty, blank, over 32 KB, or if the read or validation operation failed.
37
+ """
38
+ file_path = Path(file_name)
39
+ try:
40
+ if not file_path.exists():
41
+ exit(_FILE_DOES_NOT_EXIST_MSG)
42
+ if S_ISLNK((stat := file_path.lstat()).st_mode):
43
+ exit(_FILE_SYMLINK_DISABLED_MSG)
44
+ if stat.st_size > _FILE_SIZE_LIMIT:
45
+ exit(_FILE_SIZE_LIMIT_ERROR_MSG)
46
+ if (data := file_path.read_text()) is not None:
47
+ if validate_name(data):
48
+ return data
49
+ exit(_FILE_VALIDATION_ERROR_MSG)
50
+ # Fallthrough: return None
51
+ except OSError:
52
+ exit(_FILE_READ_OSERROR_MSG)
53
+ return None
54
+
55
+
56
+ def validate_directory(dir_path_str: str | None) -> Path | None:
57
+ """ Ensure that if the Directory argument is present, it Exists.
58
+ - Allows None to pass through the method.
59
+
60
+ **Parameters:**
61
+ - dir_path_str (str?): The String representation of the Path to the Directory.
62
+
63
+ **Returns:**
64
+ Path? - The Path to the DataDirectory, or None if given input is None.
65
+
66
+ **Raises:**
67
+ SystemExit - If a given path does not exist, or is not a Directory.
68
+ """
69
+ if dir_path_str is None:
70
+ return None
71
+ if (path := Path(dir_path_str)).exists():
72
+ if path.is_dir():
73
+ return path
74
+ exit(_NOT_A_DIR_ERROR_MSG)
75
+ exit(_DIR_DOES_NOT_EXIST_MSG)
@@ -108,7 +108,7 @@ def _validate_node_name(node_name: str) -> tuple[bool, str] | None:
108
108
  if (dir_name := validate_dir_name(node_name)) is not None:
109
109
  return (True, dir_name)
110
110
  # Fall-Through to File Node
111
- except ValueError as e:
111
+ except ValueError:
112
112
  # An error in the dir name, such that it cannot be a file either
113
113
  return None
114
114
  # Is a File
@@ -0,0 +1,144 @@
1
+ """ String Validation Methods.
2
+ Author: DK96-OS 2024 - 2025
3
+ """
4
+ from itertools import permutations, repeat
5
+ from typing import Literal
6
+
7
+
8
+ def validate_name(argument) -> bool:
9
+ """ Determine whether an argument is a non-empty string.
10
+ - Does not count whitespace.
11
+ - Uses the strip method to remove empty space.
12
+
13
+ **Parameters:**
14
+ - argument (str): The given argument, which needs validation.
15
+
16
+ **Returns:**
17
+ bool - True if the argument qualifies as valid.
18
+ """
19
+ if argument is None or not isinstance(argument, str):
20
+ return False
21
+ elif len(argument.strip()) < 1:
22
+ return False
23
+ return True
24
+
25
+
26
+ def validate_data_label(data_label: str) -> bool:
27
+ """ Determine whether a Data Label is Valid.
28
+ - Allows the approved non-alphanumeric chars.
29
+ - The exclamation point (!) is a valid DataLabel, if by itself.
30
+ - If a slash char is found in the string, it is invalid.
31
+ - Small strings (length <= 2) consisting of only punctuation are invalid.
32
+
33
+ **Parameters:**
34
+ - data_label (str): The String to check for validity.
35
+
36
+ **Returns:**
37
+ bool - Whether the String is a valid Data Label.
38
+ """
39
+ if len(data_label) < 3:
40
+ if '!' == data_label: # 33
41
+ return True
42
+ if data_label == '' or _is_invalid_small_tree_string(data_label):
43
+ return False
44
+ elif len(data_label) > 99:
45
+ return False
46
+ for ch in data_label:
47
+ n = ord(ch)
48
+ # ALLOWED: Special Punctuation (-._) Codes: 45, 46, 95
49
+ # Numbers: 48 - 57
50
+ # UpperCase: 65 - 90
51
+ # LowerCase: 97 - 122
52
+ if not (n != 47 and 45 <= n <= 57 if n < 65 else n <= 90 or n <= 122 and (n == 95 or 97 <= n)):
53
+ return False
54
+ return True
55
+
56
+
57
+ def validate_dir_name(dir_name: str) -> str | None:
58
+ """ Determine that a directory is correctly formatted.
59
+
60
+ **Parameters:**
61
+ - dir_name (str): The given input to be validated.
62
+
63
+ **Returns:**
64
+ str? - The valid directory name, or none if it may be a file.
65
+
66
+ **Raises:**
67
+ ValueError - When the name is not suitable for directories or files.
68
+ """
69
+ if (name_length := len(dir_name)) >= 100: # Keep Name Length Reasonable
70
+ raise ValueError(f'Name too Long!: {name_length}')
71
+ # Check for slash chars
72
+ if (name := _filter_slash_chars(dir_name)) is not None: # Is a Dir
73
+ # Validate chars (parent dir, current dir)
74
+ if name in ['', '.', '..']:
75
+ raise ValueError('Invalid Directory')
76
+ return name
77
+ else: # Is a File
78
+ return None
79
+
80
+
81
+ def _is_invalid_small_tree_string(tree_string: str) -> bool:
82
+ """ Checks strings of length 1 or 2 for invalid combinations of chars that are generally valid in larger strings..
83
+ - The dot strings are not allowed because they may escape the DataDirectory.
84
+ - The permutations including line characters are not allowed, to help prevent mistakes (typos) and so on.
85
+
86
+ **Parameters:**
87
+ - data_label (str): The Data Label to check, which should be of length 2 or 1.
88
+
89
+ **Returns:**
90
+ bool - True, if the given parameter is invalid, given the specific filtering criteria.
91
+ """
92
+ return tree_string in (invalid_chars := ('.', '_', '-')) or \
93
+ tree_string in (''.join(repeat(x, 2)) for x in invalid_chars) or \
94
+ tree_string in permutations(invalid_chars, 2)
95
+
96
+
97
+ def _validate_slash_char(dir_name: str) -> Literal['\\', '/'] | None:
98
+ """ Determine which slash char is used by the directory, if it is a directory.
99
+ - Discourages use of both slash chars, by raising ValueError.
100
+
101
+ **Parameters:**
102
+ - dir_name (str): The given input to be validated.
103
+
104
+ **Returns:**
105
+ str? - The slash character used, or none if no chars were found.
106
+
107
+ **Raises:**
108
+ ValueError - When the name contains both slash characters.
109
+ """
110
+ slash: Literal['\\', '/'] | None = None
111
+ if '/' in dir_name:
112
+ slash = '/'
113
+ # Also check for other slash
114
+ if '\\' in dir_name:
115
+ if slash is not None:
116
+ raise ValueError('Invalid character combination: forward and back slash in the same path.')
117
+ slash = '\\'
118
+ return slash
119
+
120
+
121
+ def _filter_slash_chars(dir_name: str) -> str | None:
122
+ """ Remove all of the slash characters and return the directory name.
123
+ - Returns None when there are no slash characters found.
124
+
125
+ **Parameters:**
126
+ - dir_name (str): The given input to be validated.
127
+
128
+ **Returns:**
129
+ str? - The valid directory Name, or None if it may be a file (there were no slash chars found).
130
+
131
+ **Raises:**
132
+ ValueError - When the name is not suitable for directories or files, such as when slash characters are used improperly.
133
+ """
134
+ slash: Literal['\\', '/'] | None = _validate_slash_char(dir_name)
135
+ if slash is None: # No slash chars found.
136
+ return None
137
+ if dir_name.endswith(slash) or dir_name.startswith(slash):
138
+ name: str = dir_name.strip(slash)
139
+ if slash in name: # Has internal slash characters
140
+ raise ValueError('Multi-dir line detected')
141
+ else:
142
+ # Found slash chars only within the node name (multi-dir line)
143
+ raise ValueError('Multi-dir line detected')
144
+ return name
@@ -13,14 +13,12 @@ from treescript_builder.data.tree_state import TreeState
13
13
  def validate_build(
14
14
  tree_data: Generator[TreeData, None, None],
15
15
  data_dir_path: Path | None = None,
16
- verbose: bool = False,
17
16
  ) -> tuple[InstructionData, ...]:
18
17
  """ Validate the Build Instructions.
19
18
 
20
19
  **Parameters:**
21
20
  - tree_data (Generator[TreeData]): The Generator that provides TreeData.
22
21
  - data_dir_path (Path?): The optional Data Directory Path. Default: None.
23
- - verbose (bool): Whether to print DataDirectory information during validation.
24
22
 
25
23
  **Returns:**
26
24
  tuple[InstructionData] - A generator that yields Instructions.
@@ -29,8 +27,6 @@ def validate_build(
29
27
  return tuple(iter(_validate_build_generator(tree_data)))
30
28
  else:
31
29
  data = DataDirectory(data_dir_path)
32
- if verbose:
33
- print(f"Validating Build With DataDir: {data_dir_path}")
34
30
  return tuple(iter(_validate_build_generator_data(tree_data, data)))
35
31
 
36
32
 
@@ -52,7 +52,7 @@ def _create_file(
52
52
  """
53
53
  try:
54
54
  copy2(data, path)
55
- except BaseException as e:
55
+ except OSError:
56
56
  return False
57
57
  return True
58
58
 
@@ -72,6 +72,6 @@ def _make_dir_exist(
72
72
  return True
73
73
  try:
74
74
  path.mkdir(parents=True, exist_ok=True)
75
- except IOError as e:
75
+ except OSError:
76
76
  return False
77
77
  return True
@@ -25,10 +25,9 @@ def _trim(instruct: InstructionData) -> bool:
25
25
  if instruct.data_path is None:
26
26
  try:
27
27
  instruct.path.unlink(missing_ok=True)
28
- return True
29
- except IOError as e:
30
- print("IO File Error")
28
+ except OSError:
31
29
  return False
30
+ return True
32
31
  return _extract_file(instruct.path, instruct.data_path)
33
32
 
34
33
 
@@ -47,9 +46,9 @@ def _extract_file(
47
46
  """
48
47
  try:
49
48
  move(path, data)
50
- return True
51
- except:
49
+ except OSError:
52
50
  return False
51
+ return True
53
52
 
54
53
 
55
54
  def _remove_dir(
@@ -65,6 +64,6 @@ def _remove_dir(
65
64
  """
66
65
  try:
67
66
  path.rmdir()
68
- except BaseException as e:
67
+ except OSError:
69
68
  return False
70
69
  return True
@@ -13,7 +13,6 @@ from treescript_builder.data.tree_state import TreeState
13
13
  def validate_trim(
14
14
  tree_data: Generator[TreeData, None, None],
15
15
  data_dir_path: Path | None = None,
16
- verbose: bool = False,
17
16
  ) -> tuple[InstructionData, ...]:
18
17
  """ Validate the Trim Instructions.
19
18
 
@@ -29,8 +28,6 @@ def validate_trim(
29
28
  return tuple(iter(_validate_trim_generator(tree_data)))
30
29
  else:
31
30
  data = DataDirectory(data_dir_path)
32
- if verbose:
33
- print(f"Validating Trim With DataDir: {data_dir_path}")
34
31
  return tuple(iter(_validate_trim_generator_data(tree_data, data)))
35
32
 
36
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: treescript-builder
3
- Version: 0.1.2
3
+ Version: 0.1.4
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
@@ -34,27 +34,70 @@ Dynamic: summary
34
34
  Script for Building File Trees.
35
35
  - Makes your dreams come true.
36
36
 
37
- ## How To
38
- 1. Prepare Your TreeScript Designs.
39
- - Initial and Final TreeScripts.
40
- - Build New Project Package/Module.
41
- 2. Logical Order of TreeScript Builder Operations.
42
- 3. Run TreeScript Builder from the CommandLine.
43
- - Apply combinations of Operations to build TreeScript Workflows.
44
-
45
- # Project Technical Details:
37
+ ## How To Make The Most Of TreeScript
38
+ 1. Think in File Trees:
39
+ - Initial and Final Trees.
40
+ - Tree Templates for New Modules, Packages, Apps.
41
+ - Data Directory and Data Labels.
42
+ 2. Prepare Your TreeScript Designs.
43
+ - New Project in any language you want.
44
+ - New Feature in a New Module File Tree.
45
+ 3. Plan TreeScript Operations.
46
+ - Split Larger Trees into multiple TreeScript Files.
47
+ - Combine Trim and Build Operations in a Sequence to meet Workflow requirements.
48
+ - Apply other TreeScript Packages to your Workflow:
49
+ - [TreeScript-Diff] : Difference between two TreeScript files.
50
+ - [TreeScript-Files] : Convert TreeScript into a list of File Paths.
51
+ - [TreeScriptify] : Create TreeScript from existing File Trees.
52
+ 4. Run TreeScript, as part of your Workflow.
53
+ - Install; add aliases to your terminal config file, if desired.
54
+
55
+ ## Script Structure
56
+ - Directory names contain a slash char.
57
+ - The Indentation is 2 spaces per level.
58
+
59
+ ### Directory Slash Chars
60
+ - Both directions are accepted: `\`, `/`
61
+ - Start or End of the Directory Name: `\src` or `src/`
62
+ - No spaces between Name and char.
63
+
64
+ ### Example
65
+
66
+ ```treescript
67
+ src/
68
+ __init__.py
69
+ dir/
70
+ ```
71
+
72
+ # Project Technical Details
46
73
 
47
74
  ## File Tree Builder
48
75
  Execute the File Tree Builder with the `ftb` command.
49
76
  - Creates Files and Directories
50
77
  - If DataLabels are present, a DataDirectory is required.
51
78
 
52
- ### File Tree Trimmer (Remover)
79
+ ## File Tree Trimmer (Remover)
53
80
  Execute the File Tree Remover by adding the `--trim` argument.
54
81
  - Removes Files and Empty Directories.
55
82
  - DataLabels require DataDirectory.
56
83
  - Files are exported to the DataDirectory.
57
84
 
85
+ ### Builder DataLabel
86
+ A `DataLabel` is a link to Text content to be inserted into the file.
87
+ - DataLabel must be present in the DataDirectory, if present in the TreeScript File.
88
+ - DataDirectory contents are checked during the Tree Validation phase of program execution.
89
+
90
+ #### Valid DataLabels
91
+ The range of accepted DataLabel characters has been narrowed to reduce risk.
92
+ - Letters: A - z
93
+ - Numbers: 0 - 9
94
+ - Punctuation: -_.
95
+
96
+ #### Invalid DataLabels
97
+ The dot directories are invalid.
98
+ - Current Dir: .
99
+ - Parent Dir: ..
100
+
58
101
  ## Default Input Reader
59
102
  Before the Reader receives TreeScript, the input is filtered so comments and empty lines are not ever seen by the Reader.
60
103
  The Default Input Reader processes one line at a time and calculates multiple file tree node properties that it stores in dataclass objects.
@@ -65,23 +108,18 @@ It calculates for each node:
65
108
  - Depth in tree
66
109
  - (optional) DataArgument
67
110
 
68
- ## Builder Data Feature
69
- The Builder provides one additional feature that goes beyond creation of the File Tree. This feature enables Files to be created with data inserted immediately.
70
-
71
111
  ### Input Data Argument
72
112
  The Data Argument specifies what will be inserted into the file that is created. The Data Argument is provided in the Input File, immediately after the File Name (separated by a space). There are two types of Data Arguments:
73
113
  - DataLabel
74
114
  - InlineContent
75
115
 
76
- ### Builder DataLabel Feature
77
- A `DataLabel` is a link to Text content to be inserted into the file.
78
- - DataLabel is present in both the DataDirectory, and the TreeScript File.
79
-
80
116
  ## Tree Trim Data Directory Feature
81
117
  The Remover provides an additional feature beyond the removal of files in the Tree. This feature enables Files to be saved to a Data Directory when they are removed. Rather than destroying the file data, it is moved to a new directory.
82
118
 
83
-
84
119
  ## To-Do Features
120
+ - Append/Prepend
121
+ - Overwrite Prevention
122
+ - Inline Content
85
123
 
86
124
  ### Builder File Inline Content (TODO)
87
125
  `Inline Content` is written in the Tree Node Structure Input file itself. To distinguish `DataContent` from a `DataLabel`, the Content must begin with a special character.
@@ -94,7 +132,7 @@ This feature is a neat mid-sized improvement that may open up opportunities for
94
132
  - Adding a new file late in the process.
95
133
  - such as after data directory is already prepared, and you review TS and notice a little thing missing.
96
134
  - value-adding option that helps you build files faster, more convenient than the DataDirectory.
97
- - Workflows that use TreeScript.
135
+ - Workflows that use TreeScript:
98
136
  - Easier To Plan, and Communicate What You Did.
99
137
  - Package Restructuring, Migrations.
100
138
  - Test Environment Setup
@@ -1,52 +0,0 @@
1
- """ File Validation Methods.
2
- - These Methods all raise SystemExit exceptions.
3
- Author: DK96-OS 2024 - 2025
4
- """
5
- from pathlib import Path
6
- from sys import exit
7
-
8
- from treescript_builder.input.string_validation import validate_name
9
-
10
-
11
- def validate_input_file(file_name: str) -> str | None:
12
- """ Read the Input File, Validate (non-blank) data, and return Input str.
13
-
14
- **Parameters:**
15
- - file_name (str): The Name of the Input File.
16
-
17
- **Returns:**
18
- str - The String Contents of the Input File.
19
-
20
- **Raises:**
21
- SystemExit - If the File does not exist, or is empty or blank, or read failed.
22
- """
23
- file_path = Path(file_name)
24
- if not file_path.exists():
25
- exit("The Input File does not Exist.")
26
- try:
27
- if (data := file_path.read_text()) is not None and validate_name(data):
28
- return data
29
- except OSError as e:
30
- exit("Failed to Read from File.")
31
- return None
32
-
33
-
34
- def validate_directory(dir_path_str: str | None) -> Path | None:
35
- """ Ensure that if the Directory is present, it Exists.
36
-
37
- **Parameters:**
38
- - dir_path_str (str, optional): The String representation of the Path to the Directory.
39
-
40
- **Returns:**
41
- Path? - The , or None if given input is None.
42
-
43
- **Raises:**
44
- SystemExit - If a given path does not exist.
45
- """
46
- if dir_path_str is None:
47
- return None
48
- if not validate_name(dir_path_str):
49
- exit("Data Directory is invalid")
50
- if (path := Path(dir_path_str)).exists():
51
- return path
52
- exit("The given Directory does not exist!")
@@ -1,130 +0,0 @@
1
- """ String Validation Methods.
2
- Author: DK96-OS 2024 - 2025
3
- """
4
- from typing import Literal
5
-
6
-
7
- def validate_name(argument) -> bool:
8
- """ Determine whether an argument is a non-empty string.
9
- - Does not count whitespace.
10
- - Uses the strip method to remove empty space.
11
-
12
- **Parameters:**
13
- - argument (str) : The given argument.
14
-
15
- **Returns:**
16
- bool - True if the argument qualifies as valid.
17
- """
18
- if argument is None or not isinstance(argument, str):
19
- return False
20
- elif len(argument.strip()) < 1:
21
- return False
22
- return True
23
-
24
-
25
- def validate_data_label(data_label: str) -> bool:
26
- """ Determine whether a Data Label is Valid.
27
-
28
- **Parameters:**
29
- - data_label (str): The String to check for validity.
30
-
31
- **Returns:**
32
- bool - Whether the String is a valid Data Label.
33
- """
34
- if not 0 < len(data_label) < 100:
35
- return False
36
- if '/' in data_label or '\\' in data_label:
37
- return False
38
- # Remove Dash Characters
39
- if '-' in data_label:
40
- data_label = data_label.replace('-', '')
41
- # Remove Underscore Characters
42
- if '_' in data_label:
43
- data_label = data_label.replace('_', '')
44
- # Remove Dot Characters
45
- if '.' in data_label:
46
- data_label = data_label.replace('.', '')
47
- if '!' == data_label:
48
- return True
49
- # All Remaining Characters must be alphanumeric
50
- return data_label.isalnum()
51
-
52
-
53
- def validate_dir_name(dir_name: str) -> str | None:
54
- """ Determine that a directory is correctly formatted.
55
- - This method should be called once for each slash type.
56
-
57
- **Parameters:**
58
- - dir_name (str): The given input to be validated.
59
-
60
- **Returns:**
61
- str | None - The valid directory name, or none if it may be a file.
62
-
63
- **Raises:**
64
- ValueError - When the name is not suitable for directories or files.
65
- """
66
- # Keep Name Length Reasonable
67
- if (name_length := len(dir_name)) >= 100:
68
- raise ValueError(f'Name too Long!: {name_length}')
69
- # Check for slash characters
70
- if (name := _filter_slash_chars(dir_name)) is not None:
71
- # Is a Dir
72
- if len(name) == 0:
73
- raise ValueError('The name is empty')
74
- # Check for invalid characters (parent dir, current dir)
75
- if name in ['.', '..']:
76
- raise ValueError('Invalid Directory')
77
- return name
78
- # Is a File
79
- return None
80
-
81
-
82
- def _validate_slash_char(dir_name: str) -> Literal['\\', '/'] | None:
83
- """ Determine which slash char is used by the directory, if it is a directory.
84
- - Discourages use of both slash chars, by raising ValueError.
85
-
86
- **Parameters:**
87
- - dir_name (str): The given input to be validated.
88
-
89
- **Returns:**
90
- str | None - The slash character used, or none if no chars were found.
91
-
92
- **Raises:**
93
- ValueError - When the name contains both slash characters.
94
- """
95
- slash = None
96
- if '/' in dir_name:
97
- slash = '/'
98
- if '\\' in dir_name:
99
- if slash is not None:
100
- raise ValueError('Invalid Directory slash character combination.')
101
- slash = '\\'
102
- return slash
103
-
104
-
105
- def _filter_slash_chars(dir_name: str) -> str | None:
106
- """ Remove all of the slash characters and return the directory name.
107
- - Returns None when there are no slash characters found.
108
- - Raises ValueError when slash characters are used improperly.
109
-
110
- **Parameters:**
111
- - dir_name (str): The given input to be validated.
112
-
113
- **Returns:**
114
- str | None - The valid directory name, or none if it may be a file.
115
-
116
- **Raises:**
117
- ValueError - When the name is not suitable for directories or files.
118
- """
119
- slash = _validate_slash_char(dir_name)
120
- if slash is None:
121
- return None
122
- if dir_name.endswith(slash) or dir_name.startswith(slash):
123
- name = dir_name.strip(slash)
124
- # Check for internal slash characters
125
- if slash in name:
126
- raise ValueError('Multi-dir line detected')
127
- else:
128
- # Found slash chars only within the node name (multi-dir line)
129
- raise ValueError('Multi-dir line detected')
130
- return name