dfpyre 0.8.21__py3-none-any.whl → 0.9.0__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.
Potentially problematic release.
This version of dfpyre might be problematic. Click here for more details.
- dfpyre/action_literals.py +14 -14
- dfpyre/codeblock.py +202 -0
- dfpyre/data/actiondump_min.json +1 -1
- dfpyre/pyre.py +9 -188
- dfpyre/scriptgen.py +4 -4
- dfpyre/slice.py +200 -0
- {dfpyre-0.8.21.dist-info → dfpyre-0.9.0.dist-info}/METADATA +2 -2
- dfpyre-0.9.0.dist-info/RECORD +15 -0
- dfpyre-0.8.21.dist-info/RECORD +0 -13
- {dfpyre-0.8.21.dist-info → dfpyre-0.9.0.dist-info}/LICENSE +0 -0
- {dfpyre-0.8.21.dist-info → dfpyre-0.9.0.dist-info}/WHEEL +0 -0
dfpyre/pyre.py
CHANGED
|
@@ -5,16 +5,16 @@ By Amp
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
|
-
from difflib import get_close_matches
|
|
9
8
|
import datetime
|
|
10
9
|
import platform
|
|
11
|
-
from enum import Enum
|
|
12
10
|
from amulet_nbt import CompoundTag, StringTag, DoubleTag
|
|
13
11
|
from dfpyre.util import df_encode, df_decode, flatten
|
|
14
12
|
from dfpyre.items import *
|
|
15
|
-
from dfpyre.
|
|
13
|
+
from dfpyre.codeblock import CodeBlock, Target, TARGETS, DEFAULT_TARGET, CONDITIONAL_CODEBLOCKS, TEMPLATE_STARTERS
|
|
14
|
+
from dfpyre.actiondump import get_default_tags
|
|
16
15
|
from dfpyre.action_literals import *
|
|
17
16
|
from dfpyre.scriptgen import generate_script, GeneratorFlags
|
|
17
|
+
from dfpyre.slice import slice_template
|
|
18
18
|
|
|
19
19
|
__all__ = [
|
|
20
20
|
'Target', 'CodeBlock', 'DFTemplate',
|
|
@@ -23,197 +23,13 @@ __all__ = [
|
|
|
23
23
|
] + VAR_ITEM_TYPES
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
VARIABLE_TYPES = {'txt', 'comp', 'num', 'item', 'loc', 'var', 'snd', 'part', 'pot', 'g_val', 'vec', 'pn_el', 'bl_tag'}
|
|
27
|
-
TEMPLATE_STARTERS = {'event', 'entity_event', 'func', 'process'}
|
|
28
26
|
DYNAMIC_CODEBLOCKS = {'func', 'process', 'call_func', 'start_process'}
|
|
29
|
-
CONDITIONAL_CODEBLOCKS = {'if_player', 'if_var', 'if_game', 'if_entity'}
|
|
30
|
-
|
|
31
|
-
TARGETS = ['Selection', 'Default', 'Killer', 'Damager', 'Shooter', 'Victim', 'AllPlayers', 'Projectile', 'AllEntities', 'AllMobs', 'LastEntity']
|
|
32
|
-
TARGET_CODEBLOCKS = {'player_action', 'entity_action', 'if_player', 'if_entity'}
|
|
33
27
|
|
|
34
28
|
CODECLIENT_URL = 'ws://localhost:31375'
|
|
35
29
|
|
|
36
30
|
DATE_FORMAT_STR = "%b %#d, %Y" if platform.system() == "Windows" else "%b %-d, %Y"
|
|
37
31
|
|
|
38
32
|
|
|
39
|
-
class Target(Enum):
|
|
40
|
-
SELECTION = 0
|
|
41
|
-
DEFAULT = 1
|
|
42
|
-
KILLER = 2
|
|
43
|
-
DAMAGER = 3
|
|
44
|
-
SHOOTER = 4
|
|
45
|
-
VICTIM = 5
|
|
46
|
-
ALL_PLAYERS = 6
|
|
47
|
-
PROJECTILE = 7
|
|
48
|
-
ALL_ENTITIES = 8
|
|
49
|
-
ALL_MOBS = 9
|
|
50
|
-
LAST_ENTITY = 10
|
|
51
|
-
|
|
52
|
-
def get_string_value(self):
|
|
53
|
-
return TARGETS[self.value]
|
|
54
|
-
|
|
55
|
-
DEFAULT_TARGET = Target.SELECTION
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def _convert_args(args):
|
|
59
|
-
return tuple(map(convert_literals, args))
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class CodeBlock:
|
|
63
|
-
def __init__(self, codeblock_type: str, action_name: str, args: tuple=(), target: Target=DEFAULT_TARGET, data: dict={}, tags: dict[str, str]={}):
|
|
64
|
-
self.type = codeblock_type
|
|
65
|
-
self.action_name = action_name
|
|
66
|
-
self.args = args
|
|
67
|
-
self.target = target
|
|
68
|
-
self.data = data
|
|
69
|
-
self.tags = tags
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@classmethod
|
|
73
|
-
def new_action(cls, codeblock_type: str, action_name: str, args: tuple, tags: dict[str, str], target: Target=DEFAULT_TARGET) -> "CodeBlock":
|
|
74
|
-
args = _convert_args(args)
|
|
75
|
-
return cls(codeblock_type, action_name, args=args, data={'id': 'block', 'block': codeblock_type, 'action': action_name}, tags=tags, target=target)
|
|
76
|
-
|
|
77
|
-
@classmethod
|
|
78
|
-
def new_data(cls, codeblock_type: str, data_value: str, args: tuple, tags: dict[str, str]) -> "CodeBlock":
|
|
79
|
-
args = _convert_args(args)
|
|
80
|
-
return cls(codeblock_type, 'dynamic', args=args, data={'id': 'block', 'block': codeblock_type, 'data': data_value}, tags=tags)
|
|
81
|
-
|
|
82
|
-
@classmethod
|
|
83
|
-
def new_conditional(cls, codeblock_type: str, action_name: str, args: tuple, tags: dict[str, str], inverted: bool, target: Target=DEFAULT_TARGET) -> "CodeBlock":
|
|
84
|
-
args = _convert_args(args)
|
|
85
|
-
data = {'id': 'block', 'block': codeblock_type, 'action': action_name}
|
|
86
|
-
if inverted:
|
|
87
|
-
data['attribute'] = 'NOT'
|
|
88
|
-
return cls(codeblock_type, action_name, args=args, data=data, tags=tags, target=target)
|
|
89
|
-
|
|
90
|
-
@classmethod
|
|
91
|
-
def new_subaction_block(cls, codeblock_type: str, action_name: str, args: tuple, tags: dict[str, str], sub_action: str|None, inverted: bool) -> "CodeBlock":
|
|
92
|
-
args = _convert_args(args)
|
|
93
|
-
data = {'id': 'block', 'block': codeblock_type, 'action': action_name}
|
|
94
|
-
if sub_action is not None:
|
|
95
|
-
data['subAction'] = sub_action
|
|
96
|
-
if inverted:
|
|
97
|
-
data['attribute'] = 'NOT'
|
|
98
|
-
return cls(codeblock_type, action_name, args=args, data=data, tags=tags)
|
|
99
|
-
|
|
100
|
-
@classmethod
|
|
101
|
-
def new_else(cls) -> "CodeBlock":
|
|
102
|
-
return cls('else', 'else', data={'id': 'block', 'block': 'else'})
|
|
103
|
-
|
|
104
|
-
@classmethod
|
|
105
|
-
def new_bracket(cls, direction: Literal['open', 'close'], bracket_type: Literal['norm', 'repeat']) -> "CodeBlock":
|
|
106
|
-
return cls('bracket', 'bracket', data={'id': 'bracket', 'direct': direction, 'type': bracket_type})
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def __repr__(self) -> str:
|
|
110
|
-
if self.action_name == 'dynamic':
|
|
111
|
-
return f'CodeBlock({self.data["block"]}, {self.data["data"]})'
|
|
112
|
-
if self.action_name == 'else':
|
|
113
|
-
return 'CodeBlock(else)'
|
|
114
|
-
if 'block' in self.data:
|
|
115
|
-
return f'CodeBlock({self.data["block"]}, {self.action_name})'
|
|
116
|
-
return f'CodeBlock(bracket, {self.data["type"]}, {self.data["direct"]})'
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def build(self) -> dict:
|
|
120
|
-
"""
|
|
121
|
-
Builds a properly formatted block from a CodeBlock object.
|
|
122
|
-
"""
|
|
123
|
-
built_block = self.data.copy()
|
|
124
|
-
|
|
125
|
-
# add target if necessary ('Selection' is the default when 'target' is blank)
|
|
126
|
-
if self.type in TARGET_CODEBLOCKS and self.target != DEFAULT_TARGET:
|
|
127
|
-
built_block['target'] = self.target.get_string_value()
|
|
128
|
-
|
|
129
|
-
# add items into args
|
|
130
|
-
final_args = [arg.format(slot) for slot, arg in enumerate(self.args) if arg.type in VARIABLE_TYPES]
|
|
131
|
-
already_applied_tags: dict[str, dict] = {a['item']['data']['tag']: a for a in final_args if a['item']['id'] == 'bl_tag'}
|
|
132
|
-
|
|
133
|
-
# check for unrecognized name, add tags
|
|
134
|
-
if self.type not in {'bracket', 'else'}:
|
|
135
|
-
if self.action_name not in CODEBLOCK_DATA[self.type]:
|
|
136
|
-
_warn_unrecognized_name(self.type, self.action_name)
|
|
137
|
-
|
|
138
|
-
tags = _get_codeblock_tags(self.type, self.action_name, self.tags)
|
|
139
|
-
for i, tag_data in enumerate(tags):
|
|
140
|
-
already_applied_tag_data = already_applied_tags.get(tag_data['item']['data']['tag'])
|
|
141
|
-
if already_applied_tag_data is not None:
|
|
142
|
-
tags[i] = already_applied_tag_data
|
|
143
|
-
|
|
144
|
-
if len(final_args) + len(tags) > 27:
|
|
145
|
-
final_args = final_args[:(27-len(tags))] # trim list if over 27 elements
|
|
146
|
-
final_args.extend(tags) # add tags to end
|
|
147
|
-
|
|
148
|
-
built_block['args'] = {'items': final_args}
|
|
149
|
-
return built_block
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def _warn_unrecognized_name(codeblock_type: str, codeblock_name: str):
|
|
153
|
-
close = get_close_matches(codeblock_name, CODEBLOCK_DATA[codeblock_type].keys())
|
|
154
|
-
if close:
|
|
155
|
-
warn(f'Code block name "{codeblock_name}" not recognized. Did you mean "{close[0]}"?')
|
|
156
|
-
else:
|
|
157
|
-
warn(f'Code block name "{codeblock_name}" not recognized. Try spell checking or retyping without spaces.')
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def _check_applied_tags(tags: list[dict], applied_tags: dict[str, str], codeblock_name: str) -> dict[str, str]:
|
|
161
|
-
if len(applied_tags) > 0 and len(tags) == 0:
|
|
162
|
-
warn(f'Action "{codeblock_name}" does not have any tags, but still received {len(applied_tags)}.')
|
|
163
|
-
return {}
|
|
164
|
-
|
|
165
|
-
valid_tags = {}
|
|
166
|
-
tags_formatted = {t['name']: t for t in tags}
|
|
167
|
-
for name, option in applied_tags.items():
|
|
168
|
-
if name not in tags_formatted:
|
|
169
|
-
tag_names_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted.keys()))
|
|
170
|
-
warn(f'Tag "{name}" does not exist for action "{codeblock_name}". Available tags:\n{tag_names_joined}')
|
|
171
|
-
elif option not in tags_formatted[name]['options']:
|
|
172
|
-
options_joined = '\n'.join(map(lambda s: ' - '+s, tags_formatted[name]['options']))
|
|
173
|
-
warn(f'Tag "{name}" does not have the option "{option}". Available tag options:\n{options_joined}')
|
|
174
|
-
else:
|
|
175
|
-
valid_tags[name] = option
|
|
176
|
-
return valid_tags
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
def _reformat_codeblock_tags(tags: list[dict], codeblock_type: str, codeblock_action: str, applied_tags: dict[str, str]) -> list[dict]:
|
|
180
|
-
"""
|
|
181
|
-
Turns tag objects into DiamondFire formatted tag items.
|
|
182
|
-
"""
|
|
183
|
-
|
|
184
|
-
def format_tag(option: str, name: str):
|
|
185
|
-
return {
|
|
186
|
-
'item': {
|
|
187
|
-
'id': 'bl_tag',
|
|
188
|
-
'data': {'option': option, 'tag': name, 'action': codeblock_action, 'block': codeblock_type}
|
|
189
|
-
},
|
|
190
|
-
'slot': tag_item['slot']
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
valid_applied_tags = _check_applied_tags(tags, applied_tags, codeblock_action)
|
|
194
|
-
reformatted_tags = []
|
|
195
|
-
for tag_item in tags:
|
|
196
|
-
tag_name = tag_item['name']
|
|
197
|
-
tag_option = tag_item['default']
|
|
198
|
-
if tag_name in valid_applied_tags:
|
|
199
|
-
tag_option = valid_applied_tags[tag_name]
|
|
200
|
-
|
|
201
|
-
new_tag_item = format_tag(tag_option, tag_name)
|
|
202
|
-
reformatted_tags.append(new_tag_item)
|
|
203
|
-
return reformatted_tags
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
def _get_codeblock_tags(codeblock_type: str, codeblock_name: str, applied_tags: dict[str, str]) -> list[dict]:
|
|
207
|
-
"""
|
|
208
|
-
Get tags for the specified codeblock type and name.
|
|
209
|
-
"""
|
|
210
|
-
action_data = CODEBLOCK_DATA[codeblock_type][codeblock_name]
|
|
211
|
-
if 'deprecatedNote' in action_data:
|
|
212
|
-
warn(f'Action "{codeblock_name}" is deprecated: {action_data["deprecatedNote"]}')
|
|
213
|
-
tags = action_data['tags']
|
|
214
|
-
return _reformat_codeblock_tags(tags, codeblock_type, codeblock_name, applied_tags)
|
|
215
|
-
|
|
216
|
-
|
|
217
33
|
class DFTemplate:
|
|
218
34
|
"""
|
|
219
35
|
Represents a DiamondFire code template.
|
|
@@ -371,7 +187,12 @@ class DFTemplate:
|
|
|
371
187
|
:param bool build_and_send: If True, `.build_and_send()` will be added to the end of the generated template.
|
|
372
188
|
"""
|
|
373
189
|
flags = GeneratorFlags(indent_size, literal_shorthand, var_shorthand, preserve_slots, assign_variable, include_import, build_and_send)
|
|
374
|
-
return generate_script(self, flags)
|
|
190
|
+
return generate_script(self.codeblocks, flags)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def slice(self, target_length: int) -> list['DFTemplate']:
|
|
194
|
+
sliced_templates = slice_template(self.codeblocks, target_length, self._get_template_name())
|
|
195
|
+
return [DFTemplate(t, self.author) for t in sliced_templates]
|
|
375
196
|
|
|
376
197
|
|
|
377
198
|
def _assemble_template(starting_block: CodeBlock, codeblocks: list[CodeBlock], author: str|None) -> DFTemplate:
|
dfpyre/scriptgen.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import dataclasses
|
|
2
|
-
import re
|
|
3
2
|
from dfpyre.util import is_number
|
|
4
3
|
from dfpyre.items import *
|
|
5
4
|
from dfpyre.actiondump import get_default_tags
|
|
5
|
+
from dfpyre.codeblock import CodeBlock
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
IMPORT_STATEMENT = 'from dfpyre import *'
|
|
@@ -155,7 +155,7 @@ def add_script_line(flags: GeneratorFlags, script_lines: list[str], indent_level
|
|
|
155
155
|
script_lines.append(added_line)
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def generate_script(
|
|
158
|
+
def generate_script(codeblocks: list[CodeBlock], flags: GeneratorFlags) -> str:
|
|
159
159
|
indent_level = 0
|
|
160
160
|
script_lines = []
|
|
161
161
|
variable_assigned = False
|
|
@@ -168,7 +168,7 @@ def generate_script(template, flags: GeneratorFlags) -> str:
|
|
|
168
168
|
script_lines[-1] = script_lines[-1][:-1]
|
|
169
169
|
|
|
170
170
|
def get_var_assignment_snippet() -> str:
|
|
171
|
-
first_block_data =
|
|
171
|
+
first_block_data = codeblocks[0].data
|
|
172
172
|
if 'data' in first_block_data:
|
|
173
173
|
name = first_block_data['data']
|
|
174
174
|
var_name = name if name else 'unnamed_template'
|
|
@@ -177,7 +177,7 @@ def generate_script(template, flags: GeneratorFlags) -> str:
|
|
|
177
177
|
return f'{string_to_python_name(var_name)} = '
|
|
178
178
|
|
|
179
179
|
|
|
180
|
-
for codeblock in
|
|
180
|
+
for codeblock in codeblocks:
|
|
181
181
|
# Handle closing brackets
|
|
182
182
|
if codeblock.type == 'bracket':
|
|
183
183
|
if codeblock.data['direct'] == 'close':
|
dfpyre/slice.py
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
from typing import Iterator
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from collections import deque
|
|
4
|
+
from dfpyre.codeblock import CodeBlock, CONDITIONAL_CODEBLOCKS, TEMPLATE_STARTERS
|
|
5
|
+
from dfpyre.items import Variable, Parameter, ParameterType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
BRACKET_CODEBLOCKS = CONDITIONAL_CODEBLOCKS
|
|
9
|
+
BRACKET_CODEBLOCKS.add('repeat')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class TemplateChunk:
|
|
14
|
+
length: int
|
|
15
|
+
start_index: int
|
|
16
|
+
end_index: int
|
|
17
|
+
contents1: list['TemplateChunk'] | None # Inside brackets
|
|
18
|
+
contents2: list['TemplateChunk'] | None # Inside `else` brackets
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_referenced_line_vars(codeblocks: list[CodeBlock]) -> set[str]:
|
|
22
|
+
referenced_vars = set()
|
|
23
|
+
for codeblock in codeblocks:
|
|
24
|
+
for argument in codeblock.args:
|
|
25
|
+
if isinstance(argument, Variable) and argument.scope == 'line':
|
|
26
|
+
referenced_vars.add(argument.name)
|
|
27
|
+
return referenced_vars
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def find_closing_bracket(codeblocks: list[CodeBlock], start_index: int) -> int:
|
|
31
|
+
"""
|
|
32
|
+
Returns the index of the cooresponding closing bracket assuming
|
|
33
|
+
that `start_index` is the index of the first codeblock inside the brackets.
|
|
34
|
+
"""
|
|
35
|
+
nested_level = 1
|
|
36
|
+
for i in range(start_index, len(codeblocks)):
|
|
37
|
+
codeblock = codeblocks[i]
|
|
38
|
+
if codeblock.type != 'bracket':
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
direction = codeblock.data['direct']
|
|
42
|
+
if direction == 'open':
|
|
43
|
+
nested_level += 1
|
|
44
|
+
else: # Closed
|
|
45
|
+
nested_level -= 1
|
|
46
|
+
|
|
47
|
+
if nested_level == 0:
|
|
48
|
+
return i
|
|
49
|
+
|
|
50
|
+
return -1
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_bracket_ranges(codeblocks: list[CodeBlock], start_index: int):
|
|
54
|
+
bracket_range_end = find_closing_bracket(codeblocks, start_index)
|
|
55
|
+
|
|
56
|
+
if len(codeblocks) >= bracket_range_end and codeblocks[bracket_range_end+1].type == 'else':
|
|
57
|
+
else_range_start = bracket_range_end+3 # Add 3 to move inside `else` brackets
|
|
58
|
+
else_range_end = find_closing_bracket(codeblocks, else_range_start)
|
|
59
|
+
else_range = (else_range_start, else_range_end)
|
|
60
|
+
else:
|
|
61
|
+
else_range = None
|
|
62
|
+
|
|
63
|
+
bracket_range = (start_index, bracket_range_end)
|
|
64
|
+
return (bracket_range, else_range)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def get_template_length(codeblocks: list[CodeBlock]) -> int:
|
|
68
|
+
return sum(b.get_length() for b in codeblocks)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_template_chunks(codeblocks: list[CodeBlock], start_index: int, end_index: int) -> list[TemplateChunk]:
|
|
72
|
+
chunks: list[TemplateChunk] = []
|
|
73
|
+
|
|
74
|
+
index = start_index
|
|
75
|
+
while index < end_index:
|
|
76
|
+
codeblock = codeblocks[index]
|
|
77
|
+
if codeblock.type == 'bracket' or codeblock.type in TEMPLATE_STARTERS:
|
|
78
|
+
index += 1
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
if codeblock.type in BRACKET_CODEBLOCKS:
|
|
82
|
+
bracket_range, else_range = get_bracket_ranges(codeblocks, index+2)
|
|
83
|
+
inside_bracket = codeblocks[bracket_range[0]:bracket_range[1]]
|
|
84
|
+
inside_bracket_length = get_template_length(inside_bracket)
|
|
85
|
+
chunk_contents1 = get_template_chunks(codeblocks, bracket_range[0], bracket_range[1])
|
|
86
|
+
if else_range is None:
|
|
87
|
+
chunk_length = inside_bracket_length + 4
|
|
88
|
+
chunk_end_index = bracket_range[1] + 1
|
|
89
|
+
chunk_contents2 = None
|
|
90
|
+
else:
|
|
91
|
+
inside_else = codeblocks[else_range[0]:else_range[1]]
|
|
92
|
+
inside_else_length = get_template_length(inside_else)
|
|
93
|
+
chunk_length = inside_bracket_length + inside_else_length + 8
|
|
94
|
+
chunk_end_index = else_range[1] + 1
|
|
95
|
+
chunk_contents2 = get_template_chunks(codeblocks, else_range[0], else_range[1])
|
|
96
|
+
|
|
97
|
+
chunk = TemplateChunk(length=chunk_length, start_index=index, end_index=chunk_end_index, contents1=chunk_contents1, contents2=chunk_contents2)
|
|
98
|
+
chunks.append(chunk)
|
|
99
|
+
index = chunk_end_index-1
|
|
100
|
+
|
|
101
|
+
else:
|
|
102
|
+
chunk = TemplateChunk(length=2, start_index=index, end_index=index+1, contents1=None, contents2=None)
|
|
103
|
+
chunks.append(chunk)
|
|
104
|
+
|
|
105
|
+
index += 1
|
|
106
|
+
|
|
107
|
+
return chunks
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def extract_one_template(codeblocks: list[CodeBlock], target_length: int, extracted_template_name: str) -> tuple[list[CodeBlock], list[CodeBlock]]:
|
|
111
|
+
chunks = get_template_chunks(codeblocks, 0, len(codeblocks))
|
|
112
|
+
current_slice_length = 2
|
|
113
|
+
current_slice_start = -1
|
|
114
|
+
current_slice_end = -1
|
|
115
|
+
|
|
116
|
+
slices: dict[tuple[int, int], int] = {}
|
|
117
|
+
|
|
118
|
+
chunks_to_iterate: deque[list[TemplateChunk]] = deque()
|
|
119
|
+
chunks_to_iterate.append(chunks)
|
|
120
|
+
|
|
121
|
+
def save_current_slice():
|
|
122
|
+
nonlocal current_slice_start, current_slice_end, current_slice_length, slices
|
|
123
|
+
current_slice_range = (current_slice_start, current_slice_end)
|
|
124
|
+
slices[current_slice_range] = current_slice_length
|
|
125
|
+
current_slice_length = 2
|
|
126
|
+
current_slice_start = -1
|
|
127
|
+
current_slice_end = -1
|
|
128
|
+
|
|
129
|
+
while chunks_to_iterate:
|
|
130
|
+
current_chunks = chunks_to_iterate.pop()
|
|
131
|
+
for chunk in reversed(current_chunks):
|
|
132
|
+
if chunk.contents1:
|
|
133
|
+
chunks_to_iterate.append(chunk.contents1)
|
|
134
|
+
if chunk.contents2:
|
|
135
|
+
chunks_to_iterate.append(chunk.contents2)
|
|
136
|
+
|
|
137
|
+
if current_slice_start == -1:
|
|
138
|
+
current_slice_start = chunk.start_index
|
|
139
|
+
if current_slice_end == -1:
|
|
140
|
+
current_slice_end = chunk.end_index
|
|
141
|
+
|
|
142
|
+
# Check if chunk is too long
|
|
143
|
+
if chunk.length > target_length - 2:
|
|
144
|
+
save_current_slice()
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
new_slice_length = current_slice_length + chunk.length
|
|
148
|
+
if new_slice_length <= target_length:
|
|
149
|
+
current_slice_length = new_slice_length
|
|
150
|
+
current_slice_start = chunk.start_index
|
|
151
|
+
else:
|
|
152
|
+
current_slice_range = (current_slice_start, current_slice_end)
|
|
153
|
+
slices[current_slice_range] = current_slice_length
|
|
154
|
+
current_slice_length = chunk.length + 2
|
|
155
|
+
current_slice_start = chunk.start_index
|
|
156
|
+
current_slice_end = chunk.end_index
|
|
157
|
+
|
|
158
|
+
save_current_slice()
|
|
159
|
+
|
|
160
|
+
sliced_range = max(slices.items(), key=lambda kv: kv[1])[0] # Extract the longest slice
|
|
161
|
+
extracted_codeblocks = codeblocks[sliced_range[0]:sliced_range[1]]
|
|
162
|
+
del codeblocks[sliced_range[0]:sliced_range[1]]
|
|
163
|
+
|
|
164
|
+
original_line_vars = get_referenced_line_vars(codeblocks)
|
|
165
|
+
extracted_line_vars = get_referenced_line_vars(extracted_codeblocks)
|
|
166
|
+
param_line_vars = set.intersection(original_line_vars, extracted_line_vars)
|
|
167
|
+
function_parameters = []
|
|
168
|
+
function_call_args = []
|
|
169
|
+
for line_var in param_line_vars:
|
|
170
|
+
function_parameters.append(Parameter(line_var, ParameterType.VAR))
|
|
171
|
+
function_call_args.append(Variable(line_var, 'line'))
|
|
172
|
+
|
|
173
|
+
function_codeblock = CodeBlock.new_data('func', extracted_template_name, tuple(function_parameters), tags={'Is Hidden': 'True'})
|
|
174
|
+
extracted_codeblocks.insert(0, function_codeblock)
|
|
175
|
+
|
|
176
|
+
call_function_codeblock = CodeBlock.new_data('call_func', extracted_template_name, tuple(function_call_args), {})
|
|
177
|
+
codeblocks.insert(sliced_range[0], call_function_codeblock)
|
|
178
|
+
|
|
179
|
+
return codeblocks, extracted_codeblocks
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def slice_template(codeblocks: list[CodeBlock], target_length: int, template_name: str) -> list[list[CodeBlock]]:
|
|
183
|
+
template_length = get_template_length(codeblocks)
|
|
184
|
+
if template_length < target_length:
|
|
185
|
+
return [codeblocks]
|
|
186
|
+
|
|
187
|
+
codeblocks = codeblocks.copy()
|
|
188
|
+
|
|
189
|
+
sliced_templates: list[list[CodeBlock]] = []
|
|
190
|
+
|
|
191
|
+
# Extract single templates until the original template meets the target length
|
|
192
|
+
template_number = 1
|
|
193
|
+
while get_template_length(codeblocks) > target_length:
|
|
194
|
+
extracted_template_name = template_name + '_' + str(template_number)
|
|
195
|
+
codeblocks, extracted_codeblocks = extract_one_template(codeblocks, target_length, extracted_template_name)
|
|
196
|
+
sliced_templates.append(extracted_codeblocks)
|
|
197
|
+
template_number += 1
|
|
198
|
+
|
|
199
|
+
sliced_templates.insert(0, codeblocks)
|
|
200
|
+
return sliced_templates
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dfpyre
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: A package for creating and modifying code templates for the DiamondFire Minecraft server.
|
|
5
5
|
Home-page: https://github.com/Amp63/pyre
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Requires-Dist: mcitemlib (>=0.4.
|
|
15
|
+
Requires-Dist: mcitemlib (>=0.4.5,<0.5.0)
|
|
16
16
|
Project-URL: Repository, https://github.com/Amp63/pyre
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
dfpyre/__init__.py,sha256=apPsSxJ1Tztfl71MoORoSmDfX7LyKLYlLwOGeLQUitw,25
|
|
2
|
+
dfpyre/action_literals.py,sha256=0aYS5v8pj3tyQVoiW_ueKBDQ0nY5VduPp4HeW_kpFio,55600
|
|
3
|
+
dfpyre/actiondump.py,sha256=l6_h811AnKkeI6WrrRlS-vDOgenh6XU9qvEuPf2DpSs,3720
|
|
4
|
+
dfpyre/codeblock.py,sha256=NwUapwVP1qrnFaN4WlKov4MTJW9_l2ujNhY1P0pzboU,8577
|
|
5
|
+
dfpyre/data/actiondump_min.json,sha256=zdUYVuua6a93wxFewHWXBHYRuuvwDZK6c3J2558BAIg,2642808
|
|
6
|
+
dfpyre/items.py,sha256=zdT_b7D38ofFVEYtjHb6x6IU0XMJJCJPuQUXW5MNsm0,17681
|
|
7
|
+
dfpyre/pyre.py,sha256=WQhIXmrd7A1APcRobjmT5eBGHNf7V12qlcPvI1QM7R8,19331
|
|
8
|
+
dfpyre/scriptgen.py,sha256=UNUbRVAUlO0gCGoo17Qpiaa5XOXTVZIEHGN2ckEdXaM,10231
|
|
9
|
+
dfpyre/slice.py,sha256=azKC5H7sxXvKSa1uFHQNoS2MGLqgl-_0ftD8F9fRn_Y,7980
|
|
10
|
+
dfpyre/style.py,sha256=mLW1CFvvi8_9fk8JaH10I5S4WI0YBdQIXHtI3G_4sR8,980
|
|
11
|
+
dfpyre/util.py,sha256=_ndjGyn_pvMfEBmUjt0ARjYvGZfZz7Av-KSYPmvx0N0,934
|
|
12
|
+
dfpyre-0.9.0.dist-info/LICENSE,sha256=_vuDskB0ja2c-Fgm7Gt8Q8cO9NsLNpZAVyvmZwX7E6o,1060
|
|
13
|
+
dfpyre-0.9.0.dist-info/METADATA,sha256=acAZkSAbA6FfFckEiOdA6eQy1hljGo62p_T1V0ZBwjo,11948
|
|
14
|
+
dfpyre-0.9.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
15
|
+
dfpyre-0.9.0.dist-info/RECORD,,
|
dfpyre-0.8.21.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
dfpyre/__init__.py,sha256=apPsSxJ1Tztfl71MoORoSmDfX7LyKLYlLwOGeLQUitw,25
|
|
2
|
-
dfpyre/action_literals.py,sha256=llWj3woVH0PRKEFN4oeMnQqcnHC9ShaA0bKgZDtHaZ0,52077
|
|
3
|
-
dfpyre/actiondump.py,sha256=l6_h811AnKkeI6WrrRlS-vDOgenh6XU9qvEuPf2DpSs,3720
|
|
4
|
-
dfpyre/data/actiondump_min.json,sha256=ZF_Aa6uB1khzsINAEAljCOIMmfh_5ihmBygZSP_bHrs,2482346
|
|
5
|
-
dfpyre/items.py,sha256=zdT_b7D38ofFVEYtjHb6x6IU0XMJJCJPuQUXW5MNsm0,17681
|
|
6
|
-
dfpyre/pyre.py,sha256=CO1Y5PBpAGZiKrEGOc1aGpDg3-0hxHpzizD1g8OSZ80,27032
|
|
7
|
-
dfpyre/scriptgen.py,sha256=Cplx-ncfD9P7FQCut-M-vcZ0qqFk8xvYTrGE2mCop48,10201
|
|
8
|
-
dfpyre/style.py,sha256=mLW1CFvvi8_9fk8JaH10I5S4WI0YBdQIXHtI3G_4sR8,980
|
|
9
|
-
dfpyre/util.py,sha256=_ndjGyn_pvMfEBmUjt0ARjYvGZfZz7Av-KSYPmvx0N0,934
|
|
10
|
-
dfpyre-0.8.21.dist-info/LICENSE,sha256=_vuDskB0ja2c-Fgm7Gt8Q8cO9NsLNpZAVyvmZwX7E6o,1060
|
|
11
|
-
dfpyre-0.8.21.dist-info/METADATA,sha256=kCWwoYfI5E_g5Eo-cjjmCdlh5V9oPKC-8siL5GtApVk,11949
|
|
12
|
-
dfpyre-0.8.21.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
13
|
-
dfpyre-0.8.21.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|