pyui-desktop 0.5.0__tar.gz

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 (40) hide show
  1. pyui_desktop-0.5.0/PKG-INFO +91 -0
  2. pyui_desktop-0.5.0/PYUI/JS/connection.js +188 -0
  3. pyui_desktop-0.5.0/PYUI/JS/handler.js +336 -0
  4. pyui_desktop-0.5.0/PYUI/PYUICommonExecutable.spec +64 -0
  5. pyui_desktop-0.5.0/PYUI/Package/PYUI.py +590 -0
  6. pyui_desktop-0.5.0/PYUI/Package/bootstrap.py +702 -0
  7. pyui_desktop-0.5.0/PYUI/Package/pyuinode.py +33 -0
  8. pyui_desktop-0.5.0/PYUI/__pycache__/__init__.cpython-313.pyc +0 -0
  9. pyui_desktop-0.5.0/PYUI/__pycache__/buildscript.cpython-313.pyc +0 -0
  10. pyui_desktop-0.5.0/PYUI/__pycache__/buildtools.cpython-313.pyc +0 -0
  11. pyui_desktop-0.5.0/PYUI/__pycache__/compiler.cpython-313.pyc +0 -0
  12. pyui_desktop-0.5.0/PYUI/__pycache__/converter.cpython-313.pyc +0 -0
  13. pyui_desktop-0.5.0/PYUI/__pycache__/pyuinode.cpython-313.pyc +0 -0
  14. pyui_desktop-0.5.0/PYUI/__pycache__/settings.cpython-313.pyc +0 -0
  15. pyui_desktop-0.5.0/PYUI/__pycache__/tailwindBuilder.cpython-313.pyc +0 -0
  16. pyui_desktop-0.5.0/PYUI/boilerplate/index.css +2 -0
  17. pyui_desktop-0.5.0/PYUI/boilerplate/index.py +5 -0
  18. pyui_desktop-0.5.0/PYUI/boilerplate/index.xml +42 -0
  19. pyui_desktop-0.5.0/PYUI/buildscript.py +274 -0
  20. pyui_desktop-0.5.0/PYUI/buildtools.py +396 -0
  21. pyui_desktop-0.5.0/PYUI/compiler.py +463 -0
  22. pyui_desktop-0.5.0/PYUI/converter.py +149 -0
  23. pyui_desktop-0.5.0/PYUI/create.py +96 -0
  24. pyui_desktop-0.5.0/PYUI/dll/xmlParser.dll +0 -0
  25. pyui_desktop-0.5.0/PYUI/pyuinode.py +33 -0
  26. pyui_desktop-0.5.0/PYUI/requirements.txt +0 -0
  27. pyui_desktop-0.5.0/PYUI/settings.py +80 -0
  28. pyui_desktop-0.5.0/PYUI/tailwindBuilder.py +39 -0
  29. pyui_desktop-0.5.0/README.md +87 -0
  30. pyui_desktop-0.5.0/README_pypi.md +78 -0
  31. pyui_desktop-0.5.0/XMLParser/raw.c +658 -0
  32. pyui_desktop-0.5.0/XMLParser/xmlparser.c +640 -0
  33. pyui_desktop-0.5.0/pyproject.toml +31 -0
  34. pyui_desktop-0.5.0/pyui_desktop.egg-info/PKG-INFO +91 -0
  35. pyui_desktop-0.5.0/pyui_desktop.egg-info/SOURCES.txt +38 -0
  36. pyui_desktop-0.5.0/pyui_desktop.egg-info/dependency_links.txt +1 -0
  37. pyui_desktop-0.5.0/pyui_desktop.egg-info/requires.txt +5 -0
  38. pyui_desktop-0.5.0/pyui_desktop.egg-info/top_level.txt +3 -0
  39. pyui_desktop-0.5.0/setup.cfg +4 -0
  40. pyui_desktop-0.5.0/setup.py +4 -0
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyui-desktop
3
+ Version: 0.5.0
4
+ Summary: A short description of my package
5
+ Author-email: Akalabaya Pal <akalabaya.2008@proton.me>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: pywebview==6.2.1
9
+ Requires-Dist: watchdog==6.0.0
10
+ Requires-Dist: websockets==16.0
11
+ Requires-Dist: colorama
12
+ Requires-Dist: pyinstaller
13
+
14
+ # PYUI(Python UI)
15
+
16
+ This project is targeted to make cross platform applications using python.PYUI is a layout pre-compiled framework for making python applications in very lightweight sizes. It uses a xml layouting system for defining layouts, python for logic and **PYWebview** as the renderer.Leading to a blank application size only 16MB compared to heavyweight rendering systems cosing 50+ MB or TKinter that has very legacy thread-unsafe architecture
17
+
18
+ ## Motivation
19
+ 1.**Making General Purpose Applications:** This project is driven by the motivation of making a framework over python that can be used to make general purpose applications with little or no learning curve.
20
+
21
+ 2.**Smaller learning curve:** Recent solutions for UI development mostly are hard to learn and manage. However we adopted age-old xml layouting system that makes defining UI easy for anyone with little xml/html knowlege.
22
+
23
+ 3.**Support of Python libaries and modules:** On the logic side python can use used to it's Limit, also the threadsafe nature of the framework helps in extreme scalability.
24
+
25
+ 4.**Compiled Layout and Reusibility:** This framework has pre-compiled layouting system.So errors in layout are identified on runtime. Also Layout supports re-usibility using **PYUI Components**.
26
+
27
+ ## Key Features of PYUI API
28
+ 1. **DOM Manipulation:** One can change dom components from python side.There style,class,innertext and other attributes.
29
+
30
+ 2. **PYUI Custom Syscalls:** Using this one can extend PYUI to support any JS libaries(chart.js and etc) by writing minimal Javascript.Or can use to commiunicate between JS ans Python runtime if needed without touching internal sockets.
31
+
32
+ 3. **PYUI Hooks:** If some DOM updates are fast and can be lossy but realtime one can use PYUI Hooks.This can be mostly used to stream video or audio from Python to JS runtime
33
+
34
+ 4. **Window Management:** A PYUI forms contain can contain more than one view(window) and **PYUI** provides apis to change windows dynamically. Also Exposes Webview object for *PYwebview* for changing the application window
35
+
36
+ 5. **Forms Management:** **PYUI** provides dedicated apis to show and hide forms.
37
+
38
+ ## Getting Started
39
+
40
+
41
+ ### Setting up project
42
+
43
+ python -m PYUI.create <directory-of-project>
44
+
45
+ This will generate boilerplate project. Following folder and files will be generated in the given directory.
46
+
47
+ layout
48
+ code
49
+ layout/JS
50
+ layout/styles
51
+ code/index.py
52
+ code/__init__.py
53
+ layout/index.xml
54
+ settings.py
55
+
56
+
57
+ ### Compiling project
58
+
59
+ To compile to a PYUI project and run it
60
+
61
+ python -m PYUI.buildtools --compile <directory-of-project> --run
62
+
63
+ This command will compile your project into a PYUI project and run it. Within few seconds(depending on project size) you can see you layout
64
+
65
+ To compile without running project
66
+
67
+ python -m PYUI.buildtools --compile <directory-of-project>
68
+
69
+ It will save your project in *build/temp_xxxxx.yyyy* (see last line of buildscript output). To launch the project go to the directory and run:
70
+
71
+ python bootstrap.py
72
+
73
+ It will launch your UI
74
+
75
+ ### HotReloading Layouts
76
+
77
+ You can hot-reload the layout for faster UI development.
78
+
79
+ python -m PYUI.buildtools --hotreload <layout-xml-file>
80
+
81
+ Changing the xml file will reload the UI automatically
82
+
83
+ **Note:** Use the *--keepontop* flag to keep the UI on top always
84
+
85
+ For further API references for XML and PYUI check the documentation.
86
+
87
+
88
+ ## Credits
89
+
90
+ PyWebview: https://github.com/r0x0r/pywebview
91
+
@@ -0,0 +1,188 @@
1
+ class PriorityQueue {
2
+ constructor(initialCapacity = 100) {
3
+ this.capacity = initialCapacity;
4
+ this.heap = new Array(this.capacity);
5
+ this.size = 0;
6
+ }
7
+
8
+ // Insert a new object and check for resize
9
+ enqueue(priority, obj) {
10
+ // 1. Check if we need to resize before adding
11
+ if (this.size === this.capacity) {
12
+ this.resize();
13
+ }
14
+
15
+ // 2. Insert at the end of the heap
16
+ const newNode = { priority, object: obj };
17
+ this.heap[this.size] = newNode;
18
+
19
+ // 3. Heapify Up to restore min-heap property
20
+ this.heapifyUp(this.size);
21
+ this.size++;
22
+ }
23
+
24
+ // Remove and return the highest priority item (lowest priority number)
25
+ dequeue() {
26
+ if (this.size === 0) return null;
27
+
28
+ const root = this.heap[0];
29
+ const lastNode = this.heap[this.size - 1];
30
+
31
+ // Move the last element to the root
32
+ this.heap[0] = lastNode;
33
+ this.heap[this.size - 1] = null; // Clear reference for garbage collection
34
+ this.size--;
35
+
36
+ // Heapify Down to restore min-heap property
37
+ if (this.size > 0) {
38
+ this.heapifyDown(0);
39
+ }
40
+
41
+ return root;
42
+ }
43
+
44
+ // Double the array capacity when full
45
+ resize() {
46
+ this.capacity *= 2;
47
+ const newHeap = new Array(this.capacity);
48
+
49
+ // Copy elements over
50
+ for (let i = 0; i < this.size; i++) {
51
+ newHeap[i] = this.heap[i];
52
+ }
53
+
54
+ this.heap = newHeap;
55
+ console.log(`[PriorityQueue] Resized. New capacity: ${this.capacity}`);
56
+ }
57
+
58
+ // Restores heap order going up
59
+ heapifyUp(index) {
60
+ while (index > 0) {
61
+ const parentIndex = Math.floor((index - 1) / 2);
62
+
63
+ // If current node's priority is fine, break
64
+ if (this.heap[index].priority >= this.heap[parentIndex].priority) {
65
+ break;
66
+ }
67
+
68
+ this.swap(index, parentIndex);
69
+ index = parentIndex;
70
+ }
71
+ }
72
+
73
+ // Restores heap order going down
74
+ heapifyDown(index) {
75
+ while (2 * index + 1 < this.size) {
76
+ let smallestChildIndex = 2 * index + 1; // Assume left child is smaller
77
+ const rightChildIndex = 2 * index + 2;
78
+
79
+ // Check if right child exists and has a lower priority number
80
+ if (
81
+ rightChildIndex < this.size &&
82
+ this.heap[rightChildIndex].priority < this.heap[smallestChildIndex].priority
83
+ ) {
84
+ smallestChildIndex = rightChildIndex;
85
+ }
86
+
87
+ // If parent is already smaller than the smallest child, we are done
88
+ if (this.heap[index].priority <= this.heap[smallestChildIndex].priority) {
89
+ break;
90
+ }
91
+
92
+ this.swap(index, smallestChildIndex);
93
+ index = smallestChildIndex;
94
+ }
95
+ }
96
+
97
+ // Helper to swap two nodes in the array
98
+ swap(i, j) {
99
+ const temp = this.heap[i];
100
+ this.heap[i] = this.heap[j];
101
+ this.heap[j] = temp;
102
+ }
103
+
104
+ peek() {
105
+ return this.size > 0 ? this.heap[0] : null;
106
+ }
107
+
108
+ isEmpty() {
109
+ return this.size === 0;
110
+ }
111
+ }
112
+
113
+
114
+
115
+
116
+
117
+ var GLOBAL_SOCKET = null;
118
+
119
+
120
+
121
+
122
+ function connectSocket(port) {
123
+
124
+ socket = new WebSocket('ws://127.0.0.1:' + port.toString());
125
+ GLOBAL_SOCKET = socket;
126
+ const handler = new Msghandler(socket);
127
+ const priority_queue = new PriorityQueue(1000);
128
+
129
+
130
+ // 2. Triggered when the handshake successfully finishes
131
+ socket.onopen = (event) => {
132
+ console.log('Connected to Python WebSocket Server!');
133
+ };
134
+
135
+ // 3. Catch and parse incoming messages from Python as JSON objects
136
+ socket.onmessage = (event) => {
137
+
138
+ var data = JSON.parse(event.data);
139
+ if (data.type == "BATCH_UPDATE") {
140
+ handler.evaluateMsg(data);
141
+ }
142
+ else {
143
+ priority_queue.enqueue(data.count, data);
144
+ }
145
+
146
+
147
+
148
+ };
149
+
150
+ let nextExpectedSequence = 0;
151
+ //Run loop to dequeue the object and get the object
152
+ setInterval(() => {
153
+
154
+ while (!priority_queue.isEmpty()) {
155
+ const topItem = priority_queue.peek(); // Just look, don't remove yet!
156
+
157
+ // If the top item is exactly what we are waiting for, process it!
158
+ if (topItem.priority === nextExpectedSequence) {
159
+ const msg = priority_queue.dequeue();
160
+
161
+ handler.evaluateMsg(msg.object); // Run your UI framework logic here
162
+
163
+ nextExpectedSequence++; // Move to the next expected number
164
+ } else {
165
+ // The next message hasn't arrived from Python yet (there's a gap).
166
+ // Stop processing and wait for the network/socket to catch up!
167
+ break;
168
+ }
169
+ }
170
+
171
+ }, 16);
172
+
173
+ }
174
+
175
+
176
+
177
+
178
+ //Console log routing to main python console
179
+ console.log = function () {
180
+ // Convert arguments to a single string
181
+ var message = Array.from(arguments).join(' ');
182
+
183
+ // Send to Python API
184
+ if (window.pywebview && window.pywebview.api) {
185
+ window.pywebview.api.log(message);
186
+ }
187
+
188
+ };
@@ -0,0 +1,336 @@
1
+ var SECRET_KEY = null;
2
+ var GLOBAL_CUSTOM_SYSCALL_MAP = {}; // Js object to store all the custom syscalls
3
+
4
+
5
+ function register_sign(sign) {
6
+ SECRET_KEY = sign;
7
+ }
8
+
9
+ async function standardSha256(message) {
10
+ // 1. Encode text string into an array of bytes (UTF-8)
11
+ const msgBuffer = new TextEncoder().encode(message);
12
+
13
+ // 2. Compute the raw SHA-256 hash buffer natively
14
+ const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
15
+
16
+ // 3. Convert the raw binary array buffer into a hex string
17
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
18
+ const hashHex = hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
19
+
20
+ return hashHex;
21
+ }
22
+
23
+
24
+ async function computeHmac(message, secretKey) {
25
+ const encoder = new TextEncoder();
26
+
27
+ // 1. Convert text inputs into byte arrays
28
+ const messageBytes = encoder.encode(message);
29
+ const keyBytes = encoder.encode(secretKey);
30
+
31
+ // 2. Import the raw secret key into the crypto engine
32
+ const cryptoKey = await crypto.subtle.importKey(
33
+ "raw",
34
+ keyBytes,
35
+ { name: "HMAC", hash: "SHA-256" },
36
+ false,
37
+ ["sign"]
38
+ );
39
+
40
+ // 3. Compute the raw binary signature
41
+ const signatureBuffer = await crypto.subtle.sign("HMAC", cryptoKey, messageBytes);
42
+
43
+ // 4. Convert the binary signature to a standard hexadecimal string
44
+ const hashArray = Array.from(new Uint8Array(signatureBuffer));
45
+ return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
46
+ }
47
+
48
+
49
+ async function _HandleCallbackSend(uuid, socket) {
50
+ //toSend = "{\"uuid\":\"" + uuid + "\",\"type\":\"CALLBACK\",\"data\":\"\"}";
51
+ toSend = { "uuid": uuid, "type": "CALLBACK", "data": "" };
52
+
53
+ send_str = JSON.stringify(toSend);
54
+
55
+ //Get the sha-256 encoded string.
56
+ sha256_encoded_msg = await standardSha256(send_str);
57
+
58
+ //make hmac
59
+ hmac_code = await computeHmac(sha256_encoded_msg, SECRET_KEY);
60
+ toSend['sign'] = hmac_code
61
+
62
+ socket.send(JSON.stringify(toSend)); //Send the msg back to python runtime
63
+ }
64
+ async function _HandleGrbContent(uuid, socket, value) {
65
+
66
+ toSend = { "uuid": uuid, "type": "GRAB_CONTENT", "data": value };
67
+
68
+ send_str = JSON.stringify(toSend);
69
+
70
+ //Get the sha-256 encoded string.
71
+ sha256_encoded_msg = await standardSha256(send_str);
72
+
73
+ //make hmac
74
+ hmac_code = await computeHmac(sha256_encoded_msg, SECRET_KEY);
75
+ toSend['sign'] = hmac_code
76
+
77
+ socket.send(JSON.stringify(toSend)); //Send the msg back to python runtime
78
+
79
+ }
80
+
81
+
82
+ function HandleStyleClass(args) {
83
+ //args: id,action and class
84
+ var id = args.id;
85
+ var action = args.action;
86
+ var cls = args.class;
87
+
88
+ var ele = document.getElementById(id);
89
+
90
+ if (ele) {
91
+ if (action == 'ADD') {
92
+ ele.classList.add(cls);
93
+ }
94
+ else if (action == 'REMOVE') {
95
+ ele.classList.remove(cls);
96
+ }
97
+ else if (action == 'TOGGLE') {
98
+ ele.classList.toggle(action);
99
+ }
100
+ }
101
+
102
+
103
+ }
104
+
105
+
106
+ async function verifyIncomingMessage(incomingMsg) {
107
+ // 1. Extract the signature and remove it from the object we want to hash
108
+ const incomingSig = incomingMsg.sign;
109
+ delete incomingMsg.sign;
110
+
111
+ // 3. Sort keys and flatten (uuid is naturally included now!)
112
+ const sortedKeys = Object.keys(incomingMsg).sort();
113
+ let flatString = JSON.stringify(incomingMsg);
114
+
115
+ // 4. Hash, compare, and burn
116
+ const dataHash = await standardSha256(flatString);
117
+ const expectedSig = await computeHmac(dataHash, SECRET_KEY);
118
+
119
+ //console.log(flatString,dataHash);
120
+
121
+
122
+ if (incomingSig !== expectedSig) {
123
+ return false;
124
+ }
125
+
126
+ return true;
127
+ }
128
+
129
+
130
+ //Function for binding JS functions with Python syscall
131
+ async function bind(syscall, callback) {
132
+
133
+ //Assign the syscall to GLOBAL CUSTOM SYSCALL MAP
134
+ GLOBAL_CUSTOM_SYSCALL_MAP[syscall] = callback;
135
+
136
+ }
137
+
138
+ function generateUUID() {
139
+ return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
140
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
141
+ );
142
+ }
143
+
144
+ async function sendSyscall(syscall, msg) {
145
+ var call = GLOBAL_CUSTOM_SYSCALL_MAP[syscall];
146
+ if (call) {
147
+ var toSend = { "data": msg, "type": syscall,"uuid":generateUUID() };
148
+
149
+ send_str = JSON.stringify(toSend);
150
+
151
+ //Get the sha-256 encoded string.
152
+ sha256_encoded_msg = await standardSha256(send_str);
153
+
154
+ //make hmac
155
+ hmac_code = await computeHmac(sha256_encoded_msg, SECRET_KEY);
156
+ toSend['sign'] = hmac_code
157
+
158
+
159
+ GLOBAL_SOCKET.send(JSON.stringify(toSend));
160
+ }
161
+ else {
162
+ console.log("Error:The callback " + syscall + " is not registered.");
163
+ }
164
+ }
165
+
166
+
167
+ class Msghandler {
168
+ constructor(socket) {
169
+
170
+ this.socket = socket;
171
+ this.callBackWrappers = new Object({});
172
+ this.processed_map = new Object({});
173
+
174
+ }
175
+
176
+
177
+ async evaluateMsg(jsonMessage) {
178
+
179
+ var type = jsonMessage.type;
180
+ var uuid = jsonMessage.uuid;
181
+
182
+
183
+
184
+ if (!(uuid in this.processed_map) && await verifyIncomingMessage(jsonMessage)) {
185
+ if (type == "EXECUTE_ONLY") {
186
+
187
+ //add it to processed list to maintain at most one call
188
+ this.processed_map[uuid] = true;
189
+
190
+ var content = jsonMessage.data;
191
+ this.handleExecuteJs(content);
192
+
193
+ }
194
+
195
+ else if (type == "REGISTER_CALLBACK") {
196
+
197
+ var id = jsonMessage.id;
198
+ var typeCallback = jsonMessage.callback_type;
199
+ var wrapper = this.registerCallback(id, typeCallback, uuid);
200
+
201
+ var container = { wrap: wrapper, type: typeCallback, Eleid: id };
202
+ console.log(container);
203
+
204
+
205
+ }
206
+ else if (type == "UNREGISTER_CALLBACK") {
207
+ var uuid_callback = jsonMessage.id;
208
+ cont = this.callBackWrappers[uuid_callback];
209
+ id = cont.Eleid;
210
+ type = cont.type;
211
+ wrap = cont.wrap;
212
+ document.getElementById(id).removeEventListener(type, wrap);
213
+
214
+ delete this.callBackWrappers[uuid_callback];
215
+ }
216
+ else if (type == "GRAB_CONTENT") {
217
+ var id = jsonMessage.id;
218
+ var attrib = jsonMessage.attrib;
219
+
220
+ if (attrib == 'value') {
221
+ var value = document.getElementById(id).value;
222
+ }
223
+ else if (attrib == 'text') {
224
+ var value = document.getElementById(id).textContent;
225
+ }
226
+
227
+ else {
228
+ var value = document.getElementById(id).getAttribute(attrib);
229
+ }
230
+
231
+ _HandleGrbContent(uuid, this.socket, value);
232
+ }
233
+
234
+
235
+ else if (type == "BATCH_UPDATE") {
236
+
237
+ //To update multiple things at once...
238
+
239
+ for (let index = 0; index < jsonMessage.batch.length; index++) {
240
+ this.evaluateMsg(jsonMessage.batch[index]);
241
+
242
+ }
243
+ }
244
+
245
+
246
+ else {
247
+
248
+ //Check if some custom syscall is present if present call it
249
+
250
+ var callback = GLOBAL_CUSTOM_SYSCALL_MAP[type];
251
+ if (callback) {
252
+ callback(jsonMessage);
253
+ }
254
+ else {
255
+ console.log("[Error] No associated callback for custom syscall:" + type);
256
+ }
257
+ }
258
+
259
+ }
260
+ else {
261
+ console.log("Wrong uuid or signature did not match.Hence dropping the packet.");
262
+ }
263
+ }
264
+
265
+ async handleExecuteJs(js_content) {
266
+
267
+ var execution_type = js_content.js_type;
268
+ var args = js_content.args;
269
+
270
+ if (execution_type == 'updateText') {
271
+
272
+ //We need text:value and id:id
273
+ var text = args.text;
274
+ var id = args.id;
275
+
276
+ //Update the text
277
+ var ele = document.getElementById(id);
278
+
279
+ if (ele) {
280
+ ele.textContent = text;
281
+ }
282
+ }
283
+ else if (execution_type == 'update') {
284
+
285
+ //We need value:value, id:id and att:attribute
286
+ var id = args.id;
287
+ var value = args.value;
288
+ var att = args.att;
289
+
290
+ var ele = document.getElementById(id);
291
+
292
+ if (ele) {
293
+ ele.setAttribute(att, value);
294
+ }
295
+
296
+ }
297
+ else if (execution_type == 'updateStyle') {
298
+
299
+ //We need id:id , att:attribute and value:value
300
+ var id = args.id;
301
+ var value = args.value;
302
+ var att = args.att;
303
+
304
+
305
+
306
+ var js = "document.getElementById(\"" + id + "\").style." + att + " = \"" + value + "\" ;"
307
+ eval(js);
308
+ }
309
+ else if (execution_type == 'addstyleclass') {
310
+ HandleStyleClass(args);
311
+ }
312
+ else if (execution_type == 'remove') {
313
+
314
+ var id = args.id;
315
+ var att = args.att;
316
+ var ele = document.getElementById(id);
317
+ ele.removeAttribute(att);
318
+
319
+ }
320
+ }
321
+
322
+ async registerCallback(id, eventType, uuid) {
323
+
324
+ //To handle the REGISTER_CALLBACK syscalls...
325
+ var element = document.getElementById(id);
326
+ var wrapper = () => _HandleCallbackSend(uuid, this.socket);
327
+ if (element) {
328
+ element.addEventListener(eventType, wrapper);
329
+ }
330
+
331
+ return wrapper;
332
+
333
+
334
+ }
335
+
336
+ }
@@ -0,0 +1,64 @@
1
+ # -*- mode: python ; coding: utf-8 -*-
2
+
3
+ import os
4
+ import glob
5
+
6
+ # 1. Name of well-defined folder
7
+ FOLDER_BUILD = os.environ.get('FOLDER')
8
+ FOLDET_OUT = os.environ.get('OUT')
9
+ PROJECT_NAME = os.environ.get('NAME')
10
+ IS_CONSOLE = os.environ.get('CONSOLE')
11
+ if IS_CONSOLE == '0':
12
+ IS_CONSOLE = False
13
+ else:
14
+ IS_CONSOLE = True
15
+
16
+ MODULE_FOLDER = 'code' # Change this to your folder's actual name
17
+
18
+ dynamic_modules = []
19
+
20
+ # 2. Automatically scan the folder for all Python files
21
+ search_path = os.path.join(MODULE_FOLDER, "**", "*.py")
22
+ for file_path in glob.glob(search_path, recursive=True):
23
+ if os.path.basename(file_path) != '__init__.py':
24
+ # Convert file path 'my_custom_folder/sub/module.py' -> 'my_custom_folder.sub.module'
25
+ module_name = os.path.splitext(file_path)[0].replace(os.sep, '.')
26
+ dynamic_modules.append(module_name)
27
+
28
+ #
29
+
30
+ a = Analysis(
31
+ ['bootstrap.py'],
32
+ pathex=[],
33
+ binaries=[],
34
+ datas=[('code', 'code'), ('compiled_layouts', 'compiled_layouts'), ('layouts', 'layouts')],
35
+ hiddenimports=dynamic_modules,
36
+ hookspath=[],
37
+ hooksconfig={},
38
+ runtime_hooks=[],
39
+ excludes=[],
40
+ noarchive=False,
41
+ optimize=0,
42
+ )
43
+ pyz = PYZ(a.pure)
44
+
45
+ exe = EXE(
46
+ pyz,
47
+ a.scripts,
48
+ a.binaries,
49
+ a.datas,
50
+ [],
51
+ name=PROJECT_NAME,
52
+ debug=False,
53
+ bootloader_ignore_signals=False,
54
+ strip=False,
55
+ upx=True,
56
+ upx_exclude=[],
57
+ runtime_tmpdir=None,
58
+ console=IS_CONSOLE,
59
+ disable_windowed_traceback=False,
60
+ argv_emulation=False,
61
+ target_arch=None,
62
+ codesign_identity=None,
63
+ entitlements_file=None,
64
+ )