Skip to content

Commit 4edb6c0

Browse files
authored
feat: basic review of sa.editor (#507)
solves #410
1 parent 8c2c2c7 commit 4edb6c0

File tree

17 files changed

+103
-191
lines changed

17 files changed

+103
-191
lines changed

scratchattach/editor/asset.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
@dataclass(init=True, repr=True)
1212
class AssetFile:
1313
"""
14-
Represents the file information for an asset
14+
Represents the file information for an asset (not the asset metdata)
1515
- stores the filename, data, and md5 hash
1616
"""
1717
filename: str
1818
_data: Optional[bytes] = field(repr=False, default=None)
1919
_md5: str = field(repr=False, default_factory=str)
2020

2121
@property
22-
def data(self):
22+
def data(self) -> bytes:
2323
"""
2424
Return the contents of the asset file, as bytes
2525
"""
@@ -35,9 +35,9 @@ def data(self):
3535
return self._data
3636

3737
@property
38-
def md5(self):
38+
def md5(self) -> str:
3939
"""
40-
Compute/retrieve the md5 hash value of the asset file data
40+
Compute/retrieve the md5 hex-digest of the asset file data
4141
"""
4242
if self._md5 is None:
4343
self._md5 = md5(self.data).hexdigest()
@@ -51,7 +51,7 @@ def __init__(self,
5151
file_name: str = "b7853f557e4426412e64bb3da6531a99.svg",
5252
_sprite: commons.SpriteInput = build_defaulting.SPRITE_DEFAULT):
5353
"""
54-
Represents a generic asset. Can be a sound or an image.
54+
Represents a generic asset, with metadata. Can be a sound or a costume.
5555
https://en.scratch-wiki.info/wiki/Scratch_File_Format#Assets
5656
"""
5757
try:
@@ -72,14 +72,14 @@ def __repr__(self):
7272
@property
7373
def folder(self):
7474
"""
75-
Get the folder name of this asset, based on the asset name. Uses the turbowarp syntax
75+
Get the folder name of this asset, based on the asset name. Uses the TurboWarp syntax
7676
"""
7777
return commons.get_folder_name(self.name)
7878

7979
@property
8080
def name_nfldr(self):
8181
"""
82-
Get the asset name after removing the folder name
82+
Get the asset name after removing the folder name. Uses the TurboWarp syntax
8383
"""
8484
return commons.get_name_nofldr(self.name)
8585

@@ -96,14 +96,16 @@ def md5ext(self):
9696
"""
9797
Get the exact file name, as it would be within an sb3 file
9898
equivalent to the md5ext value using in scratch project JSON
99+
100+
(alias for file_name)
99101
"""
100102
return self.file_name
101103

102104
@property
103105
def parent(self):
104106
"""
105-
Return the project that this asset is attached to. If there is no attached project,
106-
try returning the attached sprite
107+
Return the project (body) that this asset is attached to. If there is no attached project,
108+
try returning the attached sprite instead.
107109
"""
108110
if self.project is None:
109111
return self.sprite

scratchattach/editor/backpack_json.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
"""
2-
Module to deal with the backpack's weird JSON format, by overriding with new load methods
2+
Module to deal with the backpack's weird JSON format, by overriding editor classes with new load methods
33
"""
44
from __future__ import annotations
55

66
from . import block, prim, field, inputs, mutation, sprite
77

88

9-
def parse_prim_fields(_fields: dict[str]) -> tuple[str | None, str | None, str | None]:
9+
def parse_prim_fields(_fields: dict[str, dict[str, str]]) -> tuple[str | None, str | None, str | None]:
1010
"""
1111
Function for reading the fields in a backpack **primitive**
1212
"""
1313
for key, value in _fields.items():
14-
key: str
15-
value: dict[str, str]
1614
prim_value, prim_name, prim_id = (None,) * 3
1715
if key == "NUM":
1816
prim_value = value.get("value")
@@ -103,7 +101,7 @@ def load_script(_script_data: list[dict]) -> sprite.Sprite:
103101
"""
104102
Loads a script into a sprite from the backpack JSON format
105103
:param _script_data: Backpack script JSON data
106-
:return: a blockchain object containing the script
104+
:return: a Sprite object containing the script
107105
"""
108106
# Using a sprite since it simplifies things, e.g. local global loading
109107
_blockchain = sprite.Sprite()

scratchattach/editor/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def to_json(self):
5252

5353
def save_json(self, name: str = ''):
5454
"""
55-
Save a json file
55+
Save json to a file. Adds '.json' for you.
5656
"""
5757
data = self.to_json()
5858
with open(f"{self.__class__.__name__.lower()}{name}.json", "w") as f:

scratchattach/editor/block.py

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def link_subcomponents(self):
6868

6969
def add_input(self, name: str, _input: inputs.Input) -> Self:
7070
"""
71-
Add an input to the block.
72-
""" # not sure what else to say
71+
Attach an input object to the block.
72+
"""
7373
self.inputs[name] = _input
7474
for val in (_input.value, _input.obscurer):
7575
if isinstance(val, Block):
@@ -78,15 +78,15 @@ def add_input(self, name: str, _input: inputs.Input) -> Self:
7878

7979
def add_field(self, name: str, _field: field.Field) -> Self:
8080
"""
81-
Add a field to the block.
82-
""" # not sure what else to sa
81+
Attach a field object to the block.
82+
"""
8383
self.fields[name] = _field
8484
return self
8585

8686
def set_mutation(self, _mutation: mutation.Mutation) -> Self:
8787
"""
88-
Attach a mutation object and call mutation.link_arguments()
89-
""" # this comment explains *what* this does, not *why*
88+
Attach a mutation object and link it, also asking the mutation to link its own subcomponents.
89+
"""
9090
self.mutation = _mutation
9191
_mutation.block = self
9292
_mutation.link_arguments()
@@ -113,14 +113,15 @@ def check_toplevel(self):
113113
@property
114114
def target(self):
115115
"""
116-
Alias for sprite
117-
""" # remove this?
116+
Alias for .sprite
117+
"""
118+
# should this be deprecated?
118119
return self.sprite
119120

120121
@property
121122
def block_shape(self) -> blockshape.BlockShape:
122123
"""
123-
Search for the blockshape stored in blockshape.py
124+
Search for & return the associated blockshape stored in blockshape.py
124125
:return: The block's block shape (by opcode)
125126
"""
126127
_shape = blockshape.BlockShapes.find(self.opcode, "opcode")
@@ -133,15 +134,16 @@ def block_shape(self) -> blockshape.BlockShape:
133134
@property
134135
def can_next(self):
135136
"""
136-
:return: Whether the block *can* have a next block (basically checks if it's not a cap block, also considering the behaviour of control_stop)
137+
:return: Whether the block *can* have a next block (checks if it's not a cap block, but also considering the special behaviour of control_stop)
137138
"""
138139
_shape = self.block_shape
139140
if _shape.is_cap is not blockshape.MUTATION_DEPENDENT:
140141
return _shape.is_attachable
141142
else:
142143
if self.mutation is None:
143144
# If there's no mutation, let's just assume yes
144-
warnings.warn(f"{self} has no mutation! Assuming we can add block ;-;")
145+
# add filterwarnings?
146+
warnings.warn(f"{self} has no mutation! Assuming we can add blocks!")
145147
return True
146148

147149
return self.mutation.has_next
@@ -150,6 +152,7 @@ def can_next(self):
150152
def id(self) -> str:
151153
"""
152154
Work out the id of this block by searching through the sprite dictionary
155+
If one cannot be found, generate a new one and return that.
153156
"""
154157
if self._id:
155158
return self._id
@@ -191,8 +194,9 @@ def next_id(self):
191194
@property
192195
def relatives(self) -> list[Block]:
193196
"""
194-
:return: A list of blocks which are related to this block (e.g. parent, next, inputs)
197+
:return: A list of blocks which are related to this block (i.e. parent & next)
195198
"""
199+
# TODO: consider adding input blocks?
196200
_ret = []
197201

198202
def yield_block(_block: Block | None):
@@ -209,6 +213,7 @@ def children(self) -> list[Block | prim.Prim]:
209213
"""
210214
:return: A list of blocks that are inside of this block, **NOT INCLUDING THE ATTACHED BLOCK**
211215
"""
216+
# does this include procedure definitions' inner block?
212217
_children = []
213218
for _input in self.inputs.values():
214219
if isinstance(_input.value, Block) or isinstance(_input.value, prim.Prim):
@@ -223,7 +228,8 @@ def previous_chain(self):
223228
"""
224229
Recursive getter method to get all previous blocks in the blockchain (until hitting a top-level block)
225230
"""
226-
if self.parent is None: # todo: use is_top_level?
231+
# TODO: check if this hits the recursion limit
232+
if self.parent is None: # TODO: use is_top_level?
227233
return [self]
228234

229235
return [self] + self.parent.previous_chain
@@ -233,6 +239,7 @@ def attached_chain(self):
233239
"""
234240
Recursive getter method to get all next blocks in the blockchain (until hitting a bottom-levell block)
235241
"""
242+
# TODO: check if this hits the recursion limit
236243
if self.next is None:
237244
return [self]
238245

@@ -248,8 +255,7 @@ def complete_chain(self):
248255
@property
249256
def top_level_block(self):
250257
"""
251-
Get the first block in the block stack that this block is part of
252-
same as the old stack_parent property from sbedtior v1
258+
Get the first (top level) block in the block stack that this block is part of
253259
"""
254260
return self.previous_chain[-1]
255261

@@ -266,7 +272,7 @@ def stack_tree(self):
266272
Useful for showing a block stack in the console, using pprint
267273
:return: A tree-like nested list structure representing the stack of blocks, including inputs, starting at this block
268274
"""
269-
_tree = [self]
275+
_tree: list[Block | prim.Prim | list[Block]] = [self]
270276
for child in self.children:
271277
if isinstance(child, prim.Prim):
272278
_tree.append(child)
@@ -281,7 +287,7 @@ def stack_tree(self):
281287
@property
282288
def category(self):
283289
"""
284-
Works out what category of block this is using the opcode. Does not perform validation
290+
Works out what category of block this is as a string, using the opcode. Does not perform validation
285291
"""
286292
return self.opcode.split('_')[0]
287293

@@ -526,7 +532,7 @@ def attach_block(self, new: Block) -> Block:
526532
def duplicate_single_block(self) -> Block:
527533
return self.attach_block(self.dcopy())
528534

529-
def attach_chain(self, *chain: Iterable[Block]) -> Block:
535+
def attach_chain(self, *chain: Block) -> Block:
530536
attaching_block = self
531537
for _block in chain:
532538
attaching_block = attaching_block.attach_block(_block)
@@ -576,4 +582,3 @@ def delete_chain(self):
576582
"""
577583
for _block in self.attached_chain:
578584
_block.delete_single_block()
579-

scratchattach/editor/build_defaulting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from . import sprite, block, prim, comment
1010
from . import commons
1111

12-
12+
# TODO: should deque be used here?
1313
class _SetSprite(commons.Singleton):
1414
INSTANCE = 0
1515
def __repr__(self):

0 commit comments

Comments
 (0)