remotedesktop 1.9.2__tar.gz → 1.9.3__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 (77) hide show
  1. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/PKG-INFO +1 -1
  2. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/__init__.py +1 -1
  3. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/logs.py +28 -1
  4. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_logs.py +22 -0
  5. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/.github/workflows/ci.yml +0 -0
  6. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/.github/workflows/release.yml +0 -0
  7. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/.gitignore +0 -0
  8. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/CLAUDE.md +0 -0
  9. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/LICENSE +0 -0
  10. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/docs/media/client-demo.gif +0 -0
  11. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/docs/media/server-demo.gif +0 -0
  12. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/icon/remotedesktop.ico +0 -0
  13. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/pyproject.toml +0 -0
  14. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/readme.md +0 -0
  15. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/run.bat +0 -0
  16. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/run_claude.bat +0 -0
  17. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/scripts/make_coverage_badge.py +0 -0
  18. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/scripts/make_installer.bat +0 -0
  19. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/scripts/make_venv.bat +0 -0
  20. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/__main__.py +0 -0
  21. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/about.py +0 -0
  22. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/app.py +0 -0
  23. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/autostart.py +0 -0
  24. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/client.py +0 -0
  25. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/clipboard.py +0 -0
  26. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/compat.py +0 -0
  27. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/config.py +0 -0
  28. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/cursor_shape.py +0 -0
  29. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/db.py +0 -0
  30. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/discovery.py +0 -0
  31. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/dxgi.py +0 -0
  32. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/frames.py +0 -0
  33. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/icon.py +0 -0
  34. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/input_injection.py +0 -0
  35. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/inventory.py +0 -0
  36. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/modal_loop.py +0 -0
  37. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/performance.py +0 -0
  38. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/preferences.py +0 -0
  39. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/protocol.py +0 -0
  40. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/server.py +0 -0
  41. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/session_lock.py +0 -0
  42. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/sharing.py +0 -0
  43. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/single_instance.py +0 -0
  44. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/tls.py +0 -0
  45. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/viewer.py +0 -0
  46. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/visual_effects.py +0 -0
  47. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/src/remotedesktop/window_state.py +0 -0
  48. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/conftest.py +0 -0
  49. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_about.py +0 -0
  50. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_autostart.py +0 -0
  51. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_clipboard.py +0 -0
  52. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_compat.py +0 -0
  53. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_config.py +0 -0
  54. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_cursor_shape.py +0 -0
  55. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_discovery.py +0 -0
  56. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_dxgi.py +0 -0
  57. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_frames.py +0 -0
  58. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_icon.py +0 -0
  59. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_input.py +0 -0
  60. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_input_injection.py +0 -0
  61. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_inventory.py +0 -0
  62. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_main_window.py +0 -0
  63. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_modal_loop.py +0 -0
  64. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_performance.py +0 -0
  65. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_preferences.py +0 -0
  66. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_protocol.py +0 -0
  67. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_session_lock.py +0 -0
  68. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_sharing.py +0 -0
  69. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_sharing_tab.py +0 -0
  70. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_single_instance.py +0 -0
  71. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_smoke.py +0 -0
  72. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_tls.py +0 -0
  73. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_visual_effects.py +0 -0
  74. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tests/test_window_state.py +0 -0
  75. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tools/make_demo_gifs.py +0 -0
  76. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/tools/make_icon.py +0 -0
  77. {remotedesktop-1.9.2 → remotedesktop-1.9.3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remotedesktop
3
- Version: 1.9.2
3
+ Version: 1.9.3
4
4
  Summary: Remote desktop app for Windows computers on the same LAN, with autodiscovery. View other computers and optionally share this one — screen, keyboard, mouse, and clipboard, without RDP or Microsoft authentication.
5
5
  Project-URL: Homepage, https://github.com/jamesabel/remotedesktop
6
6
  Project-URL: Repository, https://github.com/jamesabel/remotedesktop
@@ -1,3 +1,3 @@
1
1
  """Remote desktop client/server for Windows computers on the same LAN."""
2
2
 
3
- __version__ = "1.9.2"
3
+ __version__ = "1.9.3"
@@ -16,7 +16,7 @@ import logging.handlers
16
16
  from pathlib import Path
17
17
 
18
18
  import platformdirs
19
- from PySide6.QtCore import Qt
19
+ from PySide6.QtCore import QMessageLogContext, Qt, QtMsgType, qInstallMessageHandler
20
20
  from PySide6.QtWidgets import QDialog, QPlainTextEdit, QVBoxLayout, QWidget
21
21
 
22
22
  # Cap on what a peer gets when it asks for our log: the most recent entries
@@ -70,12 +70,39 @@ class PeerLogDialog(QDialog):
70
70
  layout.addWidget(view)
71
71
 
72
72
 
73
+ _QT_LEVELS = {
74
+ QtMsgType.QtDebugMsg: logging.DEBUG,
75
+ QtMsgType.QtInfoMsg: logging.INFO,
76
+ QtMsgType.QtWarningMsg: logging.WARNING,
77
+ QtMsgType.QtCriticalMsg: logging.ERROR,
78
+ QtMsgType.QtFatalMsg: logging.CRITICAL,
79
+ }
80
+
81
+
82
+ def _qt_message_handler(
83
+ mode: QtMsgType, context: QMessageLogContext, message: str
84
+ ) -> None:
85
+ # Category ("qt.qpa.mime", ...) is how Qt names the subsystem; file/line
86
+ # are only populated in debug builds of Qt, so they aren't included.
87
+ category = context.category
88
+ if category and category != "default":
89
+ message = f"{category}: {message}"
90
+ logging.getLogger("remotedesktop.qt").log(
91
+ _QT_LEVELS.get(mode, logging.WARNING), message
92
+ )
93
+
94
+
73
95
  def init_logging(app_name: str, *, directory: Path | None = None) -> Path:
74
96
  """Write "remotedesktop" logger output to <log dir>/<app_name>.log.
75
97
 
98
+ Also routes Qt's own log output (e.g. "qt.qpa.mime: Retrying to obtain
99
+ clipboard.") into the same file: Qt's default message handler writes to
100
+ stderr, which a GUI app must never do.
101
+
76
102
  Returns the log file path. `directory` exists for tests; the apps use
77
103
  the platformdirs log dir.
78
104
  """
105
+ qInstallMessageHandler(_qt_message_handler)
79
106
  log_dir = directory if directory is not None else default_log_dir()
80
107
  log_dir.mkdir(parents=True, exist_ok=True)
81
108
  path = log_path(app_name, directory=directory)
@@ -1,5 +1,7 @@
1
1
  import logging
2
2
 
3
+ from PySide6.QtCore import qInstallMessageHandler, qWarning
4
+
3
5
  from remotedesktop import logs
4
6
 
5
7
 
@@ -23,6 +25,26 @@ def test_init_logging_writes_formatted_records(tmp_path):
23
25
  handler.close()
24
26
 
25
27
 
28
+ def test_init_logging_routes_qt_messages_to_the_log_file(tmp_path):
29
+ # Qt's default message handler writes to stderr — a GUI app must never
30
+ # do that, so init_logging redirects Qt's output into the log file.
31
+ path = logs.init_logging("client", directory=tmp_path)
32
+ root = logging.getLogger("remotedesktop")
33
+ try:
34
+ qWarning("qt grumbled about something")
35
+ for handler in root.handlers:
36
+ handler.flush()
37
+ text = path.read_text(encoding="utf-8")
38
+ assert "qt grumbled about something" in text
39
+ assert "WARNING" in text
40
+ assert "remotedesktop.qt" in text
41
+ finally:
42
+ qInstallMessageHandler(None) # back to Qt's default handler
43
+ for handler in list(root.handlers):
44
+ root.removeHandler(handler)
45
+ handler.close()
46
+
47
+
26
48
  def test_read_log_tail_returns_recent_content(tmp_path):
27
49
  (tmp_path / "server.log").write_text("early line\nrecent line\n", encoding="utf-8")
28
50
  text = logs.read_log_tail("server", directory=tmp_path)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes