minecraft-datapack-language 15.4.1__py3-none-any.whl → 15.4.2__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.
@@ -6,6 +6,16 @@ from dataclasses import dataclass
6
6
  from typing import Optional, List, Any
7
7
  import os
8
8
 
9
+ # Import color utilities
10
+ try:
11
+ from .cli_colors import color
12
+ except ImportError:
13
+ # Fallback if colors aren't available
14
+ class DummyColor:
15
+ def __getattr__(self, name):
16
+ return lambda text: text
17
+ color = DummyColor()
18
+
9
19
 
10
20
  @dataclass
11
21
  class MDLError(BaseException):
@@ -27,32 +37,32 @@ class MDLError(BaseException):
27
37
  # Show relative path if possible
28
38
  try:
29
39
  rel_path = os.path.relpath(self.file_path)
30
- parts.append(f"File: {rel_path}")
40
+ parts.append(f"{color.file_path('File:')} {color.file_path(rel_path)}")
31
41
  except ValueError:
32
- parts.append(f"File: {self.file_path}")
42
+ parts.append(f"{color.file_path('File:')} {color.file_path(self.file_path)}")
33
43
 
34
44
  if self.line is not None:
35
- parts.append(f"Line: {self.line}")
45
+ parts.append(f"{color.line_number('Line:')} {color.line_number(str(self.line))}")
36
46
  if self.column is not None:
37
- parts.append(f"Column: {self.column}")
47
+ parts.append(f"{color.column_number('Column:')} {color.column_number(str(self.column))}")
38
48
 
39
49
  if self.line_content:
40
- parts.append(f"Code: {self.line_content.strip()}")
50
+ parts.append(f"{color.context('Code:')} {color.context(self.line_content.strip())}")
41
51
  if self.column is not None:
42
52
  # Add a caret to show the exact position
43
53
  indent = " " * (self.column - 1)
44
- parts.append(f" {indent}^")
54
+ parts.append(f" {indent}{color.error('^')}")
45
55
 
46
- parts.append(f"Error: {self.message}")
56
+ parts.append(f"{color.error_type('Error:')} {color.error(self.message)}")
47
57
 
48
58
  if self.suggestion:
49
- parts.append(f"Suggestion: {self.suggestion}")
59
+ parts.append(f"{color.suggestion('Suggestion:')} {color.suggestion(self.suggestion)}")
50
60
 
51
61
  # Add context if we have file and line information
52
62
  if self.file_path and self.line is not None:
53
63
  context = format_error_context(self.file_path, self.line, self.column, self.context_lines)
54
64
  if context:
55
- parts.append(f"\nContext:\n{context}")
65
+ parts.append(f"\n{color.context('Context:')}\n{context}")
56
66
 
57
67
  return "\n".join(parts)
58
68
 
@@ -75,7 +85,7 @@ class MDLSyntaxError(MDLError):
75
85
  error_type: str = "syntax_error"
76
86
 
77
87
  def __str__(self) -> str:
78
- return f"Syntax Error: {super().__str__()}"
88
+ return f"{color.error_type('Syntax Error:')} {super().__str__()}"
79
89
 
80
90
 
81
91
  @dataclass
@@ -84,7 +94,7 @@ class MDLLexerError(MDLError):
84
94
  error_type: str = "lexer_error"
85
95
 
86
96
  def __str__(self) -> str:
87
- return f"Lexer Error: {super().__str__()}"
97
+ return f"{color.error_type('Lexer Error:')} {super().__str__()}"
88
98
 
89
99
 
90
100
  @dataclass
@@ -93,52 +103,43 @@ class MDLParserError(MDLError):
93
103
  error_type: str = "parser_error"
94
104
 
95
105
  def __str__(self) -> str:
96
- return f"Parser Error: {super().__str__()}"
106
+ return f"{color.error_type('Parser Error:')} {super().__str__()}"
97
107
 
98
108
 
99
109
  @dataclass
100
110
  class MDLValidationError(MDLError):
101
- """Error during validation."""
111
+ """Validation error during semantic analysis."""
102
112
  error_type: str = "validation_error"
103
113
 
104
114
  def __str__(self) -> str:
105
- return f"Validation Error: {super().__str__()}"
106
-
107
-
108
- @dataclass
109
- class MDLBuildError(MDLError):
110
- """Error during build process."""
111
- error_type: str = "build_error"
112
-
113
- def __str__(self) -> str:
114
- return f"Build Error: {super().__str__()}"
115
+ return f"{color.error_type('Validation Error:')} {super().__str__()}"
115
116
 
116
117
 
117
118
  @dataclass
118
- class MDLCompilationError(MDLError):
119
- """Error during compilation."""
120
- error_type: str = "compilation_error"
119
+ class MDLConfigurationError(MDLError):
120
+ """Configuration or setup error."""
121
+ error_type: str = "configuration_error"
121
122
 
122
123
  def __str__(self) -> str:
123
- return f"Compilation Error: {super().__str__()}"
124
+ return f"{color.error_type('Configuration Error:')} {super().__str__()}"
124
125
 
125
126
 
126
127
  @dataclass
127
128
  class MDLFileError(MDLError):
128
- """Error related to file operations."""
129
+ """File I/O or access error."""
129
130
  error_type: str = "file_error"
130
131
 
131
132
  def __str__(self) -> str:
132
- return f"File Error: {super().__str__()}"
133
+ return f"{color.error_type('File Error:')} {super().__str__()}"
133
134
 
134
135
 
135
136
  @dataclass
136
- class MDLConfigurationError(MDLError):
137
- """Error related to configuration."""
138
- error_type: str = "configuration_error"
137
+ class MDLWarning(MDLError):
138
+ """Warning message (non-fatal)."""
139
+ error_type: str = "warning"
139
140
 
140
141
  def __str__(self) -> str:
141
- return f"Configuration Error: {super().__str__()}"
142
+ return f"{color.warning('Warning:')} {super().__str__()}"
142
143
 
143
144
 
144
145
  class MDLErrorCollector:
@@ -148,12 +149,16 @@ class MDLErrorCollector:
148
149
  self.errors: List[MDLError] = []
149
150
  self.warnings: List[MDLError] = []
150
151
 
151
- def add_error(self, error: MDLError) -> None:
152
- """Add an error to the collection."""
153
- self.errors.append(error)
152
+ def add_error(self, error: MDLError):
153
+ """Add an error to the collector."""
154
+ if isinstance(error, MDLWarning):
155
+ self.warnings.append(error)
156
+ else:
157
+ self.errors.append(error)
154
158
 
155
- def add_warning(self, warning: MDLError) -> None:
156
- """Add a warning to the collection."""
159
+ def add_warning(self, message: str, **kwargs):
160
+ """Add a warning message."""
161
+ warning = create_error(MDLWarning, message, **kwargs)
157
162
  self.warnings.append(warning)
158
163
 
159
164
  def has_errors(self) -> bool:
@@ -164,114 +169,104 @@ class MDLErrorCollector:
164
169
  """Check if there are any warnings."""
165
170
  return len(self.warnings) > 0
166
171
 
167
- def get_all_issues(self) -> List[MDLError]:
168
- """Get all errors and warnings."""
169
- return self.errors + self.warnings
172
+ def get_error_count(self) -> int:
173
+ """Get the total number of errors."""
174
+ return len(self.errors)
170
175
 
171
- def print_errors(self, verbose: bool = False, ignore_warnings: bool = False) -> None:
172
- """Print all errors and warnings."""
173
- if not self.errors and not self.warnings:
174
- return
176
+ def get_warning_count(self) -> int:
177
+ """Get the total number of warnings."""
178
+ return len(self.warnings)
179
+
180
+ def clear(self):
181
+ """Clear all errors and warnings."""
182
+ self.errors.clear()
183
+ self.warnings.clear()
184
+
185
+ def print_errors(self, verbose: bool = True, ignore_warnings: bool = False):
186
+ """Print all collected errors and warnings."""
187
+ if not ignore_warnings and self.warnings:
188
+ print(f"\n{color.warning(f'⚠️ {len(self.warnings)} Warning(s):')}")
189
+ for warning in self.warnings:
190
+ print(f"\n{warning}")
175
191
 
176
192
  if self.errors:
177
- print(f"\nERROR: Found {len(self.errors)} error(s):")
178
- for i, error in enumerate(self.errors, 1):
179
- print(f"\n{i}. {error}")
193
+ print(f"\n{color.error(f'❌ {len(self.errors)} Error(s):')}")
194
+ for error in self.errors:
195
+ print(f"\n{error}")
180
196
 
181
- if self.warnings and not ignore_warnings:
182
- print(f"\nWARNING: Found {len(self.warnings)} warning(s):")
183
- for i, warning in enumerate(self.warnings, 1):
184
- print(f"\n{i}. {warning}")
197
+ if not self.errors and not self.warnings:
198
+ print(f"\n{color.success('✅ No errors or warnings found!')}")
185
199
 
186
- def raise_if_errors(self) -> None:
200
+ def raise_if_errors(self):
187
201
  """Raise an exception if there are any errors."""
188
202
  if self.has_errors():
189
- error_messages = [str(error) for error in self.errors]
190
- raise MDLBuildError(
191
- message=f"Build failed with {len(self.errors)} error(s):\n" + "\n".join(error_messages),
192
- error_type="build_error"
203
+ error_summary = f"Compilation failed with {len(self.errors)} error(s)"
204
+ if self.warnings:
205
+ error_summary += f" and {len(self.warnings)} warning(s)"
206
+
207
+ # Create a summary error
208
+ summary_error = create_error(
209
+ MDLConfigurationError,
210
+ error_summary,
211
+ suggestion="Fix the errors above and try again."
193
212
  )
194
-
195
- def get_summary(self) -> str:
196
- """Get a summary of errors and warnings."""
197
- summary_parts = []
198
-
199
- if self.errors:
200
- summary_parts.append(f"{len(self.errors)} error(s)")
201
-
202
- if self.warnings:
203
- summary_parts.append(f"{len(self.warnings)} warning(s)")
204
-
205
- if not summary_parts:
206
- return "No issues found"
207
-
208
- return ", ".join(summary_parts)
213
+
214
+ # Add all errors as context
215
+ for error in self.errors:
216
+ summary_error.message += f"\n- {error.message}"
217
+
218
+ raise summary_error
209
219
 
210
220
 
211
- def create_error(error_type: str, message: str, file_path: Optional[str] = None,
221
+ def create_error(error_class: type, message: str, file_path: Optional[str] = None,
212
222
  line: Optional[int] = None, column: Optional[int] = None,
213
- line_content: Optional[str] = None, suggestion: Optional[str] = None) -> MDLError:
214
- """Factory function to create appropriate error type."""
215
- error_classes = {
216
- "syntax": MDLSyntaxError,
217
- "lexer": MDLLexerError,
218
- "parser": MDLParserError,
219
- "validation": MDLValidationError,
220
- "build": MDLBuildError,
221
- "compilation": MDLCompilationError,
222
- "file": MDLFileError,
223
- "configuration": MDLConfigurationError
224
- }
225
-
226
- error_class = error_classes.get(error_type, MDLError)
223
+ line_content: Optional[str] = None, suggestion: Optional[str] = None,
224
+ context_lines: int = 2) -> MDLError:
225
+ """Create an MDL error with the given information."""
227
226
  return error_class(
228
227
  message=message,
229
228
  file_path=file_path,
230
229
  line=line,
231
230
  column=column,
232
231
  line_content=line_content,
233
- error_type=error_type,
234
- suggestion=suggestion
232
+ suggestion=suggestion,
233
+ context_lines=context_lines
235
234
  )
236
235
 
237
236
 
238
- def get_line_content(file_path: str, line_number: int) -> Optional[str]:
239
- """Get the content of a specific line from a file."""
240
- try:
241
- with open(file_path, 'r', encoding='utf-8') as f:
242
- lines = f.readlines()
243
- if 1 <= line_number <= len(lines):
244
- return lines[line_number - 1]
245
- except (FileNotFoundError, UnicodeDecodeError):
246
- pass
247
- return None
248
-
249
-
250
- def format_error_context(file_path: str, line: int, column: int,
251
- context_lines: int = 2) -> str:
237
+ def format_error_context(file_path: str, line: int, column: Optional[int], context_lines: int) -> str:
252
238
  """Format error context with surrounding lines."""
253
239
  try:
254
240
  with open(file_path, 'r', encoding='utf-8') as f:
255
241
  lines = f.readlines()
256
242
 
257
- start_line = max(1, line - context_lines)
243
+ if not lines:
244
+ return ""
245
+
246
+ # Calculate line range to show
247
+ start_line = max(0, line - context_lines - 1)
258
248
  end_line = min(len(lines), line + context_lines)
259
249
 
260
- context = []
261
- for i in range(start_line, end_line + 1):
262
- prefix = ">>> " if i == line else " "
263
- line_num = f"{i:4d}"
264
- content = lines[i - 1].rstrip('\n')
265
- context.append(f"{prefix}{line_num}: {content}")
250
+ context_parts = []
251
+ for i in range(start_line, end_line):
252
+ line_num = i + 1
253
+ line_content = lines[i].rstrip('\n\r')
266
254
 
267
- if i == line and column is not None:
268
- # Add caret to show exact position
269
- indent = " " * (column - 1)
270
- context.append(f" {indent}^")
255
+ if line_num == line:
256
+ # Highlight the error line
257
+ prefix = f"{color.line_number(f'{line_num:3d}:')} "
258
+ content = color.error(line_content)
259
+ context_parts.append(f"{prefix}{content}")
260
+ else:
261
+ # Show context lines
262
+ prefix = f"{color.context(f'{line_num:3d}:')} "
263
+ content = color.context(line_content)
264
+ context_parts.append(f"{prefix}{content}")
265
+
266
+ return "\n".join(context_parts)
271
267
 
272
- return "\n".join(context)
273
- except (FileNotFoundError, UnicodeDecodeError):
274
- return f"Unable to read file: {file_path}"
268
+ except Exception:
269
+ return "Unable to load file context"
275
270
 
276
271
 
277
272
  def create_syntax_error(message: str, file_path: Optional[str] = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: minecraft-datapack-language
3
- Version: 15.4.1
3
+ Version: 15.4.2
4
4
  Summary: Compile JavaScript-style MDL language or Python API into a Minecraft datapack (1.21+ ready). Features variables, control flow, error handling, and VS Code extension.
5
5
  Project-URL: Homepage, https://www.mcmdl.com
6
6
  Project-URL: Documentation, https://www.mcmdl.com/docs
@@ -1,25 +1,25 @@
1
1
  minecraft_datapack_language/__init__.py,sha256=i-qCchbe5b2Fshgc6yCU9mddOLs2UBt9SAcLqfUIrT0,606
2
- minecraft_datapack_language/_version.py,sha256=Ohcg9Yyw2RsH29peJV8QS4k6ROTO-G8se_Vhy3xGc3M,706
2
+ minecraft_datapack_language/_version.py,sha256=ryxn9HWHc1n3aIKcrjY9Y_8_9ek9rdgANmjmrldYgYI,706
3
3
  minecraft_datapack_language/ast_nodes.py,sha256=pgjI2Nlap3ixFPgWqGSkqncG9zB91h5BKgRjtcJqMew,2118
4
4
  minecraft_datapack_language/cli.py,sha256=p5A_tEEXugN2NhQFbbgfwi4FxbWYD91RWeKR_A3Vuec,6263
5
- minecraft_datapack_language/cli_build.py,sha256=YEEStmQfZg4uZqbhDQc3z8jExCNJ08dAuP632wOBC7M,47610
5
+ minecraft_datapack_language/cli_build.py,sha256=8G0YtPd9hoG2s5aJwKM5HOtz6nDAVRj90XzxhvhlOy0,8213
6
6
  minecraft_datapack_language/cli_check.py,sha256=bPq9gHsxQ1CIiftkrAtRCifWkVAyjp5c8Oay2NNQ1qs,6277
7
7
  minecraft_datapack_language/cli_colors.py,sha256=Ims0KbdYpsiwoqv96Y_g89uOB5l1qdETm_P51rkljfk,7884
8
- minecraft_datapack_language/cli_help.py,sha256=jUTHUQBONAZKVTdQK9tNPXq4c_6xpsafNOvHDjkEldg,12243
8
+ minecraft_datapack_language/cli_help.py,sha256=n2cJLYlKRz0umCgWuKrZm2Il0qEAkOloSUOcZvPa4Qk,13186
9
9
  minecraft_datapack_language/cli_new.py,sha256=Uw-xuW6KTTRTeOsnS3wgoZnna7xA203SM8qvUUDFHTk,8112
10
10
  minecraft_datapack_language/cli_utils.py,sha256=nl22j96vpCW0XRMpD_zjwamnMU4e4LXEjACsnwiFGzs,9931
11
11
  minecraft_datapack_language/dir_map.py,sha256=HmxFkuvWGkzHF8o_GFb4BpuMCRc6QMw8UbmcAI8JVdY,1788
12
12
  minecraft_datapack_language/expression_processor.py,sha256=GN6cuRNvgI8TrV6YnEHrA9P0X-ACTT7rCBh4WlOPjSI,20140
13
13
  minecraft_datapack_language/linter.py,sha256=7UqbygC5JPCGg-BSOq65NB2xEJBu_OUOYIIgmHItO2M,16567
14
- minecraft_datapack_language/mdl_errors.py,sha256=a_-683gjF3gfGRpDMbRgCXmXD9_aYYBmLodNH6fe29A,11596
14
+ minecraft_datapack_language/mdl_errors.py,sha256=O0lIem8C6GtOeYnbV0E0-ZGNVx9G7aD5X5LuzsvFCfs,11907
15
15
  minecraft_datapack_language/mdl_lexer_js.py,sha256=VvbhKm727khdSAABxa03hoIIA7H3hWi3RLp9BSXbhY0,28277
16
16
  minecraft_datapack_language/mdl_linter.py,sha256=z85xoAglENurCh30bR7kEHZ_JeMxcYaLDcGNRAl-RAI,17253
17
17
  minecraft_datapack_language/mdl_parser_js.py,sha256=SQzc67pKls3NVnQaT0xIILGqpZYAmcZn78TQ0KIM4TE,40216
18
18
  minecraft_datapack_language/pack.py,sha256=nYiXQ3jgJlDfc4m-65f7C2LFhDRioaUU_XVy6Na4SJI,34625
19
19
  minecraft_datapack_language/utils.py,sha256=Aq0HAGlXqj9BUTEjaEilpvzEW0EtZYYMMwOqG9db6dE,684
20
- minecraft_datapack_language-15.4.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
21
- minecraft_datapack_language-15.4.1.dist-info/METADATA,sha256=GKfvUfLEIW3Jpbllp2U8_kuvrCWb0m8We9yBNF7Q3_M,35229
22
- minecraft_datapack_language-15.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
- minecraft_datapack_language-15.4.1.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
24
- minecraft_datapack_language-15.4.1.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
25
- minecraft_datapack_language-15.4.1.dist-info/RECORD,,
20
+ minecraft_datapack_language-15.4.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
21
+ minecraft_datapack_language-15.4.2.dist-info/METADATA,sha256=U4e9OFniRONfR61-P6gGWyO5a2xLevPGxR9bGS0ZzdQ,35229
22
+ minecraft_datapack_language-15.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ minecraft_datapack_language-15.4.2.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
24
+ minecraft_datapack_language-15.4.2.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
25
+ minecraft_datapack_language-15.4.2.dist-info/RECORD,,