scratchattach 2.1.9__py3-none-any.whl → 2.1.10a0__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.
Files changed (59) hide show
  1. scratchattach/__init__.py +28 -25
  2. scratchattach/cloud/__init__.py +2 -0
  3. scratchattach/cloud/_base.py +454 -282
  4. scratchattach/cloud/cloud.py +171 -168
  5. scratchattach/editor/__init__.py +21 -0
  6. scratchattach/editor/asset.py +199 -0
  7. scratchattach/editor/backpack_json.py +117 -0
  8. scratchattach/editor/base.py +142 -0
  9. scratchattach/editor/block.py +507 -0
  10. scratchattach/editor/blockshape.py +353 -0
  11. scratchattach/editor/build_defaulting.py +47 -0
  12. scratchattach/editor/comment.py +74 -0
  13. scratchattach/editor/commons.py +243 -0
  14. scratchattach/editor/extension.py +43 -0
  15. scratchattach/editor/field.py +90 -0
  16. scratchattach/editor/inputs.py +132 -0
  17. scratchattach/editor/meta.py +106 -0
  18. scratchattach/editor/monitor.py +175 -0
  19. scratchattach/editor/mutation.py +317 -0
  20. scratchattach/editor/pallete.py +91 -0
  21. scratchattach/editor/prim.py +170 -0
  22. scratchattach/editor/project.py +273 -0
  23. scratchattach/editor/sbuild.py +2837 -0
  24. scratchattach/editor/sprite.py +586 -0
  25. scratchattach/editor/twconfig.py +113 -0
  26. scratchattach/editor/vlb.py +134 -0
  27. scratchattach/eventhandlers/_base.py +99 -92
  28. scratchattach/eventhandlers/cloud_events.py +110 -103
  29. scratchattach/eventhandlers/cloud_recorder.py +26 -21
  30. scratchattach/eventhandlers/cloud_requests.py +460 -452
  31. scratchattach/eventhandlers/cloud_server.py +246 -244
  32. scratchattach/eventhandlers/cloud_storage.py +135 -134
  33. scratchattach/eventhandlers/combine.py +29 -27
  34. scratchattach/eventhandlers/filterbot.py +160 -159
  35. scratchattach/eventhandlers/message_events.py +41 -40
  36. scratchattach/other/other_apis.py +284 -212
  37. scratchattach/other/project_json_capabilities.py +475 -546
  38. scratchattach/site/_base.py +64 -46
  39. scratchattach/site/activity.py +414 -122
  40. scratchattach/site/backpack_asset.py +118 -84
  41. scratchattach/site/classroom.py +430 -142
  42. scratchattach/site/cloud_activity.py +107 -103
  43. scratchattach/site/comment.py +220 -190
  44. scratchattach/site/forum.py +400 -399
  45. scratchattach/site/project.py +806 -787
  46. scratchattach/site/session.py +1134 -867
  47. scratchattach/site/studio.py +611 -609
  48. scratchattach/site/user.py +835 -837
  49. scratchattach/utils/commons.py +243 -148
  50. scratchattach/utils/encoder.py +157 -156
  51. scratchattach/utils/enums.py +197 -190
  52. scratchattach/utils/exceptions.py +233 -206
  53. scratchattach/utils/requests.py +67 -59
  54. {scratchattach-2.1.9.dist-info → scratchattach-2.1.10a0.dist-info}/LICENSE +21 -21
  55. {scratchattach-2.1.9.dist-info → scratchattach-2.1.10a0.dist-info}/METADATA +154 -146
  56. scratchattach-2.1.10a0.dist-info/RECORD +62 -0
  57. {scratchattach-2.1.9.dist-info → scratchattach-2.1.10a0.dist-info}/WHEEL +1 -1
  58. scratchattach-2.1.9.dist-info/RECORD +0 -40
  59. {scratchattach-2.1.9.dist-info → scratchattach-2.1.10a0.dist-info}/top_level.txt +0 -0
@@ -1,135 +1,136 @@
1
- """CloudStorage class"""
2
-
3
- from .cloud_requests import CloudRequests
4
- import json
5
- import time
6
- from threading import Thread
7
-
8
- class Database:
9
-
10
- """
11
- A Database is a simple key-value storage that stores data in a JSON file saved locally (other database services like MongoDB can be implemented)
12
- """
13
-
14
- def __init__(self, name, *, json_file_path, save_interval=30):
15
- self.save_event_function = None
16
- self.set_event_function = None
17
- self.name = name
18
-
19
- # Import from JSON file
20
- if not json_file_path.endswith(".json"):
21
- json_file_path = json_file_path+".json"
22
- self.json_file_path = json_file_path
23
-
24
- try:
25
- with open(json_file_path, 'r') as json_file:
26
- self.data = json.load(json_file)
27
- except FileNotFoundError:
28
- print(f"Creating file {json_file_path}. Your database {name} will be stored there.")
29
- self.data = {}
30
- self.save_to_json()
31
-
32
- if isinstance(self.data , list):
33
- raise ValueError(
34
- "Invalid JSON file content: Top-level object must be a dict, not a list"
35
- )
36
-
37
- # Start autosaving
38
- self.save_interval = save_interval
39
- if self.save_interval is not None:
40
- Thread(target=self._autosaver).start()
41
-
42
- def save_to_json(self):
43
- with open(self.json_file_path, 'w') as json_file:
44
- json.dump(self.data, json_file, indent=4)
45
-
46
- if self.save_event_function is not None:
47
- self.save_event_function()
48
-
49
- def keys(self) -> list:
50
- return list(self.data.keys())
51
-
52
- def get(self, key) -> str:
53
- if not key in self.data:
54
- return None
55
- return self.data[key]
56
-
57
- def set(self, key, value):
58
- self.data[key] = value
59
-
60
- if self.set_event_function is not None:
61
- self.set_event_function(key, value)
62
-
63
- def event(self, event_function):
64
- # Decorator function for adding the on_save event that is called when a save is performed
65
- if event_function.__name__ == "on_save":
66
- self.save_event_function = event_function
67
- if event_function.__name__ == "on_set":
68
- self.set_event_function = event_function
69
-
70
- def _autosaver(self):
71
- # Task autosaving the db. save interval specified in .save_interval attribute
72
- while True:
73
- time.sleep(self.save_interval)
74
- self.save_to_json()
75
-
76
- class CloudStorage(CloudRequests):
77
-
78
- """
79
- A CloudStorage object saves multiple databases and allows the connected Scratch project to access and modify the data of these databases through cloud requests
80
-
81
- The CloudStorage class is built upon CloudRequests
82
- """
83
-
84
- def __init__(self, cloud, used_cloud_vars=["1", "2", "3", "4", "5", "6", "7", "8", "9"], no_packet_loss=False):
85
- super().__init__(cloud, used_cloud_vars=used_cloud_vars, no_packet_loss=no_packet_loss)
86
- # Setup
87
- self._databases = {}
88
- self.request(self.get, thread=False)
89
- self.request(self.set, thread=False)
90
- self.request(self.keys, thread=False)
91
- self.request(self.database_names, thread=False)
92
- self.request(self.ping, thread=False)
93
-
94
- def ping(self):
95
- return "Database backend is running"
96
-
97
- def get(self, db_name, key) -> str:
98
- try:
99
- return self.get_database(db_name).get(key)
100
- except Exception:
101
- if self.get_database(db_name) is None:
102
- return f"Error: Database {db_name} doesn't exist"
103
- else:
104
- return f"Error: Key {key} doesn't exist in database {db_name}"
105
-
106
- def set(self, db_name, key, value):
107
- print(db_name, key, value, self._databases)
108
- return self.get_database(db_name).set(key, value)
109
-
110
- def keys(self, db_name) -> list:
111
- try:
112
- return self.get_database(db_name).keys()
113
- except Exception:
114
- return f"Error: Database {db_name} doesn't exist"
115
-
116
- def databases(self) -> list:
117
- return list(self._databases.values())
118
-
119
- def database_names(self) -> list:
120
- return list(self._databases.keys())
121
-
122
- def add_database(self, database:Database):
123
- self._databases[database.name] = database
124
-
125
- def get_database(self, name) -> Database:
126
- if name in self._databases:
127
- return self._databases[name]
128
- return None
129
-
130
- def save(self):
131
- """
132
- Saves the data in the JSON files for all databases in self._databases
133
- """
134
- for dbname in self._databases:
1
+ """CloudStorage class"""
2
+ from __future__ import annotations
3
+
4
+ from .cloud_requests import CloudRequests
5
+ import json
6
+ import time
7
+ from threading import Thread
8
+
9
+ class Database:
10
+
11
+ """
12
+ A Database is a simple key-value storage that stores data in a JSON file saved locally (other database services like MongoDB can be implemented)
13
+ """
14
+
15
+ def __init__(self, name, *, json_file_path, save_interval=30):
16
+ self.save_event_function = None
17
+ self.set_event_function = None
18
+ self.name = name
19
+
20
+ # Import from JSON file
21
+ if not json_file_path.endswith(".json"):
22
+ json_file_path = json_file_path+".json"
23
+ self.json_file_path = json_file_path
24
+
25
+ try:
26
+ with open(json_file_path, 'r') as json_file:
27
+ self.data = json.load(json_file)
28
+ except FileNotFoundError:
29
+ print(f"Creating file {json_file_path}. Your database {name} will be stored there.")
30
+ self.data = {}
31
+ self.save_to_json()
32
+
33
+ if isinstance(self.data , list):
34
+ raise ValueError(
35
+ "Invalid JSON file content: Top-level object must be a dict, not a list"
36
+ )
37
+
38
+ # Start autosaving
39
+ self.save_interval = save_interval
40
+ if self.save_interval is not None:
41
+ Thread(target=self._autosaver).start()
42
+
43
+ def save_to_json(self):
44
+ with open(self.json_file_path, 'w') as json_file:
45
+ json.dump(self.data, json_file, indent=4)
46
+
47
+ if self.save_event_function is not None:
48
+ self.save_event_function()
49
+
50
+ def keys(self) -> list:
51
+ return list(self.data.keys())
52
+
53
+ def get(self, key) -> str:
54
+ if not key in self.data:
55
+ return None
56
+ return self.data[key]
57
+
58
+ def set(self, key, value):
59
+ self.data[key] = value
60
+
61
+ if self.set_event_function is not None:
62
+ self.set_event_function(key, value)
63
+
64
+ def event(self, event_function):
65
+ # Decorator function for adding the on_save event that is called when a save is performed
66
+ if event_function.__name__ == "on_save":
67
+ self.save_event_function = event_function
68
+ if event_function.__name__ == "on_set":
69
+ self.set_event_function = event_function
70
+
71
+ def _autosaver(self):
72
+ # Task autosaving the db. save interval specified in .save_interval attribute
73
+ while True:
74
+ time.sleep(self.save_interval)
75
+ self.save_to_json()
76
+
77
+ class CloudStorage(CloudRequests):
78
+
79
+ """
80
+ A CloudStorage object saves multiple databases and allows the connected Scratch project to access and modify the data of these databases through cloud requests
81
+
82
+ The CloudStorage class is built upon CloudRequests
83
+ """
84
+
85
+ def __init__(self, cloud, used_cloud_vars=["1", "2", "3", "4", "5", "6", "7", "8", "9"], no_packet_loss=False):
86
+ super().__init__(cloud, used_cloud_vars=used_cloud_vars, no_packet_loss=no_packet_loss)
87
+ # Setup
88
+ self._databases = {}
89
+ self.request(self.get, thread=False)
90
+ self.request(self.set, thread=False)
91
+ self.request(self.keys, thread=False)
92
+ self.request(self.database_names, thread=False)
93
+ self.request(self.ping, thread=False)
94
+
95
+ def ping(self):
96
+ return "Database backend is running"
97
+
98
+ def get(self, db_name, key) -> str:
99
+ try:
100
+ return self.get_database(db_name).get(key)
101
+ except Exception:
102
+ if self.get_database(db_name) is None:
103
+ return f"Error: Database {db_name} doesn't exist"
104
+ else:
105
+ return f"Error: Key {key} doesn't exist in database {db_name}"
106
+
107
+ def set(self, db_name, key, value):
108
+ print(db_name, key, value, self._databases)
109
+ return self.get_database(db_name).set(key, value)
110
+
111
+ def keys(self, db_name) -> list:
112
+ try:
113
+ return self.get_database(db_name).keys()
114
+ except Exception:
115
+ return f"Error: Database {db_name} doesn't exist"
116
+
117
+ def databases(self) -> list:
118
+ return list(self._databases.values())
119
+
120
+ def database_names(self) -> list:
121
+ return list(self._databases.keys())
122
+
123
+ def add_database(self, database:Database):
124
+ self._databases[database.name] = database
125
+
126
+ def get_database(self, name) -> Database:
127
+ if name in self._databases:
128
+ return self._databases[name]
129
+ return None
130
+
131
+ def save(self):
132
+ """
133
+ Saves the data in the JSON files for all databases in self._databases
134
+ """
135
+ for dbname in self._databases:
135
136
  self._databases[dbname].save_to_json()
@@ -1,28 +1,30 @@
1
- class MultiEventHandler:
2
-
3
- def __init__(self, *handlers):
4
- self.handlers = handlers
5
-
6
- def request(self, function, *args, **kwargs):
7
- for handler in self.handlers:
8
- handler.request(function, *args, **kwargs)
9
-
10
- def event(self, function, *args, **kwargs):
11
- for handler in self.handlers:
12
- handler.request(function, *args, **kwargs)
13
-
14
- def start(self, *args, **kwargs):
15
- for handler in self.handlers:
16
- handler.start(*args, **kwargs)
17
-
18
- def stop(self, *args, **kwargs):
19
- for handler in self.handlers:
20
- handler.stop(*args, **kwargs)
21
-
22
- def pause(self, *args, **kwargs):
23
- for handler in self.handlers:
24
- handler.pause(*args, **kwargs)
25
-
26
- def resume(self, *args, **kwargs):
27
- for handler in self.handlers:
1
+ from __future__ import annotations
2
+
3
+ class MultiEventHandler:
4
+
5
+ def __init__(self, *handlers):
6
+ self.handlers = handlers
7
+
8
+ def request(self, function, *args, **kwargs):
9
+ for handler in self.handlers:
10
+ handler.request(function, *args, **kwargs)
11
+
12
+ def event(self, function, *args, **kwargs):
13
+ for handler in self.handlers:
14
+ handler.request(function, *args, **kwargs)
15
+
16
+ def start(self, *args, **kwargs):
17
+ for handler in self.handlers:
18
+ handler.start(*args, **kwargs)
19
+
20
+ def stop(self, *args, **kwargs):
21
+ for handler in self.handlers:
22
+ handler.stop(*args, **kwargs)
23
+
24
+ def pause(self, *args, **kwargs):
25
+ for handler in self.handlers:
26
+ handler.pause(*args, **kwargs)
27
+
28
+ def resume(self, *args, **kwargs):
29
+ for handler in self.handlers:
28
30
  handler.resume(*args, **kwargs)