From 14861389c07a975eb3f95d4f1357b4a8e3f0469a Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Tue, 12 Aug 2025 00:53:28 +0530 Subject: [PATCH 01/11] Update README.md Signed-off-by: itsaethrr --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index dff5b6da..ef302c00 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ The library allows setting cloud variables, following users, updating your profile, and so much more! Additionally, it provides frameworks that simplify sending data through cloud variables. +This is a fork of scratchattach, so that I can contribute to the project. Thank you to [TimMcCool](https://scratch.mit.edu/users/TimMcCool/) for making this project :D +

From a33b11971583b1f484b38b0ae0ff9d30d13db961 Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 01:13:57 +0530 Subject: [PATCH 02/11] added construct_proccode Signed-off-by: itsaethrr --- scratchattach/editor/mutation.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scratchattach/editor/mutation.py b/scratchattach/editor/mutation.py index a416fb14..0d75783a 100644 --- a/scratchattach/editor/mutation.py +++ b/scratchattach/editor/mutation.py @@ -322,3 +322,30 @@ def link_arguments(self): for _argument in self.arguments: _argument.mutation = self _argument.link_using_mutation() + +def construct_proccode(components: list[ArgumentType | Argument | str]) -> str: + """ + if your reading ts: + ive only recently really gotten into python so sorry if this is bad lol. + + each comp may be: + - ArgumentType: itll be converted to .proc_str + - Argument: converted based on .proc_str + - str: added directly + + will return: + str: a (hopefully) vaid proc code string, eg "move %n steps" + """ + result = [] + for comp in components: + if isinstance(comp, ArgumentType): + result.append(comp.proc_str) + elif hasattr(item, 'typename'): + result.append(f"[{item.typename}]") + elif hasattr(item, 'name') and hasattr(item, 'type'): + result.append(f"[{item.type} {item.name}]") + else: + raise TypeError(f"Unsupported component type: {type(comp)}") + + return " ".join(result) + From d389aae79b623804d6e12f6693df4f422cb628ec Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 01:14:21 +0530 Subject: [PATCH 03/11] Update __init__.py Signed-off-by: itsaethrr --- scratchattach/editor/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scratchattach/editor/__init__.py b/scratchattach/editor/__init__.py index 0e3a2452..10c1f851 100644 --- a/scratchattach/editor/__init__.py +++ b/scratchattach/editor/__init__.py @@ -17,5 +17,7 @@ from .vlb import Variable, List, Broadcast from .comment import Comment from .monitor import Monitor +from .mutation import construct_proccode +from . import mutation from .build_defaulting import add_chain, add_comment, add_block From 95241e7704fa44a1ca72b4fbddc6520452c5a52a Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 02:25:18 +0530 Subject: [PATCH 04/11] added build_proccode Signed-off-by: itsaethrr --- scratchattach/editor/mutation.py | 61 ++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/scratchattach/editor/mutation.py b/scratchattach/editor/mutation.py index 0d75783a..cdcf9fb2 100644 --- a/scratchattach/editor/mutation.py +++ b/scratchattach/editor/mutation.py @@ -142,6 +142,41 @@ def parse_proc_code(_proc_code: str) -> list[str, ArgumentType] | None: return tokens +def construct_proccode(components): + + """ + if your reading ts: + sorry if the code is bad or doesnt work. ive only recently gotten into python + if it doesnt work telling me whats wrong/helping me out would really help :p + + anyway the components may include: + ArgumentType enums + Argument instances + plain text stirngs + + should output smth like: + move %n steps. + say %s for %n seconds. + + """ + + + result = [] + + for comp in components: + if isinstance(comp, ArgumentType): + result.append(comp.proc_str) + + elif hasattr(comp, 'typename'): + result.append(f"[{comp.typename}]") + + elif hasattr(comp, 'name') and hasattr(comp, 'type'): + result.append(f"[{comp.type} {comp.name}]") + + else: + raise TypeError(f"Unsupported component type: {type(comp)}") + + return " ".join(result) class Mutation(base.BlockSubComponent): def __init__(self, _tag_name: str = "mutation", _children: Optional[list] = None, _proc_code: Optional[str] = None, @@ -323,29 +358,3 @@ def link_arguments(self): _argument.mutation = self _argument.link_using_mutation() -def construct_proccode(components: list[ArgumentType | Argument | str]) -> str: - """ - if your reading ts: - ive only recently really gotten into python so sorry if this is bad lol. - - each comp may be: - - ArgumentType: itll be converted to .proc_str - - Argument: converted based on .proc_str - - str: added directly - - will return: - str: a (hopefully) vaid proc code string, eg "move %n steps" - """ - result = [] - for comp in components: - if isinstance(comp, ArgumentType): - result.append(comp.proc_str) - elif hasattr(item, 'typename'): - result.append(f"[{item.typename}]") - elif hasattr(item, 'name') and hasattr(item, 'type'): - result.append(f"[{item.type} {item.name}]") - else: - raise TypeError(f"Unsupported component type: {type(comp)}") - - return " ".join(result) - From 4e7dde5d391c7ccfd0747d8ab33cb30875f1b06f Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 02:26:51 +0530 Subject: [PATCH 05/11] Update __init__.py Signed-off-by: itsaethrr --- scratchattach/editor/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scratchattach/editor/__init__.py b/scratchattach/editor/__init__.py index 10c1f851..8495920e 100644 --- a/scratchattach/editor/__init__.py +++ b/scratchattach/editor/__init__.py @@ -17,7 +17,7 @@ from .vlb import Variable, List, Broadcast from .comment import Comment from .monitor import Monitor -from .mutation import construct_proccode -from . import mutation + +from .editor.mutation import construct_proccode, ArgumentType from .build_defaulting import add_chain, add_comment, add_block From cf67a3b36b0e994e6e6ee352a408275fe12378d3 Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 02:29:35 +0530 Subject: [PATCH 06/11] addded build_proccode Signed-off-by: itsaethrr --- scratchattach/editor/mutation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scratchattach/editor/mutation.py b/scratchattach/editor/mutation.py index cdcf9fb2..9cbbe049 100644 --- a/scratchattach/editor/mutation.py +++ b/scratchattach/editor/mutation.py @@ -178,6 +178,7 @@ def construct_proccode(components): return " ".join(result) + class Mutation(base.BlockSubComponent): def __init__(self, _tag_name: str = "mutation", _children: Optional[list] = None, _proc_code: Optional[str] = None, _is_warp: Optional[bool] = None, _arguments: Optional[list[Argument]] = None, _has_next: Optional[bool] = None, From 112b5215214e8bb9c4926b56ecfc6199df8b232d Mon Sep 17 00:00:00 2001 From: itsaethrr Date: Sat, 16 Aug 2025 02:40:42 +0530 Subject: [PATCH 07/11] Update README.md Signed-off-by: itsaethrr --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ef302c00..7182b2d8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ The library allows setting cloud variables, following users, updating your profile, and so much more! Additionally, it provides frameworks that simplify sending data through cloud variables. -This is a fork of scratchattach, so that I can contribute to the project. Thank you to [TimMcCool](https://scratch.mit.edu/users/TimMcCool/) for making this project :D

From 9c25a078b10abe39d38c31d83c6f8ea6a588fbff Mon Sep 17 00:00:00 2001 From: faretek <107722825+FAReTek1@users.noreply.github.com> Date: Sat, 16 Aug 2025 08:48:10 +0000 Subject: [PATCH 08/11] revert readme change Signed-off-by: faretek <107722825+FAReTek1@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7182b2d8..dff5b6da 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ The library allows setting cloud variables, following users, updating your profile, and so much more! Additionally, it provides frameworks that simplify sending data through cloud variables. -

From cfc41b90163686e1af8d6c01aaafad86dc887205 Mon Sep 17 00:00:00 2001 From: faretek <107722825+FAReTek1@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:19:33 +0100 Subject: [PATCH 09/11] fix: construct_proccode - docstring - use isinstance() not hasattr() - add support for ArgumentType instance - caching and defaulting for Argument._type and Argument.mutation --- scratchattach/editor/__init__.py | 4 +- scratchattach/editor/build_defaulting.py | 2 +- scratchattach/editor/mutation.py | 77 +++++++++++++----------- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/scratchattach/editor/__init__.py b/scratchattach/editor/__init__.py index 8495920e..0c8ed5e8 100644 --- a/scratchattach/editor/__init__.py +++ b/scratchattach/editor/__init__.py @@ -5,7 +5,7 @@ from .asset import Asset, Costume, Sound from .project import Project from .extension import Extensions, Extension -from .mutation import Mutation, Argument, parse_proc_code +from .mutation import Mutation, Argument, ArgumentType, parse_proc_code, construct_proccode, ArgTypes from .meta import Meta, set_meta_platform from .sprite import Sprite from .block import Block @@ -18,6 +18,4 @@ from .comment import Comment from .monitor import Monitor -from .editor.mutation import construct_proccode, ArgumentType - from .build_defaulting import add_chain, add_comment, add_block diff --git a/scratchattach/editor/build_defaulting.py b/scratchattach/editor/build_defaulting.py index ef946c11..99fb9867 100644 --- a/scratchattach/editor/build_defaulting.py +++ b/scratchattach/editor/build_defaulting.py @@ -43,7 +43,7 @@ def add_block(_block: block.Block | prim.Prim) -> block.Block | prim.Prim: return current_sprite().add_block(_block) -def add_chain(*chain: Iterable[block.Block, prim.Prim]) -> block.Block | prim.Prim: +def add_chain(*chain: Iterable[block.Block | prim.Prim]) -> block.Block | prim.Prim: return current_sprite().add_chain(*chain) diff --git a/scratchattach/editor/mutation.py b/scratchattach/editor/mutation.py index 9cbbe049..0a34e0c5 100644 --- a/scratchattach/editor/mutation.py +++ b/scratchattach/editor/mutation.py @@ -18,6 +18,7 @@ class ArgumentType(base.Base): proc_str: str def __eq__(self, other): + # noinspection PyProtectedMember if isinstance(other, enums._EnumWrapper): other = other.value @@ -65,25 +66,37 @@ def __lt__(self, other): class Argument(base.MutationSubComponent): name: str default: str = '' + _type: Optional[ArgumentType] = None _id: str = None """ Argument ID: Will be used to replace other parameters during block instantiation. """ + def __post_init__(self): + super().__init__() + @property def index(self): return self.mutation.arguments.index(self) @property - def type(self) -> None | ArgumentType: - i = 0 - goal = self.index - for token in parse_proc_code(self.mutation.proc_code): - if isinstance(token, ArgumentType): - if i == goal: - return token - i += 1 + def type(self) -> Optional[ArgumentType]: + if not self._type: + if not self.mutation: + raise ValueError(f"Cannot infer 'type' of {self} when there is no mutation attached. " + f"Consider providing a type manually.") + + i = 0 + goal = self.index + for token in parse_proc_code(self.mutation.proc_code): + if isinstance(token, ArgumentType): + if i == goal: + self._type = token + break + i += 1 + + return self._type @staticmethod def from_json(data: dict | list | Any): @@ -97,12 +110,13 @@ def link_using_mutation(self): self._id = self.block.new_id +# noinspection PyProtectedMember class ArgTypes(enums._EnumWrapper): BOOLEAN = ArgumentType("boolean", "%b") NUMBER_OR_TEXT = ArgumentType("number or text", "%s") -def parse_proc_code(_proc_code: str) -> list[str, ArgumentType] | None: +def parse_proc_code(_proc_code: str) -> Optional[list[str | ArgumentType]]: """ Parse a proccode (part of a mutation) into argument types and strings """ @@ -142,41 +156,36 @@ def parse_proc_code(_proc_code: str) -> list[str, ArgumentType] | None: return tokens -def construct_proccode(components): - +def construct_proccode(*components: ArgumentType | ArgTypes | Argument | str) -> str: """ - if your reading ts: - sorry if the code is bad or doesnt work. ive only recently gotten into python - if it doesnt work telling me whats wrong/helping me out would really help :p - - anyway the components may include: - ArgumentType enums - Argument instances - plain text stirngs - - should output smth like: - move %n steps. - say %s for %n seconds. - + Create a proccode from strings/ArgumentType enum members/Argument instances + + :param components: list of strings/Arguments/ArgumentType instances + :return: A proccode, e.g. 'move %s steps' or 'say %s for %n seconds' """ - - - result = [] + + result = "" for comp in components: if isinstance(comp, ArgumentType): - result.append(comp.proc_str) + result += comp.proc_str - elif hasattr(comp, 'typename'): - result.append(f"[{comp.typename}]") + elif isinstance(comp, ArgTypes): + new: ArgumentType = comp.value + result += new.proc_str - elif hasattr(comp, 'name') and hasattr(comp, 'type'): - result.append(f"[{comp.type} {comp.name}]") + elif isinstance(comp, Argument): + result += comp.type.proc_str + + elif isinstance(comp, str): + result += comp else: raise TypeError(f"Unsupported component type: {type(comp)}") - return " ".join(result) + result += ' ' + + return result class Mutation(base.BlockSubComponent): @@ -308,7 +317,7 @@ def get(_lst: list | tuple | None, _idx: int): _arg_name = get(_argument_names, i) _arg_default = get(_argument_defaults, i) - _arguments.append(Argument(_arg_name, _arg_default, _arg_id)) + _arguments.append(Argument(_arg_name, _arg_default, _id=_arg_id)) return Mutation(_tag_name, _children, _proc_code, _is_warp, _arguments, _has_next, _argument_settings) From 420a9833853916b8399682a2c448486667ad1d85 Mon Sep 17 00:00:00 2001 From: faretek <107722825+FAReTek1@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:34:48 +0100 Subject: [PATCH 10/11] fix: make sprite optional in __init__ --- scratchattach/editor/base.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scratchattach/editor/base.py b/scratchattach/editor/base.py index d60fc10c..f637bc30 100644 --- a/scratchattach/editor/base.py +++ b/scratchattach/editor/base.py @@ -92,9 +92,7 @@ class SpriteSubComponent(JSONSerializable, ABC): sprite: module_sprite.Sprite def __init__(self, _sprite: "commons.SpriteInput" = build_defaulting.SPRITE_DEFAULT): if _sprite is build_defaulting.SPRITE_DEFAULT: - retrieved_sprite = build_defaulting.current_sprite() - assert retrieved_sprite is not None, "You don't have any sprites." - _sprite = retrieved_sprite + _sprite = build_defaulting.current_sprite() self.sprite = _sprite @property From 14360d8b8bfe2ec6cb266d558f92e6231be38119 Mon Sep 17 00:00:00 2001 From: faretek <107722825+FAReTek1@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:37:38 +0100 Subject: [PATCH 11/11] fix: remove trailing spaces from parsed proccodes --- scratchattach/editor/mutation.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scratchattach/editor/mutation.py b/scratchattach/editor/mutation.py index 0a34e0c5..5f7800c7 100644 --- a/scratchattach/editor/mutation.py +++ b/scratchattach/editor/mutation.py @@ -134,6 +134,10 @@ def parse_proc_code(_proc_code: str) -> Optional[list[str | ArgumentType]]: token = token[:-1] # Clip the % sign off the token + if token.endswith(' '): + # A space is required before params, but this should not be part of the parsed output + token = token[:-1] + if token != '': # Make sure not to append an empty token tokens.append(token)