pyloid 0.26.3__tar.gz → 0.26.5__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. {pyloid-0.26.3 → pyloid-0.26.5}/PKG-INFO +1 -1
  2. {pyloid-0.26.3 → pyloid-0.26.5}/pyproject.toml +4 -1
  3. pyloid-0.26.5/src/pyloid/__init__.py +5 -0
  4. pyloid-0.26.5/src/pyloid/autostart.py +164 -0
  5. pyloid-0.26.5/src/pyloid/base_ipc/base.py +395 -0
  6. {pyloid-0.26.3/src/pyloid/js_api → pyloid-0.26.5/src/pyloid/base_ipc}/event_api.py +1 -1
  7. pyloid-0.26.5/src/pyloid/browser_window.py +3910 -0
  8. pyloid-0.26.5/src/pyloid/custom/titlebar.py +179 -0
  9. pyloid-0.26.5/src/pyloid/filewatcher.py +193 -0
  10. pyloid-0.26.5/src/pyloid/ipc.py +142 -0
  11. pyloid-0.26.5/src/pyloid/monitor.py +1118 -0
  12. pyloid-0.26.5/src/pyloid/pyloid.py +3449 -0
  13. pyloid-0.26.5/src/pyloid/rpc.py +755 -0
  14. pyloid-0.26.5/src/pyloid/serve.py +323 -0
  15. pyloid-0.26.5/src/pyloid/store.py +257 -0
  16. pyloid-0.26.5/src/pyloid/thread_pool.py +648 -0
  17. pyloid-0.26.5/src/pyloid/timer.py +426 -0
  18. pyloid-0.26.5/src/pyloid/tray.py +64 -0
  19. pyloid-0.26.5/src/pyloid/url_interceptor.py +42 -0
  20. pyloid-0.26.5/src/pyloid/utils.py +258 -0
  21. pyloid-0.26.3/src/pyloid/__init__.py +0 -3
  22. pyloid-0.26.3/src/pyloid/api.py +0 -104
  23. pyloid-0.26.3/src/pyloid/autostart.py +0 -101
  24. pyloid-0.26.3/src/pyloid/browser_window.py +0 -3145
  25. pyloid-0.26.3/src/pyloid/custom/titlebar.py +0 -116
  26. pyloid-0.26.3/src/pyloid/filewatcher.py +0 -163
  27. pyloid-0.26.3/src/pyloid/js_api/base.py +0 -259
  28. pyloid-0.26.3/src/pyloid/monitor.py +0 -921
  29. pyloid-0.26.3/src/pyloid/pyloid.py +0 -2724
  30. pyloid-0.26.3/src/pyloid/rpc.py +0 -548
  31. pyloid-0.26.3/src/pyloid/serve.py +0 -231
  32. pyloid-0.26.3/src/pyloid/store.py +0 -179
  33. pyloid-0.26.3/src/pyloid/thread_pool.py +0 -501
  34. pyloid-0.26.3/src/pyloid/timer.py +0 -307
  35. pyloid-0.26.3/src/pyloid/tray.py +0 -48
  36. pyloid-0.26.3/src/pyloid/url_interceptor.py +0 -25
  37. pyloid-0.26.3/src/pyloid/utils.py +0 -208
  38. {pyloid-0.26.3 → pyloid-0.26.5}/LICENSE +0 -0
  39. {pyloid-0.26.3 → pyloid-0.26.5}/README.md +0 -0
  40. {pyloid-0.26.3/src/pyloid/js_api → pyloid-0.26.5/src/pyloid/base_ipc}/window_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyloid
3
- Version: 0.26.3
3
+ Version: 0.26.5
4
4
  Summary:
5
5
  Author: aesthetics-of-record
6
6
  Author-email: 111675679+aesthetics-of-record@users.noreply.github.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pyloid"
3
- version = "0.26.3"
3
+ version = "0.26.5"
4
4
  description = ""
5
5
  authors = ["aesthetics-of-record <111675679+aesthetics-of-record@users.noreply.github.com>"]
6
6
  readme = "README.md"
@@ -16,6 +16,9 @@ pickledb = "^1.3.2"
16
16
  aiohttp-cors = "^0.8.1"
17
17
  aiofiles = "^24.1.0"
18
18
 
19
+ [tool.poetry.group.dev.dependencies]
20
+ ruff = "^0.13.2"
21
+
19
22
  [build-system]
20
23
  requires = ["poetry-core"]
21
24
  build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,5 @@
1
+ from .pyloid import (
2
+ Pyloid,
3
+ )
4
+
5
+ __all__ = ['Pyloid']
@@ -0,0 +1,164 @@
1
+ import sys
2
+ import os
3
+
4
+ if sys.platform == 'win32':
5
+ import winreg as reg
6
+
7
+
8
+ class AutoStart:
9
+ def __init__(
10
+ self,
11
+ app_name,
12
+ app_path,
13
+ ):
14
+ self.app_name = app_name
15
+ self.app_path = app_path
16
+
17
+ def set_auto_start(
18
+ self,
19
+ enable: bool,
20
+ ):
21
+ if sys.platform == 'win32':
22
+ self._set_auto_start_windows(enable)
23
+ elif sys.platform == 'darwin':
24
+ self._set_auto_start_macos(enable)
25
+ elif sys.platform.startswith('linux'):
26
+ self._set_auto_start_linux(enable)
27
+
28
+ def _set_auto_start_windows(
29
+ self,
30
+ enable: bool,
31
+ ):
32
+ key_path = r'Software\Microsoft\Windows\CurrentVersion\Run'
33
+ try:
34
+ key = reg.OpenKey(
35
+ reg.HKEY_CURRENT_USER,
36
+ key_path,
37
+ 0,
38
+ reg.KEY_ALL_ACCESS,
39
+ )
40
+ if enable:
41
+ reg.SetValueEx(
42
+ key,
43
+ self.app_name,
44
+ 0,
45
+ reg.REG_SZ,
46
+ self.app_path,
47
+ )
48
+ else:
49
+ reg.DeleteValue(
50
+ key,
51
+ self.app_name,
52
+ )
53
+ reg.CloseKey(key)
54
+ return True
55
+ except WindowsError:
56
+ return False
57
+
58
+ def _set_auto_start_macos(
59
+ self,
60
+ enable: bool,
61
+ ):
62
+ plist_path = os.path.expanduser(f'~/Library/LaunchAgents/com.{self.app_name}.plist')
63
+ plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
64
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
65
+ <plist version="1.0">
66
+ <dict>
67
+ <key>Label</key>
68
+ <string>com.{self.app_name}</string>
69
+ <key>ProgramArguments</key>
70
+ <array>
71
+ <string>{self.app_path}</string>
72
+ </array>
73
+ <key>RunAtLoad</key>
74
+ <true/>
75
+ <key>KeepAlive</key>
76
+ <false/>
77
+ </dict>
78
+ </plist>
79
+ """
80
+ try:
81
+ if enable:
82
+ os.makedirs(
83
+ os.path.dirname(plist_path),
84
+ exist_ok=True,
85
+ )
86
+ with open(
87
+ plist_path,
88
+ 'w',
89
+ ) as f:
90
+ f.write(plist_content)
91
+ os.chmod(
92
+ plist_path,
93
+ 0o644,
94
+ )
95
+ else:
96
+ if os.path.exists(plist_path):
97
+ os.remove(plist_path)
98
+ return True
99
+ except (
100
+ IOError,
101
+ OSError,
102
+ ) as e:
103
+ print(f'Error setting auto start on macOS: {e}')
104
+ return False
105
+
106
+ def _set_auto_start_linux(
107
+ self,
108
+ enable: bool,
109
+ ):
110
+ autostart_dir = os.path.expanduser('~/.config/autostart')
111
+ desktop_file_path = os.path.join(
112
+ autostart_dir,
113
+ f'{self.app_name}.desktop',
114
+ )
115
+ desktop_content = f"""[Desktop Entry]
116
+ Type=Application
117
+ Exec={self.app_path}
118
+ Hidden=false
119
+ NoDisplay=false
120
+ X-GNOME-Autostart-enabled=true
121
+ Name={self.app_name}
122
+ Comment=Pylon Application
123
+ """
124
+ if enable:
125
+ os.makedirs(
126
+ autostart_dir,
127
+ exist_ok=True,
128
+ )
129
+ with open(
130
+ desktop_file_path,
131
+ 'w',
132
+ ) as f:
133
+ f.write(desktop_content)
134
+ else:
135
+ if os.path.exists(desktop_file_path):
136
+ os.remove(desktop_file_path)
137
+
138
+ def is_auto_start(
139
+ self,
140
+ ):
141
+ if sys.platform == 'win32':
142
+ key_path = r'Software\Microsoft\Windows\CurrentVersion\Run'
143
+ try:
144
+ key = reg.OpenKey(
145
+ reg.HKEY_CURRENT_USER,
146
+ key_path,
147
+ 0,
148
+ reg.KEY_READ,
149
+ )
150
+ reg.QueryValueEx(
151
+ key,
152
+ self.app_name,
153
+ )
154
+ reg.CloseKey(key)
155
+ return True
156
+ except WindowsError:
157
+ return False
158
+ elif sys.platform == 'darwin':
159
+ plist_path = os.path.expanduser(f'~/Library/LaunchAgents/com.{self.app_name}.plist')
160
+ return os.path.exists(plist_path)
161
+ elif sys.platform.startswith('linux'):
162
+ desktop_file_path = os.path.expanduser(f'~/.config/autostart/{self.app_name}.desktop')
163
+ return os.path.exists(desktop_file_path)
164
+ return False
@@ -0,0 +1,395 @@
1
+ from typing import (
2
+ TYPE_CHECKING,
3
+ Optional,
4
+ )
5
+
6
+ from ..ipc import (
7
+ PyloidIPC,
8
+ Bridge,
9
+ )
10
+ from PySide6.QtCore import (
11
+ QByteArray,
12
+ QBuffer,
13
+ QIODeviceBase,
14
+ )
15
+ import base64
16
+ from ..utils import (
17
+ get_platform,
18
+ is_production,
19
+ get_production_path,
20
+ )
21
+
22
+ if TYPE_CHECKING:
23
+ from ..pyloid import (
24
+ _Pyloid,
25
+ )
26
+
27
+
28
+ class BaseIPC(PyloidIPC):
29
+ def __init__(
30
+ self,
31
+ window_id: str,
32
+ data: dict,
33
+ app: '_Pyloid',
34
+ server_url: Optional[str] = None,
35
+ ):
36
+ super().__init__()
37
+ self.window_id: str = window_id
38
+ self.data: dict = data
39
+ self.app: '_Pyloid' = app
40
+ self.server_url: Optional[str] = server_url
41
+
42
+ @Bridge(result=dict)
43
+ def getData(
44
+ self,
45
+ ):
46
+ """Returns the shared data of the application."""
47
+ return self.data
48
+
49
+ @Bridge()
50
+ def startSystemDrag(
51
+ self,
52
+ ):
53
+ """Starts the system drag."""
54
+ window = self.app.get_window_by_id(self.window_id)
55
+ if window:
56
+ window._window.web_view.start_system_drag()
57
+
58
+ @Bridge(result=str)
59
+ def getWindowId(
60
+ self,
61
+ ):
62
+ """Returns the current window ID."""
63
+ return self.window_id
64
+
65
+ @Bridge(result=dict)
66
+ def getWindowProperties(
67
+ self,
68
+ ):
69
+ """Returns the properties of the window."""
70
+ window = self.app.get_window_by_id(self.window_id)
71
+ window_properties = window._window.get_window_properties()
72
+ return window_properties
73
+
74
+ @Bridge()
75
+ def close(
76
+ self,
77
+ ):
78
+ """Closes the window."""
79
+ window = self.app.get_window_by_id(self.window_id)
80
+ if window:
81
+ window._window.close()
82
+
83
+ @Bridge()
84
+ def hide(
85
+ self,
86
+ ):
87
+ """Hides the window."""
88
+ window = self.app.get_window_by_id(self.window_id)
89
+ if window:
90
+ window._window.hide()
91
+
92
+ @Bridge()
93
+ def show(
94
+ self,
95
+ ):
96
+ """Shows and focuses the window."""
97
+ window = self.app.get_window_by_id(self.window_id)
98
+ if window:
99
+ window._window.show()
100
+
101
+ @Bridge()
102
+ def focus(
103
+ self,
104
+ ):
105
+ """Focuses the window."""
106
+ window = self.app.get_window_by_id(self.window_id)
107
+ if window:
108
+ window._window.focus()
109
+
110
+ @Bridge()
111
+ def showAndFocus(
112
+ self,
113
+ ):
114
+ """Shows and focuses the window."""
115
+ window = self.app.get_window_by_id(self.window_id)
116
+ if window:
117
+ window._window.show_and_focus()
118
+
119
+ @Bridge()
120
+ def fullscreen(
121
+ self,
122
+ ):
123
+ """Enters fullscreen mode."""
124
+ window = self.app.get_window_by_id(self.window_id)
125
+ if window:
126
+ window._window.fullscreen()
127
+
128
+ @Bridge()
129
+ def toggleFullscreen(
130
+ self,
131
+ ):
132
+ """Toggles fullscreen mode for the window."""
133
+ window = self.app.get_window_by_id(self.window_id)
134
+ if window:
135
+ window._window.toggle_fullscreen()
136
+
137
+ @Bridge()
138
+ def minimize(
139
+ self,
140
+ ):
141
+ """Minimizes the window."""
142
+ window = self.app.get_window_by_id(self.window_id)
143
+ if window:
144
+ window._window.minimize()
145
+
146
+ @Bridge()
147
+ def maximize(
148
+ self,
149
+ ):
150
+ """Maximizes the window."""
151
+ window = self.app.get_window_by_id(self.window_id)
152
+ if window:
153
+ window._window.maximize()
154
+
155
+ @Bridge()
156
+ def unmaximize(
157
+ self,
158
+ ):
159
+ """Restores the window to its normal state."""
160
+ window = self.app.get_window_by_id(self.window_id)
161
+ if window:
162
+ window._window.unmaximize()
163
+
164
+ @Bridge()
165
+ def toggleMaximize(
166
+ self,
167
+ ):
168
+ """Toggles the maximized state of the window."""
169
+ window = self.app.get_window_by_id(self.window_id)
170
+ if window:
171
+ window._window.toggle_maximize()
172
+
173
+ @Bridge(result=bool)
174
+ def isFullscreen(
175
+ self,
176
+ ):
177
+ """Returns True if the window is fullscreen."""
178
+ window = self.app.get_window_by_id(self.window_id)
179
+ return window._window.is_fullscreen()
180
+
181
+ @Bridge(result=bool)
182
+ def isMaximized(
183
+ self,
184
+ ):
185
+ """Returns True if the window is maximized."""
186
+ window = self.app.get_window_by_id(self.window_id)
187
+ return window._window.is_maximized()
188
+
189
+ @Bridge(str)
190
+ def setTitle(
191
+ self,
192
+ title: str,
193
+ ):
194
+ """Sets the title of the window."""
195
+ window = self.app.get_window_by_id(self.window_id)
196
+ if window:
197
+ window._window.set_title(title)
198
+
199
+ @Bridge(
200
+ int,
201
+ int,
202
+ )
203
+ def setSize(
204
+ self,
205
+ width: int,
206
+ height: int,
207
+ ):
208
+ """Sets the size of the window."""
209
+ window = self.app.get_window_by_id(self.window_id)
210
+ if window:
211
+ window._window.set_size(
212
+ width,
213
+ height,
214
+ )
215
+
216
+ @Bridge(
217
+ int,
218
+ int,
219
+ )
220
+ def setPosition(
221
+ self,
222
+ x: int,
223
+ y: int,
224
+ ):
225
+ """Sets the position of the window."""
226
+ window = self.app.get_window_by_id(self.window_id)
227
+ if window:
228
+ window._window.set_position(
229
+ x,
230
+ y,
231
+ )
232
+
233
+ @Bridge(bool)
234
+ def setFrame(
235
+ self,
236
+ frame: bool,
237
+ ):
238
+ """Sets the frame of the window."""
239
+ window = self.app.get_window_by_id(self.window_id)
240
+ if window:
241
+ window._window.set_frame(frame)
242
+
243
+ @Bridge(result=bool)
244
+ def getFrame(
245
+ self,
246
+ ):
247
+ """Returns whether the window has a frame."""
248
+ window = self.app.get_window_by_id(self.window_id)
249
+ return window._window.frame if window else False
250
+
251
+ @Bridge(result=str)
252
+ def getTitle(
253
+ self,
254
+ ):
255
+ """Returns the title of the window."""
256
+ window = self.app.get_window_by_id(self.window_id)
257
+ return window._window.title if window else ''
258
+
259
+ @Bridge(result=dict)
260
+ def getSize(
261
+ self,
262
+ ):
263
+ """Returns the size of the window."""
264
+ window = self.app.get_window_by_id(self.window_id)
265
+ size = window.get_size()
266
+ return (
267
+ size
268
+ if window
269
+ else {
270
+ 'width': 0,
271
+ 'height': 0,
272
+ }
273
+ )
274
+
275
+ @Bridge(result=dict)
276
+ def getPosition(
277
+ self,
278
+ ):
279
+ """Returns the position of the window."""
280
+ window = self.app.get_window_by_id(self.window_id)
281
+ pos = window.get_position()
282
+ return (
283
+ pos
284
+ if window
285
+ else {
286
+ 'x': 0,
287
+ 'y': 0,
288
+ }
289
+ )
290
+
291
+ ###############################################################
292
+ # Clipboard
293
+ ###############################################################
294
+
295
+ @Bridge(str)
296
+ def setClipboardText(
297
+ self,
298
+ text: str,
299
+ ):
300
+ """Sets the text to the clipboard."""
301
+ self.app.set_clipboard_text(text)
302
+
303
+ @Bridge(result=str)
304
+ def getClipboardText(
305
+ self,
306
+ ):
307
+ """Gets the text from the clipboard."""
308
+ return self.app.get_clipboard_text()
309
+
310
+ @Bridge(
311
+ str,
312
+ str,
313
+ )
314
+ def setClipboardImage(
315
+ self,
316
+ image_path: str,
317
+ format: str,
318
+ ):
319
+ """Sets the image to the clipboard."""
320
+ self.app.set_clipboard_image(
321
+ image_path,
322
+ format,
323
+ )
324
+
325
+ @Bridge(result=str)
326
+ def getClipboardImage(
327
+ self,
328
+ ):
329
+ """Returns the clipboard image as a Base64 encoded data URL."""
330
+ image = self.app.get_clipboard_image() # Assuming it returns QImage
331
+ if image and not image.isNull():
332
+ # Convert QImage to byte array
333
+ byte_array = QByteArray()
334
+ buffer = QBuffer(byte_array)
335
+ buffer.open(QIODeviceBase.WriteOnly)
336
+ image.save(
337
+ buffer,
338
+ 'PNG',
339
+ ) # Save in PNG format
340
+
341
+ # Encode to Base64
342
+ base64_data = byte_array.toBase64().data().decode()
343
+ return f'data:image/png;base64,{base64_data}'
344
+ return ''
345
+
346
+ ###########################################################################################
347
+ # Quit
348
+ ###########################################################################################
349
+ @Bridge()
350
+ def quit(
351
+ self,
352
+ ):
353
+ """Quits the application."""
354
+ self.app.quit()
355
+
356
+ ###########################################################################################
357
+ # Utils
358
+ ###########################################################################################
359
+ @Bridge(result=str)
360
+ def getPlatform(
361
+ self,
362
+ ):
363
+ """Returns the platform of the application.
364
+
365
+ Returns
366
+ -------
367
+ str
368
+ The platform of the application (windows, linux, macos)
369
+ """
370
+ return get_platform()
371
+
372
+ @Bridge(result=bool)
373
+ def isProduction(
374
+ self,
375
+ ):
376
+ """Returns True if the application is in production mode."""
377
+ return is_production()
378
+
379
+ @Bridge(
380
+ str,
381
+ result=str,
382
+ )
383
+ def getProductionPath(
384
+ self,
385
+ path: str,
386
+ ):
387
+ """Returns the production path of the application."""
388
+ return get_production_path(path)
389
+
390
+ @Bridge(result=str)
391
+ def getServerUrl(
392
+ self,
393
+ ):
394
+ """Returns the RPC URL of the application."""
395
+ return self.server_url
@@ -22,4 +22,4 @@
22
22
  # """다른 윈도우로 특정 이벤트를 보냅니다."""
23
23
  # if event_name in self.subscribers:
24
24
  # for callback in self.subscribers[event_name]:
25
- # callback(*args, **kwargs)
25
+ # callback(*args, **kwargs)