pyloid 0.20.2.dev0__py3-none-any.whl → 0.21.0.dev1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
pyloid/browser_window.py CHANGED
@@ -28,15 +28,18 @@ from .custom.titlebar import CustomTitleBar
28
28
  from .js_api.window_api import WindowAPI
29
29
  from PySide6.QtGui import QPixmap, QMovie
30
30
  from PySide6.QtWidgets import QSplashScreen, QLabel
31
- from PySide6.QtCore import QSize
32
31
  from typing import TYPE_CHECKING
33
- from PySide6.QtWebEngineCore import QWebEngineSettings
32
+ from PySide6.QtWebEngineCore import (
33
+ QWebEngineSettings,
34
+ QWebEngineDesktopMediaRequest,
35
+ QWebEngineUrlRequestInterceptor,
36
+ )
37
+ from .utils import get_production_path, is_production
34
38
 
35
39
  if TYPE_CHECKING:
36
40
  from ..pyloid import Pyloid
37
41
 
38
42
 
39
- # 어차피 load 부분에만 쓰이니까 나중에 분리해서 load 위에서 선언하자.
40
43
  class CustomWebPage(QWebEnginePage):
41
44
  def __init__(self, profile=None):
42
45
  super().__init__(profile)
@@ -47,11 +50,11 @@ class CustomWebPage(QWebEnginePage):
47
50
  self._url_handlers = {} # URL 핸들러 저장을 위한 딕셔너리 추가
48
51
 
49
52
  # interceptor ( all url request )
50
- self.interceptor = CustomUrlInterceptor()
51
- self.profile().setUrlRequestInterceptor(self.interceptor)
53
+ # self.interceptor = CustomUrlInterceptor()
54
+ # self.profile().setUrlRequestInterceptor(self.interceptor)
52
55
 
53
56
  def _handlePermissionRequest(self, origin: QUrl, feature: QWebEnginePage.Feature):
54
- print(origin, feature)
57
+ # print(origin, feature)
55
58
 
56
59
  """Default permission request handler"""
57
60
  if feature in self._permission_handlers:
@@ -68,37 +71,47 @@ class CustomWebPage(QWebEnginePage):
68
71
  """Register a handler for a specific permission"""
69
72
  self._permission_handlers[feature] = handler
70
73
 
71
- def _handleDesktopMediaRequest(self, *args, **kwargs):
72
- print("Desktop media request received:", args, kwargs)
74
+ def _handleDesktopMediaRequest(self, request: QWebEngineDesktopMediaRequest):
75
+ print("Desktop media request received:", request)
76
+
77
+ # 사용 가능한 화면 목록 확인
78
+ screens_model = request.screensModel()
79
+ print("\n=== Available Screens ===")
80
+ for i in range(screens_model.rowCount()):
81
+ screen_index = screens_model.index(i)
82
+ screen_name = screens_model.data(screen_index)
83
+ print(f"Screen {i}: {screen_name}")
84
+
85
+ # 사용 가능한 창 목록 확인
86
+ windows_model = request.windowsModel()
87
+ print("\n=== Available Windows ===")
88
+ for i in range(windows_model.rowCount()):
89
+ window_index = windows_model.index(i)
90
+ window_name = windows_model.data(window_index)
91
+ print(f"Window {i}: {window_name}")
92
+
93
+ request.selectWindow(windows_model.index(3))
73
94
 
74
95
  # interceptor ( navigation request )
75
96
  def acceptNavigationRequest(self, url, navigation_type, is_main_frame):
76
97
  """네비게이션 요청을 처리하는 메서드"""
77
- print(f"Navigation Request - URL: {url.toString()}")
98
+ url_string = url.toString()
99
+ print(f"Navigation Request - URL: {url_string}")
78
100
  print(f"Navigation Type: {navigation_type}")
79
101
  print(f"Is Main Frame: {is_main_frame}")
80
102
 
81
- # # URL이 구글이 아닐 경우에만 구글로 리다이렉트
82
- # if "example.com" not in url.toString():
83
- # self.setUrl(QUrl("https://www.example.com"))
84
- # return False
103
+ # file:// 프로토콜 처리
104
+ if url.scheme() == "file":
105
+ # 파일 경로에서 file:/// 제거
106
+ file_path = url_string.replace("file:///", "").rstrip("/")
85
107
 
86
- return True
108
+ # HTML 파일이 아닌 경우에만 index.html로 리다이렉트
109
+ if not file_path.endswith(".html"):
110
+ base_path = os.path.dirname(file_path)
111
+ self.setUrl(QUrl.fromLocalFile(os.path.join(base_path, "index.html")))
112
+ return False
87
113
 
88
- def add_url_handler(self, pattern: str, handler):
89
- """URL 패턴에 대한 핸들러 등록
90
-
91
- Parameters:
92
- -----------
93
- pattern : str
94
- 정규표현식 패턴
95
- handler : callable
96
- URL을 인자로 받고 bool을 반환해야 함
97
- True를 반환하면 네비게이션을 허용, False를 반환하면 차단
98
- """
99
- import re
100
-
101
- self._url_handlers[re.compile(pattern)] = handler
114
+ return True
102
115
 
103
116
 
104
117
  # interceptor ( all url request )
@@ -108,6 +121,50 @@ class CustomUrlInterceptor(QWebEngineUrlRequestInterceptor):
108
121
  print(url)
109
122
 
110
123
 
124
+ # class CustomInterceptor(QWebEngineUrlRequestInterceptor):
125
+ # def __init__(self, index_path=None):
126
+ # super().__init__()
127
+ # self.index_path = get_production_path()
128
+ # self.last_path = "/"
129
+
130
+ # def interceptRequest(self, info):
131
+ # url = info.requestUrl()
132
+ # navigation_type = info.navigationType()
133
+
134
+ # print("--------------------------------")
135
+
136
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeTyped:
137
+ # print("NavigationTypeTyped")
138
+
139
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeReload:
140
+ # print("NavigationTypeReload")
141
+
142
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeBackForward:
143
+ # print("NavigationTypeBackForward")
144
+
145
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeLinkClicked:
146
+ # print("NavigationTypeLinkClicked")
147
+
148
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeFormSubmitted:
149
+ # print("NavigationTypeFormSubmitted")
150
+
151
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeTyped:
152
+ # print("NavigationTypeTyped")
153
+
154
+ # if navigation_type == QWebEnginePage.NavigationType.NavigationTypeOther:
155
+ # print("NavigationTypeOther")
156
+
157
+ # print(navigation_type.value)
158
+
159
+ # print(url)
160
+ # print(url.scheme())
161
+ # print(url.host())
162
+ # print(url.url())
163
+ # print(self.last_path)
164
+
165
+ # self.last_path = url.path()
166
+
167
+
111
168
  class CustomWebEngineView(QWebEngineView):
112
169
  def __init__(self, parent: "BrowserWindow" = None):
113
170
  super().__init__(parent._window)
@@ -433,6 +490,13 @@ class BrowserWindow:
433
490
  # Set F12 shortcut
434
491
  self.set_dev_tools(self.dev_tools)
435
492
 
493
+ # 프로필 가져오기 및 인터셉터 설정
494
+ profile = self.web_view.page().profile()
495
+
496
+ # # 기존 인터셉터가 있다면 제거
497
+ # if self.interceptor:
498
+ # profile.setUrlRequestInterceptor(None)
499
+
436
500
  def _on_load_finished(self, ok):
437
501
  """Handles the event when the web page finishes loading."""
438
502
  if ok and self.js_apis:
pyloid/builder/spec.py CHANGED
@@ -2,27 +2,30 @@ from pyloid.utils import get_platform
2
2
  import json
3
3
  from pathlib import Path
4
4
 
5
+
5
6
  def create_spec_from_json(json_path):
6
- with open(json_path, 'r', encoding='utf-8') as f:
7
+ with open(json_path, "r", encoding="utf-8") as f:
7
8
  config = json.load(f)
8
9
 
9
10
  os_type = get_platform()
10
-
11
- if os_type == 'macos':
11
+
12
+ if os_type == "macos":
12
13
  spec_content = _create_macos_spec(config)
13
- elif os_type == 'linux':
14
+ elif os_type == "linux":
14
15
  spec_content = _create_linux_spec(config)
15
16
  else: # windows
16
17
  spec_content = _create_windows_spec(config)
17
-
18
+
18
19
  spec_path = Path(f"build-{os_type}.spec")
19
- spec_path.write_text(spec_content, encoding='utf-8')
20
-
20
+ spec_path.write_text(spec_content, encoding="utf-8")
21
+
21
22
  return str(spec_path)
22
23
 
24
+
23
25
  def _create_windows_spec(config):
24
- bundle_type = config.get('bundle', {}).get('windows', 'directory')
25
-
26
+ bundle_type = config.get("bundle", {}).get("windows", "directory")
27
+ console = config.get("console", False)
28
+
26
29
  base_spec = f"""# -*- mode: python ; coding: utf-8 -*-
27
30
 
28
31
  block_cipher = None
@@ -47,8 +50,10 @@ pyz = PYZ(a.pure, a.zipped_data,
47
50
  cipher=block_cipher)
48
51
  """
49
52
 
50
- if bundle_type == 'onefile':
51
- return base_spec + f"""
53
+ if bundle_type == "onefile":
54
+ return (
55
+ base_spec
56
+ + f"""
52
57
  exe = EXE(
53
58
  pyz,
54
59
  a.scripts,
@@ -63,7 +68,7 @@ exe = EXE(
63
68
  upx=True,
64
69
  upx_exclude=[],
65
70
  runtime_tmpdir=None,
66
- console=False,
71
+ console={console},
67
72
  disable_windowed_traceback=False,
68
73
  argv_emulation=False,
69
74
  target_arch=None,
@@ -72,8 +77,11 @@ exe = EXE(
72
77
  icon='{config.get('icon', 'src-pyloid/icons/icon.ico')}'
73
78
  )
74
79
  """
80
+ )
75
81
  else:
76
- return base_spec + f"""
82
+ return (
83
+ base_spec
84
+ + f"""
77
85
  exe = EXE(
78
86
  pyz,
79
87
  a.scripts,
@@ -84,7 +92,7 @@ exe = EXE(
84
92
  bootloader_ignore_signals=False,
85
93
  strip=False,
86
94
  upx=True,
87
- console=False,
95
+ console={console},
88
96
  disable_windowed_traceback=False,
89
97
  argv_emulation=False,
90
98
  target_arch=None,
@@ -104,8 +112,11 @@ coll = COLLECT(
104
112
  name='{config.get("name", "pyloid-app")}'
105
113
  )
106
114
  """
115
+ )
116
+
107
117
 
108
118
  def _create_macos_spec(config):
119
+ console = config.get("console", False)
109
120
  return f"""# -*- mode: python ; coding: utf-8 -*-
110
121
 
111
122
  a = Analysis(
@@ -134,7 +145,7 @@ exe = EXE(
134
145
  bootloader_ignore_signals=False,
135
146
  strip=False,
136
147
  upx=True,
137
- console=False,
148
+ console={console},
138
149
  disable_windowed_traceback=False,
139
150
  argv_emulation=False,
140
151
  target_arch=None,
@@ -161,9 +172,11 @@ app = BUNDLE(
161
172
  )
162
173
  """
163
174
 
175
+
164
176
  def _create_linux_spec(config):
165
- bundle_type = config.get('bundle', {}).get('linux', 'directory')
166
-
177
+ bundle_type = config.get("bundle", {}).get("linux", "directory")
178
+ console = config.get("console", False)
179
+
167
180
  base_spec = f"""# -*- mode: python ; coding: utf-8 -*-
168
181
 
169
182
  block_cipher = None
@@ -188,8 +201,10 @@ pyz = PYZ(a.pure, a.zipped_data,
188
201
  cipher=block_cipher)
189
202
  """
190
203
 
191
- if bundle_type == 'onefile':
192
- return base_spec + f"""
204
+ if bundle_type == "onefile":
205
+ return (
206
+ base_spec
207
+ + f"""
193
208
  exe = EXE(
194
209
  pyz,
195
210
  a.scripts,
@@ -204,7 +219,7 @@ exe = EXE(
204
219
  upx=True,
205
220
  upx_exclude=[],
206
221
  runtime_tmpdir=None,
207
- console=False,
222
+ console={console},
208
223
  disable_windowed_traceback=False,
209
224
  argv_emulation=False,
210
225
  target_arch=None,
@@ -213,8 +228,11 @@ exe = EXE(
213
228
  icon='{config.get('icon', 'src-pyloid/icons/icon.png')}'
214
229
  )
215
230
  """
231
+ )
216
232
  else:
217
- return base_spec + f"""
233
+ return (
234
+ base_spec
235
+ + f"""
218
236
  exe = EXE(
219
237
  pyz,
220
238
  a.scripts,
@@ -225,7 +243,7 @@ exe = EXE(
225
243
  bootloader_ignore_signals=False,
226
244
  strip=False,
227
245
  upx=True,
228
- console=False,
246
+ console={console},
229
247
  disable_windowed_traceback=False,
230
248
  argv_emulation=False,
231
249
  target_arch=None,
@@ -244,4 +262,5 @@ coll = COLLECT(
244
262
  upx_exclude=[],
245
263
  name='{config.get("name", "pyloid-app")}'
246
264
  )
247
- """
265
+ """
266
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyloid
3
- Version: 0.20.2.dev0
3
+ Version: 0.21.0.dev1
4
4
  Summary:
5
5
  Author: aesthetics-of-record
6
6
  Author-email: 111675679+aesthetics-of-record@users.noreply.github.com
@@ -11,8 +11,8 @@ Classifier: Programming Language :: Python :: 3.10
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
- Requires-Dist: pyinstaller (>=6.11.1,<7.0.0)
15
- Requires-Dist: pyside6 (>=6.8.1,<7.0.0)
14
+ Requires-Dist: pyinstaller (>=6.12.0,<7.0.0)
15
+ Requires-Dist: pyside6 (>=6.8.2.1,<7.0.0.0)
16
16
  Description-Content-Type: text/markdown
17
17
 
18
18
  # Pyloid 👋
@@ -1,10 +1,10 @@
1
1
  pyloid/__init__.py,sha256=t1_67LkSfP4F1TYq4-62z5Cc3Gx1jyWI1yXux7Ojaug,484
2
2
  pyloid/api.py,sha256=A61Kmddh8BlpT3LfA6NbPQNzFmD95vQ4WKX53oKsGYU,2419
3
3
  pyloid/autostart.py,sha256=K7DQYl4LHItvPp0bt1V9WwaaZmVSTeGvadkcwG-KKrI,3899
4
- pyloid/browser_window.py,sha256=d9_h7URbECbNgRxqEjFAkbiZfso0oQ0v3RZXnzYTqN4,64228
4
+ pyloid/browser_window.py,sha256=bSxi8LnAIePF6-u7CFttgEatq6dKHLc405H2QBOQXh4,66702
5
5
  pyloid/builder/__init__.py,sha256=nw0r2RXqZ6eEbSbVF44sHD7NXovMShujxpTwygXXlrY,2889
6
6
  pyloid/builder/build_config.schema.json,sha256=Wj4_RCxXrQE9lq9Qxen1oy1Q0lhi2ojDkln8YX_LntM,2213
7
- pyloid/builder/spec.py,sha256=2nkVNH-gu91U1oPxljQc-_1nYtZtsMNgKkt1OFztK7g,6123
7
+ pyloid/builder/spec.py,sha256=KuAnqO5CdJyzNbU5dmEGoq_dpHA9HW2U2Cj77Cd6uKI,6421
8
8
  pyloid/custom/titlebar.py,sha256=itzK9pJbZMQ7BKca9kdbuHMffurrw15UijR6OU03Xsk,3894
9
9
  pyloid/filewatcher.py,sha256=3M5zWVUf1OhlkWJcDFC8ZA9agO4Q-U8WdgGpy6kaVz0,4601
10
10
  pyloid/js_api/event_api.py,sha256=_52yyBonqecmMvJpFW7OMNi_jX8Nrteqw_kI6r-DGG0,951
@@ -15,7 +15,7 @@ pyloid/thread_pool.py,sha256=fKOBb8jMfZn_7crA_fJCno8dObBRZE31EIWaNQ759aw,14616
15
15
  pyloid/timer.py,sha256=RqMsChFUd93cxMVgkHWiIKrci0QDTBgJSTULnAtYT8M,8712
16
16
  pyloid/tray.py,sha256=D12opVEc2wc2T4tK9epaN1oOdeziScsIVNM2uCN7C-A,1710
17
17
  pyloid/utils.py,sha256=mAjuppRXlZAocggf8La00Ae0Qzi4IRL_ovG87x4wagI,3300
18
- pyloid-0.20.2.dev0.dist-info/LICENSE,sha256=MTYF-6xpRekyTUglRweWtbfbwBL1I_3Bgfbm_SNOuI8,11525
19
- pyloid-0.20.2.dev0.dist-info/METADATA,sha256=3V1NT6igjaUCGKUt7ArRoE7IRYZSrZzuJICzqLbjw30,3112
20
- pyloid-0.20.2.dev0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
21
- pyloid-0.20.2.dev0.dist-info/RECORD,,
18
+ pyloid-0.21.0.dev1.dist-info/LICENSE,sha256=MTYF-6xpRekyTUglRweWtbfbwBL1I_3Bgfbm_SNOuI8,11525
19
+ pyloid-0.21.0.dev1.dist-info/METADATA,sha256=6bh7zmaYT4vlwI13WvqxaoGU8hxLlQc6V2I36EuOFog,3116
20
+ pyloid-0.21.0.dev1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
21
+ pyloid-0.21.0.dev1.dist-info/RECORD,,