pyloid 0.16.2__py3-none-any.whl → 0.16.5__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
@@ -25,13 +25,47 @@ from .js_api.window_api import WindowAPI
25
25
  from PySide6.QtGui import QPixmap, QMovie
26
26
  from PySide6.QtWidgets import QSplashScreen, QLabel
27
27
  from PySide6.QtCore import QSize
28
+ from typing import TYPE_CHECKING
29
+ from PySide6.QtWebEngineCore import QWebEngineSettings
30
+
31
+ if TYPE_CHECKING:
32
+ from ..pyloid import Pyloid
28
33
 
29
34
 
30
35
  # 어차피 load 부분에만 쓰이니까 나중에 분리해서 load 위에서 선언하자.
36
+ class CustomWebPage(QWebEnginePage):
37
+ def __init__(self, profile=None):
38
+ super().__init__(profile)
39
+ # 권한 요청 시그널 연결
40
+ self.featurePermissionRequested.connect(self._handlePermissionRequest)
41
+ self._permission_handlers = {}
42
+
43
+ def _handlePermissionRequest(self, origin: QUrl, feature: QWebEnginePage.Feature):
44
+ """기본 권한 요청 핸들러"""
45
+ if feature in self._permission_handlers:
46
+ # 등록된 핸들러가 있으면 실행
47
+ handler = self._permission_handlers[feature]
48
+ handler(origin, feature)
49
+ else:
50
+ # 기본적으로 모든 권한 허용
51
+ self.setFeaturePermission(
52
+ origin, feature, QWebEnginePage.PermissionPolicy.PermissionGrantedByUser
53
+ )
54
+
55
+ def setPermissionHandler(self, feature: QWebEnginePage.Feature, handler):
56
+ """특정 권한에 대한 핸들러 등록"""
57
+ self._permission_handlers[feature] = handler
58
+
59
+
31
60
  class CustomWebEngineView(QWebEngineView):
32
61
  def __init__(self, parent=None):
33
62
  super().__init__(parent._window)
34
63
  self.parent = parent
64
+
65
+ # 커스텀 웹 페이지 설정
66
+ self.custom_page = CustomWebPage()
67
+ self.setPage(self.custom_page)
68
+
35
69
  self.drag_relative_position = None
36
70
  self.is_dragging = False
37
71
  self.is_resizing = False
@@ -164,7 +198,7 @@ class CustomWebEngineView(QWebEngineView):
164
198
  class BrowserWindow:
165
199
  def __init__(
166
200
  self,
167
- app,
201
+ app: "Pyloid",
168
202
  title: str = "pyloid app",
169
203
  width: int = 800,
170
204
  height: int = 600,
@@ -195,6 +229,8 @@ class BrowserWindow:
195
229
  for js_api in js_apis:
196
230
  self.js_apis.append(js_api)
197
231
  self.shortcuts = {}
232
+ self.close_on_load = True
233
+ self.splash_screen = None
198
234
  ###########################################################################################
199
235
 
200
236
  def _set_custom_frame(
@@ -289,13 +325,13 @@ class BrowserWindow:
289
325
  def _on_load_finished(self, ok):
290
326
  """Handles the event when the web page finishes loading."""
291
327
  if ok and self.js_apis:
292
-
293
328
  # Load qwebchannel.js
294
329
  qwebchannel_js = QFile("://qtwebchannel/qwebchannel.js")
295
330
  if qwebchannel_js.open(QFile.ReadOnly):
296
331
  source = bytes(qwebchannel_js.readAll()).decode("utf-8")
297
332
  self.web_view.page().runJavaScript(source)
298
333
  qwebchannel_js.close()
334
+
299
335
 
300
336
  js_code = """
301
337
  if (typeof QWebChannel !== 'undefined') {
@@ -327,6 +363,22 @@ class BrowserWindow:
327
363
  window.pyloid.WindowAPI.startSystemDrag();
328
364
  }
329
365
  });
366
+
367
+ function updateTheme(theme) {
368
+ document.documentElement.setAttribute(
369
+ 'data-pyloid-theme',
370
+ theme
371
+ );
372
+ }
373
+
374
+ // 테마 변경 이벤트 리스너
375
+ document.addEventListener('themeChange', (e) => {
376
+ console.log('themeChange event received:', e);
377
+ updateTheme(e.detail.theme);
378
+ });
379
+
380
+ updateTheme('%s');
381
+
330
382
 
331
383
  // Dispatch a custom event to signal that the initialization is ready
332
384
  const event = new CustomEvent('pyloidReady');
@@ -343,7 +395,7 @@ class BrowserWindow:
343
395
  for js_api in self.js_apis
344
396
  ]
345
397
  )
346
- self.web_view.page().runJavaScript(js_code % js_api_init)
398
+ self.web_view.page().runJavaScript(js_code % (js_api_init, self.app.theme))
347
399
 
348
400
  # if splash screen is set, close it when the page is loaded
349
401
  if self.close_on_load and self.splash_screen:
@@ -481,6 +533,57 @@ class BrowserWindow:
481
533
  self.y = y
482
534
  self._window.setGeometry(self.x, self.y, self.width, self.height)
483
535
 
536
+ def set_position_by_anchor(self, anchor: str):
537
+ """
538
+ Positions the window at a specific location on the screen.
539
+
540
+ Parameters
541
+ ----------
542
+ anchor : str
543
+ The anchor point indicating where to position the window.
544
+ Possible values: 'center', 'top', 'bottom', 'left', 'right',
545
+ 'top-left', 'top-right', 'bottom-left', 'bottom-right'
546
+
547
+ Examples
548
+ --------
549
+ >>> window.set_position_by_anchor('center')
550
+ >>> window.set_position_by_anchor('top-right')
551
+ """
552
+ screen = self.app.primaryScreen().availableGeometry()
553
+ window_size = self.get_size()
554
+
555
+ if anchor == "center":
556
+ x = (screen.width() - window_size["width"]) // 2
557
+ y = (screen.height() - window_size["height"]) // 2
558
+ elif anchor == "top":
559
+ x = (screen.width() - window_size["width"]) // 2
560
+ y = screen.top()
561
+ elif anchor == "bottom":
562
+ x = (screen.width() - window_size["width"]) // 2
563
+ y = screen.bottom() - window_size["height"]
564
+ elif anchor == "left":
565
+ x = screen.left()
566
+ y = (screen.height() - window_size["height"]) // 2
567
+ elif anchor == "right":
568
+ x = screen.right() - window_size["width"]
569
+ y = (screen.height() - window_size["height"]) // 2
570
+ elif anchor == "top-left":
571
+ x = screen.left()
572
+ y = screen.top()
573
+ elif anchor == "top-right":
574
+ x = screen.right() - window_size["width"]
575
+ y = screen.top()
576
+ elif anchor == "bottom-left":
577
+ x = screen.left()
578
+ y = screen.bottom() - window_size["height"]
579
+ elif anchor == "bottom-right":
580
+ x = screen.right() - window_size["width"]
581
+ y = screen.bottom() - window_size["height"]
582
+ else:
583
+ raise ValueError("Invalid anchor point.")
584
+
585
+ self.set_position(x, y)
586
+
484
587
  def set_frame(self, frame: bool):
485
588
  """
486
589
  Sets the frame of the window.
@@ -1322,6 +1425,26 @@ class BrowserWindow:
1322
1425
  """
1323
1426
  return self._window
1324
1427
 
1428
+ def get_QWebEngineView(self) -> CustomWebEngineView:
1429
+ """
1430
+ Returns the CustomWebEngineView object which inherits from QWebEngineView.
1431
+
1432
+ Returns
1433
+ -------
1434
+ CustomWebEngineView
1435
+ CustomWebEngineView object of the window
1436
+
1437
+ Examples
1438
+ --------
1439
+ ```python
1440
+ window = app.create_window("pyloid-window")
1441
+ web_view = window.get_QWebEngineView()
1442
+
1443
+ web_view.page().runJavaScript("console.log('Hello, Pyloid!')")
1444
+ ```
1445
+ """
1446
+ return self.web_view
1447
+
1325
1448
  ###########################################################################################
1326
1449
  # QMainWindow flags
1327
1450
  ###########################################################################################
@@ -1552,3 +1675,124 @@ class BrowserWindow:
1552
1675
  self.splash_screen.close()
1553
1676
  self.close_on_load = None
1554
1677
  self.splash_screen = None
1678
+
1679
+ ###########################################################################################
1680
+ # WebEngineView Attribute setting
1681
+ ###########################################################################################
1682
+ def set_web_engine_view_attribute(self, attribute: QWebEngineSettings, on: bool):
1683
+ """
1684
+ Sets the attribute of the WebEngineView.
1685
+
1686
+ Parameters
1687
+ ----------
1688
+ attribute : QWebEngineSettings
1689
+ Attribute to set
1690
+ on : bool
1691
+ True to enable the attribute, False to disable it
1692
+
1693
+ Examples
1694
+ --------
1695
+ ```python
1696
+ window.set_web_engine_view_attribute(QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard, False)
1697
+ ```
1698
+ """
1699
+ settings = self.web_view.settings()
1700
+ settings.setAttribute(attribute, on)
1701
+
1702
+ def is_web_engine_view_attribute(self, attribute: QWebEngineSettings) -> bool:
1703
+ """
1704
+ Returns the attribute of the WebEngineView.
1705
+
1706
+ Parameters
1707
+ ----------
1708
+ attribute : QWebEngineSettings
1709
+ Attribute to get
1710
+
1711
+ Returns
1712
+ -------
1713
+ bool
1714
+ True if the attribute is enabled, False otherwise
1715
+
1716
+ Examples
1717
+ --------
1718
+ ```python
1719
+ window.is_web_engine_view_attribute(QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard)
1720
+ ```
1721
+ """
1722
+ settings = self.web_view.settings()
1723
+ return settings.testAttribute(attribute)
1724
+
1725
+ def set_permission_handler(self, feature: QWebEnginePage.Feature, handler):
1726
+ """
1727
+ 특정 권한에 대한 핸들러를 설정합니다.
1728
+
1729
+ Parameters
1730
+ ----------
1731
+ feature : QWebEnginePage.Feature
1732
+ 설정할 권한 타입
1733
+ handler : callable
1734
+ 권한 요청을 처리할 핸들러 함수
1735
+
1736
+ Examples
1737
+ --------
1738
+ ```python
1739
+ def handle_camera(origin, feature):
1740
+ window.web_view.page().setFeaturePermission(
1741
+ origin,
1742
+ feature,
1743
+ QWebEnginePage.PermissionPolicy.PermissionGrantedByUser
1744
+ )
1745
+
1746
+ window.set_permission_handler(
1747
+ QWebEnginePage.Feature.MediaVideoCapture,
1748
+ handle_camera
1749
+ )
1750
+ ```
1751
+ """
1752
+ self.web_view.custom_page.setPermissionHandler(feature, handler)
1753
+
1754
+ def grant_permission(self, feature: QWebEnginePage.Feature):
1755
+ """
1756
+ 권한 요청이 왔을 때, 특정 권한을 자동으로 허용하도록 설정합니다.
1757
+
1758
+ Parameters
1759
+ ----------
1760
+ feature : QWebEnginePage.Feature
1761
+ 자동 허용할 권한 타입
1762
+
1763
+ Examples
1764
+ --------
1765
+ ```python
1766
+ window.grant_permission(QWebEnginePage.Feature.MediaVideoCapture)
1767
+ ```
1768
+ """
1769
+
1770
+ def auto_grant(origin, feat):
1771
+ self.web_view.page().setFeaturePermission(
1772
+ origin, feat, QWebEnginePage.PermissionPolicy.PermissionGrantedByUser
1773
+ )
1774
+
1775
+ self.set_permission_handler(feature, auto_grant)
1776
+
1777
+ def deny_permission(self, feature: QWebEnginePage.Feature):
1778
+ """
1779
+ 권한 요청이 왔을 때, 특정 권한을 자동으로 거부하도록 설정합니다.
1780
+
1781
+ Parameters
1782
+ ----------
1783
+ feature : QWebEnginePage.Feature
1784
+ 자동 거부할 권한 타입
1785
+
1786
+ Examples
1787
+ --------
1788
+ ```python
1789
+ window.deny_permission(QWebEnginePage.Feature.Notifications)
1790
+ ```
1791
+ """
1792
+
1793
+ def auto_deny(origin, feat):
1794
+ self.web_view.page().setFeaturePermission(
1795
+ origin, feat, QWebEnginePage.PermissionPolicy.PermissionDeniedByUser
1796
+ )
1797
+
1798
+ self.set_permission_handler(feature, auto_deny)
@@ -1,6 +1,7 @@
1
1
  from typing import TYPE_CHECKING, Optional
2
2
 
3
3
  from ..api import PyloidAPI, Bridge
4
+ from PySide6.QtCore import QByteArray, QBuffer, QIODeviceBase
4
5
 
5
6
  if TYPE_CHECKING:
6
7
  from ..pyloid import Pyloid
@@ -208,3 +209,38 @@ class WindowAPI(PyloidAPI):
208
209
  window = self.app.get_window_by_id(self.window_id)
209
210
  if window:
210
211
  window.web_view.start_system_drag()
212
+
213
+ ###############################################################
214
+ # Clipboard
215
+ ###############################################################
216
+
217
+ @Bridge(str)
218
+ def setClipboardText(self, text: str):
219
+ """Sets the text to the clipboard."""
220
+ self.app.set_clipboard_text(text)
221
+
222
+ @Bridge(result=str)
223
+ def getClipboardText(self):
224
+ """Gets the text from the clipboard."""
225
+ return self.app.get_clipboard_text()
226
+
227
+ @Bridge(str, str)
228
+ def setClipboardImage(self, image_path: str, format: str):
229
+ """Sets the image to the clipboard."""
230
+ self.app.set_clipboard_image(image_path, format)
231
+
232
+ @Bridge(result=str)
233
+ def getClipboardImage(self):
234
+ """클립보드의 이미지를 Base64 인코딩된 데이터 URL로 반환합니다."""
235
+ image = self.app.get_clipboard_image() # QImage 반환 가정
236
+ if image and not image.isNull():
237
+ # QImage를 바이트 배열로 변환
238
+ byte_array = QByteArray()
239
+ buffer = QBuffer(byte_array)
240
+ buffer.open(QIODeviceBase.WriteOnly)
241
+ image.save(buffer, "PNG") # PNG 형식으로 저장
242
+
243
+ # Base64로 인코딩
244
+ base64_data = byte_array.toBase64().data().decode()
245
+ return f"data:image/png;base64,{base64_data}"
246
+ return ""
pyloid/pyloid.py CHANGED
@@ -15,7 +15,7 @@ from PySide6.QtGui import (
15
15
  from PySide6.QtCore import Qt, Signal, QObject, QTimer
16
16
  from PySide6.QtNetwork import QLocalServer, QLocalSocket
17
17
  from .api import PyloidAPI
18
- from typing import List, Optional, Dict, Callable, Union
18
+ from typing import List, Optional, Dict, Callable, Union, Literal
19
19
  from PySide6.QtCore import qInstallMessageHandler
20
20
  import signal
21
21
  from .utils import is_production
@@ -25,6 +25,7 @@ from .filewatcher import FileWatcher
25
25
  import logging
26
26
  from .browser_window import BrowserWindow
27
27
  from .tray import TrayEvent
28
+ from PySide6.QtCore import QCoreApplication
28
29
 
29
30
  # for linux debug
30
31
  os.environ["QTWEBENGINE_DICTIONARIES_PATH"] = "/"
@@ -32,6 +33,11 @@ os.environ["QTWEBENGINE_DICTIONARIES_PATH"] = "/"
32
33
  # for macos debug
33
34
  logging.getLogger("Qt").setLevel(logging.ERROR)
34
35
 
36
+ QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling)
37
+ os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = (
38
+ "--enable-features=WebRTCPipeWireCapturer --ignore-certificate-errors --allow-insecure-localhost"
39
+ )
40
+
35
41
 
36
42
  def custom_message_handler(mode, context, message):
37
43
  if not hasattr(custom_message_handler, "vulkan_warning_shown") and (
@@ -56,6 +62,7 @@ def custom_message_handler(mode, context, message):
56
62
 
57
63
  qInstallMessageHandler(custom_message_handler)
58
64
 
65
+
59
66
  class _WindowController(QObject):
60
67
  create_window_signal = Signal(
61
68
  QApplication, str, int, int, int, int, bool, bool, bool, list
@@ -123,6 +130,51 @@ class Pyloid(QApplication):
123
130
  self.icon_frames = []
124
131
  self.current_frame = 0
125
132
 
133
+ self.theme = (
134
+ "dark"
135
+ if self.styleHints().colorScheme() == Qt.ColorScheme.Dark
136
+ else "light"
137
+ )
138
+
139
+ # Add color scheme tracking
140
+ self.styleHints().colorSchemeChanged.connect(self._handle_color_scheme_change)
141
+
142
+ # def set_theme(self, theme: Literal["system", "dark", "light"]):
143
+ # """
144
+ # 시스템의 테마를 설정합니다.
145
+
146
+ # Parameters
147
+ # ----------
148
+ # theme : Literal["system", "dark", "light"]
149
+ # 설정할 테마 ("system", "dark", "light" 중 하나)
150
+
151
+ # Examples
152
+ # --------
153
+ # >>> app = Pyloid(app_name="Pyloid-App")
154
+ # >>> app.set_theme("dark") # 다크 테마로 설정
155
+ # >>> app.set_theme("light") # 라이트 테마로 설정
156
+ # >>> app.set_theme("system") # 시스템 테마를 따름
157
+ # """
158
+ # self.theme = theme
159
+
160
+ # if theme == "system":
161
+ # # 시스템 테마를 light/dark 문자열로 변환
162
+ # system_theme = (
163
+ # "dark"
164
+ # if self.styleHints().colorScheme() == Qt.ColorScheme.Dark
165
+ # else "light"
166
+ # )
167
+ # self._handle_color_scheme_change(system_theme)
168
+ # self.styleHints().colorSchemeChanged.connect(
169
+ # lambda: self._handle_color_scheme_change(system_theme)
170
+ # )
171
+ # else:
172
+ # # 기존 이벤트 연결 해제
173
+ # self.styleHints().colorSchemeChanged.disconnect(
174
+ # lambda: self._handle_color_scheme_change(self.theme)
175
+ # )
176
+ # self._handle_color_scheme_change(self.theme)
177
+
126
178
  def set_icon(self, icon_path: str):
127
179
  """
128
180
  Dynamically sets the application's icon.
@@ -407,7 +459,7 @@ class Pyloid(QApplication):
407
459
  app = Pyloid(app_name="Pyloid-App")
408
460
 
409
461
  window = app.get_window_by_id("123e4567-e89b-12d3-a456-426614174000")
410
-
462
+
411
463
  if window:
412
464
  print("Window found:", window)
413
465
  ```
@@ -1244,7 +1296,9 @@ class Pyloid(QApplication):
1244
1296
  ###########################################################################################
1245
1297
  # File dialog
1246
1298
  ###########################################################################################
1247
- def open_file_dialog(self, dir: Optional[str] = None, filter: Optional[str] = None) -> Optional[str]:
1299
+ def open_file_dialog(
1300
+ self, dir: Optional[str] = None, filter: Optional[str] = None
1301
+ ) -> Optional[str]:
1248
1302
  """
1249
1303
  Opens a file dialog to select a file to open.
1250
1304
 
@@ -1270,7 +1324,9 @@ class Pyloid(QApplication):
1270
1324
  file_path, _ = QFileDialog.getOpenFileName(None, dir=dir, filter=filter)
1271
1325
  return file_path if file_path else None
1272
1326
 
1273
- def save_file_dialog(self, dir: Optional[str] = None, filter: Optional[str] = None) -> Optional[str]:
1327
+ def save_file_dialog(
1328
+ self, dir: Optional[str] = None, filter: Optional[str] = None
1329
+ ) -> Optional[str]:
1274
1330
  """
1275
1331
  Opens a file dialog to select a file to save.
1276
1332
 
@@ -1320,4 +1376,22 @@ class Pyloid(QApplication):
1320
1376
  directory_path = QFileDialog.getExistingDirectory(None, dir=dir)
1321
1377
  return directory_path if directory_path else None
1322
1378
 
1379
+ def _handle_color_scheme_change(self):
1380
+ self.theme = (
1381
+ "dark"
1382
+ if self.styleHints().colorScheme() == Qt.ColorScheme.Dark
1383
+ else "light"
1384
+ )
1385
+
1386
+ js_code = f"""
1387
+ document.dispatchEvent(new CustomEvent('themeChange', {{
1388
+ detail: {{ theme: "{self.theme}" }}
1389
+ }}));
1390
+ """
1323
1391
 
1392
+ # 모든 윈도우에 변경사항 적용
1393
+ for window in self.windows:
1394
+ window.web_view.page().runJavaScript(js_code)
1395
+ window.web_view.page().setBackgroundColor(
1396
+ Qt.GlobalColor.black if self.theme == "dark" else Qt.GlobalColor.white
1397
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyloid
3
- Version: 0.16.2
3
+ Version: 0.16.5
4
4
  Summary:
5
5
  Author: aesthetics-of-record
6
6
  Author-email: 111675679+aesthetics-of-record@users.noreply.github.com
@@ -1,17 +1,17 @@
1
1
  pyloid/__init__.py,sha256=OOPhOKNQVmAM8hnfTeE7lHzxb8LsFNcgegBAvDrA-vY,293
2
2
  pyloid/api.py,sha256=np0pFVUlen_GpN0svY0A3awY_ZjVFk-RpHQZZKFUMuo,2157
3
3
  pyloid/autostart.py,sha256=K7DQYl4LHItvPp0bt1V9WwaaZmVSTeGvadkcwG-KKrI,3899
4
- pyloid/browser_window.py,sha256=oX0FfQSFLVtTohI91QN2PR8EkwhY12qtcxWb0tknHrs,49771
4
+ pyloid/browser_window.py,sha256=aISmYtmf-suKPiN42wGskeNRVlkmkSV4CIKKfB-W8Cw,58251
5
5
  pyloid/custom/titlebar.py,sha256=itzK9pJbZMQ7BKca9kdbuHMffurrw15UijR6OU03Xsk,3894
6
6
  pyloid/filewatcher.py,sha256=3M5zWVUf1OhlkWJcDFC8ZA9agO4Q-U8WdgGpy6kaVz0,4601
7
7
  pyloid/js_api/event_api.py,sha256=_52yyBonqecmMvJpFW7OMNi_jX8Nrteqw_kI6r-DGG0,951
8
- pyloid/js_api/window_api.py,sha256=bUZBnBDJ8TYkM9T4swCT2khPZGzOpyiwpcXDrvmmhCI,6713
8
+ pyloid/js_api/window_api.py,sha256=_EAZ0GG0oa0EeIIyWnys03InLQuQfv4ZPezMouOJEGc,8155
9
9
  pyloid/monitor.py,sha256=nmcoOmlHeTysrZVT5mmL92ASbqMg8aH-hQg35qKWi0M,27540
10
- pyloid/pyloid.py,sha256=3YymePkpM_hKPzvHSSgELuSHkmbDsKW60HnRwwBMY7A,41178
10
+ pyloid/pyloid.py,sha256=2YcI0vn5VvCf4oXwsS3Y_7itlzjGlHQEQIbpwR_rkZ4,43874
11
11
  pyloid/timer.py,sha256=RqMsChFUd93cxMVgkHWiIKrci0QDTBgJSTULnAtYT8M,8712
12
12
  pyloid/tray.py,sha256=D12opVEc2wc2T4tK9epaN1oOdeziScsIVNM2uCN7C-A,1710
13
13
  pyloid/utils.py,sha256=VGZE2liY8_AElEqxVe1YLbk3fWlcAevpRc6oOTTgi-U,1927
14
- pyloid-0.16.2.dist-info/LICENSE,sha256=MTYF-6xpRekyTUglRweWtbfbwBL1I_3Bgfbm_SNOuI8,11525
15
- pyloid-0.16.2.dist-info/METADATA,sha256=jkiAeck5XT9NawztFM4196igCb15YUVNYGezF-xq-g0,3050
16
- pyloid-0.16.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
17
- pyloid-0.16.2.dist-info/RECORD,,
14
+ pyloid-0.16.5.dist-info/LICENSE,sha256=MTYF-6xpRekyTUglRweWtbfbwBL1I_3Bgfbm_SNOuI8,11525
15
+ pyloid-0.16.5.dist-info/METADATA,sha256=P8jz2kA5mL5UU9U-LqjGhwfpKLCHg8x6o2nzFOyn7Fs,3050
16
+ pyloid-0.16.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
17
+ pyloid-0.16.5.dist-info/RECORD,,