minecraft-datapack-language 15.4.1__py3-none-any.whl → 15.4.3__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.
- minecraft_datapack_language/_version.py +2 -2
- minecraft_datapack_language/cli_build.py +195 -1019
- minecraft_datapack_language/cli_help.py +371 -404
- minecraft_datapack_language/mdl_errors.py +112 -117
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/METADATA +1 -1
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/RECORD +10 -10
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/WHEEL +0 -0
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/entry_points.txt +0 -0
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/licenses/LICENSE +0 -0
- {minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/top_level.txt +0 -0
@@ -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"\
|
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
|
-
"""
|
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
|
119
|
-
"""
|
120
|
-
error_type: str = "
|
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"
|
124
|
+
return f"{color.error_type('Configuration Error:')} {super().__str__()}"
|
124
125
|
|
125
126
|
|
126
127
|
@dataclass
|
127
128
|
class MDLFileError(MDLError):
|
128
|
-
"""
|
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
|
137
|
-
"""
|
138
|
-
error_type: str = "
|
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"
|
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)
|
152
|
-
"""Add an error to the
|
153
|
-
|
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,
|
156
|
-
"""Add a warning
|
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
|
168
|
-
"""Get
|
169
|
-
return self.errors
|
172
|
+
def get_error_count(self) -> int:
|
173
|
+
"""Get the total number of errors."""
|
174
|
+
return len(self.errors)
|
170
175
|
|
171
|
-
def
|
172
|
-
"""
|
173
|
-
|
174
|
-
|
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"\
|
178
|
-
for
|
179
|
-
print(f"\n{
|
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.
|
182
|
-
print(f"\
|
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)
|
200
|
+
def raise_if_errors(self):
|
187
201
|
"""Raise an exception if there are any errors."""
|
188
202
|
if self.has_errors():
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
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(
|
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
|
214
|
-
|
215
|
-
|
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
|
-
|
234
|
-
|
232
|
+
suggestion=suggestion,
|
233
|
+
context_lines=context_lines
|
235
234
|
)
|
236
235
|
|
237
236
|
|
238
|
-
def
|
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
|
-
|
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
|
-
|
261
|
-
for i in range(start_line, end_line
|
262
|
-
|
263
|
-
|
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
|
268
|
-
#
|
269
|
-
|
270
|
-
|
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
|
-
|
273
|
-
|
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.
|
3
|
+
Version: 15.4.3
|
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
|
{minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/RECORD
RENAMED
@@ -1,25 +1,25 @@
|
|
1
1
|
minecraft_datapack_language/__init__.py,sha256=i-qCchbe5b2Fshgc6yCU9mddOLs2UBt9SAcLqfUIrT0,606
|
2
|
-
minecraft_datapack_language/_version.py,sha256=
|
2
|
+
minecraft_datapack_language/_version.py,sha256=TWxTg6FF2asyPjeyhUrfqiyvE3AJnzMlsJoqmuMDSQU,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=
|
5
|
+
minecraft_datapack_language/cli_build.py,sha256=hbBqAI0VeoffF2EPaZu0HSCRfFBsEnjpwSZm0PNCfDE,9023
|
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=
|
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=
|
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.
|
21
|
-
minecraft_datapack_language-15.4.
|
22
|
-
minecraft_datapack_language-15.4.
|
23
|
-
minecraft_datapack_language-15.4.
|
24
|
-
minecraft_datapack_language-15.4.
|
25
|
-
minecraft_datapack_language-15.4.
|
20
|
+
minecraft_datapack_language-15.4.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
21
|
+
minecraft_datapack_language-15.4.3.dist-info/METADATA,sha256=fwKp0v5RagXdPoDFgzN1mZWRvCgGKdWNC-GQLGtCPqA,35229
|
22
|
+
minecraft_datapack_language-15.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
minecraft_datapack_language-15.4.3.dist-info/entry_points.txt,sha256=c6vjBeCiyQflvPHBRyBk2nJCSfYt3Oc7Sc9V87ySi_U,108
|
24
|
+
minecraft_datapack_language-15.4.3.dist-info/top_level.txt,sha256=ADtFI476tbKLLxEAA-aJQAfg53MA3k_DOb0KTFiggfw,28
|
25
|
+
minecraft_datapack_language-15.4.3.dist-info/RECORD,,
|
{minecraft_datapack_language-15.4.1.dist-info → minecraft_datapack_language-15.4.3.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|