pytodo-qt 0.2.7__tar.gz → 0.3.8__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 (96) hide show
  1. pytodo_qt-0.3.8/PKG-INFO +199 -0
  2. pytodo_qt-0.3.8/README.md +169 -0
  3. pytodo_qt-0.3.8/pyproject.toml +90 -0
  4. pytodo_qt-0.3.8/src/pytodo_qt/__init__.py +18 -0
  5. pytodo_qt-0.3.8/src/pytodo_qt/__main__.py +167 -0
  6. pytodo_qt-0.3.8/src/pytodo_qt/core/__init__.py +104 -0
  7. pytodo_qt-0.3.8/src/pytodo_qt/core/config.py +313 -0
  8. pytodo_qt-0.3.8/src/pytodo_qt/core/database.py +421 -0
  9. pytodo_qt-0.3.8/src/pytodo_qt/core/logger.py +143 -0
  10. pytodo_qt-0.3.8/src/pytodo_qt/core/migration.py +258 -0
  11. pytodo_qt-0.3.8/src/pytodo_qt/core/models.py +323 -0
  12. pytodo_qt-0.3.8/src/pytodo_qt/core/paths.py +166 -0
  13. pytodo_qt-0.3.8/src/pytodo_qt/core/settings.py +41 -0
  14. pytodo_qt-0.3.8/src/pytodo_qt/core/sync_engine.py +327 -0
  15. pytodo_qt-0.3.8/src/pytodo_qt/crypto/__init__.py +91 -0
  16. pytodo_qt-0.3.8/src/pytodo_qt/crypto/aes_gcm.py +205 -0
  17. pytodo_qt-0.3.8/src/pytodo_qt/crypto/kdf.py +130 -0
  18. pytodo_qt-0.3.8/src/pytodo_qt/crypto/key_exchange.py +292 -0
  19. pytodo_qt-0.3.8/src/pytodo_qt/crypto/keyring_storage.py +298 -0
  20. pytodo_qt-0.3.8/src/pytodo_qt/crypto/legacy.py +85 -0
  21. pytodo_qt-0.3.8/src/pytodo_qt/gui/__init__.py +28 -0
  22. pytodo_qt-0.3.8/src/pytodo_qt/gui/dialogs/__init__.py +13 -0
  23. pytodo_qt-0.3.8/src/pytodo_qt/gui/dialogs/add_todo.py +97 -0
  24. pytodo_qt-0.3.8/src/pytodo_qt/gui/dialogs/peer_manager.py +418 -0
  25. pytodo_qt-0.3.8/src/pytodo_qt/gui/dialogs/settings.py +330 -0
  26. pytodo_qt-0.3.8/src/pytodo_qt/gui/dialogs/sync.py +198 -0
  27. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/exit.svg +6 -0
  28. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/minus.svg +3 -0
  29. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/plus.svg +3 -0
  30. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/pytodo-qt-1024.png +0 -0
  31. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/pytodo-qt-256.png +0 -0
  32. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/pytodo-qt.icns +0 -0
  33. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/pytodo-qt.svg +18 -0
  34. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/toggle.svg +4 -0
  35. pytodo_qt-0.3.8/src/pytodo_qt/gui/icons/tray.svg +3 -0
  36. pytodo_qt-0.3.8/src/pytodo_qt/gui/main_window.py +940 -0
  37. pytodo_qt-0.3.8/src/pytodo_qt/gui/styles/__init__.py +25 -0
  38. pytodo_qt-0.3.8/src/pytodo_qt/gui/styles/themes.py +475 -0
  39. pytodo_qt-0.3.8/src/pytodo_qt/gui/widgets/__init__.py +11 -0
  40. pytodo_qt-0.3.8/src/pytodo_qt/gui/widgets/list_selector.py +158 -0
  41. pytodo_qt-0.3.8/src/pytodo_qt/gui/widgets/status_bar.py +94 -0
  42. pytodo_qt-0.3.8/src/pytodo_qt/gui/widgets/todo_table.py +190 -0
  43. pytodo_qt-0.3.8/src/pytodo_qt/net/__init__.py +47 -0
  44. pytodo_qt-0.3.8/src/pytodo_qt/net/client.py +439 -0
  45. pytodo_qt-0.3.8/src/pytodo_qt/net/discovery.py +300 -0
  46. pytodo_qt-0.3.8/src/pytodo_qt/net/protocol.py +367 -0
  47. pytodo_qt-0.3.8/src/pytodo_qt/net/server.py +433 -0
  48. pytodo_qt-0.3.8/src/pytodo_qt.egg-info/PKG-INFO +199 -0
  49. pytodo_qt-0.3.8/src/pytodo_qt.egg-info/SOURCES.txt +67 -0
  50. pytodo_qt-0.3.8/src/pytodo_qt.egg-info/requires.txt +14 -0
  51. pytodo_qt-0.3.8/tests/test_config.py +340 -0
  52. pytodo_qt-0.3.8/tests/test_crypto.py +545 -0
  53. pytodo_qt-0.3.8/tests/test_database.py +590 -0
  54. pytodo_qt-0.3.8/tests/test_discovery.py +415 -0
  55. pytodo_qt-0.3.8/tests/test_keyring_storage.py +470 -0
  56. pytodo_qt-0.3.8/tests/test_legacy_crypto.py +234 -0
  57. pytodo_qt-0.3.8/tests/test_migration.py +492 -0
  58. pytodo_qt-0.3.8/tests/test_models.py +261 -0
  59. pytodo_qt-0.3.8/tests/test_net.py +347 -0
  60. pytodo_qt-0.3.8/tests/test_paths.py +364 -0
  61. pytodo_qt-0.3.8/tests/test_protocol.py +211 -0
  62. pytodo_qt-0.3.8/tests/test_settings.py +83 -0
  63. pytodo_qt-0.3.8/tests/test_sqlite_integration.py +449 -0
  64. pytodo_qt-0.3.8/tests/test_sync.py +587 -0
  65. pytodo-qt-0.2.7/PKG-INFO +0 -81
  66. pytodo-qt-0.2.7/README.md +0 -65
  67. pytodo-qt-0.2.7/pyproject.toml +0 -36
  68. pytodo-qt-0.2.7/setup.py +0 -3
  69. pytodo-qt-0.2.7/src/pytodo_qt/__init__.py +0 -0
  70. pytodo-qt-0.2.7/src/pytodo_qt/__main__.py +0 -115
  71. pytodo-qt-0.2.7/src/pytodo_qt/core/Logger.py +0 -62
  72. pytodo-qt-0.2.7/src/pytodo_qt/core/TodoDatabase.py +0 -243
  73. pytodo-qt-0.2.7/src/pytodo_qt/core/__init__.py +0 -35
  74. pytodo-qt-0.2.7/src/pytodo_qt/core/json_helpers.py +0 -90
  75. pytodo-qt-0.2.7/src/pytodo_qt/core/settings.py +0 -37
  76. pytodo-qt-0.2.7/src/pytodo_qt/crypto/AESCipher.py +0 -57
  77. pytodo-qt-0.2.7/src/pytodo_qt/crypto/__init__.py +0 -0
  78. pytodo-qt-0.2.7/src/pytodo_qt/gui/AddTodoDialog.py +0 -93
  79. pytodo-qt-0.2.7/src/pytodo_qt/gui/MainWindow.py +0 -969
  80. pytodo-qt-0.2.7/src/pytodo_qt/gui/SyncDialog.py +0 -106
  81. pytodo-qt-0.2.7/src/pytodo_qt/gui/__init__.py +0 -0
  82. pytodo-qt-0.2.7/src/pytodo_qt/gui/icons/minus.png +0 -0
  83. pytodo-qt-0.2.7/src/pytodo_qt/gui/icons/plus.png +0 -0
  84. pytodo-qt-0.2.7/src/pytodo_qt/gui/icons/pytodo-qt.png +0 -0
  85. pytodo-qt-0.2.7/src/pytodo_qt/net/__init__.py +0 -20
  86. pytodo-qt-0.2.7/src/pytodo_qt/net/sync_operations.py +0 -18
  87. pytodo-qt-0.2.7/src/pytodo_qt/net/tcp_client_lib.py +0 -134
  88. pytodo-qt-0.2.7/src/pytodo_qt/net/tcp_server_lib.py +0 -141
  89. pytodo-qt-0.2.7/src/pytodo_qt.egg-info/PKG-INFO +0 -81
  90. pytodo-qt-0.2.7/src/pytodo_qt.egg-info/SOURCES.txt +0 -30
  91. pytodo-qt-0.2.7/src/pytodo_qt.egg-info/requires.txt +0 -2
  92. {pytodo-qt-0.2.7 → pytodo_qt-0.3.8}/COPYING +0 -0
  93. {pytodo-qt-0.2.7 → pytodo_qt-0.3.8}/setup.cfg +0 -0
  94. {pytodo-qt-0.2.7 → pytodo_qt-0.3.8}/src/pytodo_qt.egg-info/dependency_links.txt +0 -0
  95. {pytodo-qt-0.2.7 → pytodo_qt-0.3.8}/src/pytodo_qt.egg-info/entry_points.txt +0 -0
  96. {pytodo-qt-0.2.7 → pytodo_qt-0.3.8}/src/pytodo_qt.egg-info/top_level.txt +0 -0
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytodo-qt
3
+ Version: 0.3.8
4
+ Summary: A cross-platform to-do list manager with encrypted peer-to-peer synchronization
5
+ Author-email: Michael Berry <trismegustis@gmail.com>
6
+ License: GPLv3
7
+ Project-URL: Homepage, https://github.com/berrym/pytodo-qt
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.11
14
+ Description-Content-Type: text/markdown
15
+ License-File: COPYING
16
+ Requires-Dist: PyQt6>=6.4
17
+ Requires-Dist: cryptography>=41.0
18
+ Requires-Dist: zeroconf>=0.80
19
+ Requires-Dist: keyring>=24.0
20
+ Requires-Dist: qasync>=0.24
21
+ Requires-Dist: rich>=13.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: pytest-qt>=4.2; extra == "dev"
25
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
26
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
27
+ Requires-Dist: ruff>=0.4; extra == "dev"
28
+ Requires-Dist: basedpyright>=1.18; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ # pytodo-qt
32
+
33
+ [![CI](https://github.com/berrym/pytodo-qt/actions/workflows/ci.yml/badge.svg)](https://github.com/berrym/pytodo-qt/actions/workflows/ci.yml)
34
+ [![codecov](https://codecov.io/gh/berrym/pytodo-qt/graph/badge.svg)](https://codecov.io/gh/berrym/pytodo-qt)
35
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
36
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
37
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
38
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
39
+
40
+ A cross-platform to-do list manager with encrypted peer-to-peer synchronization.
41
+
42
+ ## Features
43
+
44
+ - **Multiple lists** - Organize tasks into separate lists
45
+ - **Priority levels** - High, normal, and low priority with color coding
46
+ - **Encrypted sync** - AES-256-GCM encryption with Ed25519 key exchange
47
+ - **Auto-discovery** - Find other instances on your network via mDNS/Zeroconf
48
+ - **Dark/light themes** - System-following or manual theme selection
49
+ - **Cross-platform** - Linux, macOS, and Windows support
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.11 or later
54
+ - PyQt6
55
+
56
+ ## Installation
57
+
58
+ ### Pre-built Binaries
59
+
60
+ Download the latest release for your platform from the [Releases page](https://github.com/berrym/pytodo-qt/releases).
61
+
62
+ #### macOS
63
+
64
+ 1. Download `pytodo-qt-VERSION-macos-arm64.zip` (Apple Silicon) or `pytodo-qt-VERSION-macos-x86_64.zip` (Intel)
65
+ 2. Extract the zip file
66
+ 3. Move `pytodo-qt.app` to `/Applications` or `~/Applications`
67
+ 4. **First run only:** Right-click the app and select "Open" to bypass Gatekeeper
68
+ - Alternatively, run: `xattr -rd com.apple.quarantine /Applications/pytodo-qt.app`
69
+ 5. After the first run, you can open normally by double-clicking
70
+
71
+ > **Note:** The app is ad-hoc signed (not notarized with an Apple Developer ID), so macOS will show an "unidentified developer" warning on first launch. This is normal for open-source software distributed outside the App Store.
72
+
73
+ #### Linux
74
+
75
+ 1. Download `pytodo-qt-VERSION-linux-x86_64.tar.gz` or `pytodo-qt-VERSION-linux-arm64.tar.gz`
76
+ 2. Extract: `tar -xzf pytodo-qt-VERSION-linux-*.tar.gz`
77
+ 3. Run the install script: `cd pytodo-qt-*/ && ./install.sh`
78
+ 4. Or run directly: `./pytodo-qt`
79
+
80
+ The install script places the binary in `~/.local/bin/` and creates a desktop entry.
81
+
82
+ To uninstall: `~/.local/lib/pytodo-qt/uninstall.sh` (or run `./uninstall.sh` from the extracted archive)
83
+
84
+ #### Windows
85
+
86
+ 1. Download `pytodo-qt-VERSION-windows-x86_64.zip`
87
+ 2. Extract the zip file
88
+ 3. Run `pytodo-qt.exe`
89
+
90
+ ### From PyPI
91
+
92
+ ```bash
93
+ pipx install pytodo-qt # recommended
94
+ pip install pytodo-qt # alternative
95
+ ```
96
+
97
+ ### From source
98
+
99
+ ```bash
100
+ git clone https://github.com/berrym/pytodo-qt.git
101
+ cd pytodo-qt
102
+ pip install .
103
+ ```
104
+
105
+ ### Development install
106
+
107
+ ```bash
108
+ pip install -e ".[dev]"
109
+ ```
110
+
111
+ ## Usage
112
+
113
+ ```bash
114
+ pytodo-qt
115
+ ```
116
+
117
+ ### Command-line options
118
+
119
+ ```
120
+ Server Options:
121
+ -s, --server {yes,no} enable/disable network server
122
+ --pull {yes,no} allow remote pull requests
123
+ --push {yes,no} allow remote push requests
124
+ -i, --ip IP server bind address
125
+ -p, --port PORT server port
126
+
127
+ Discovery Options:
128
+ -d, --discovery {yes,no} enable/disable mDNS discovery
129
+
130
+ Appearance Options:
131
+ -t, --theme {light,dark,system}
132
+ ```
133
+
134
+ ## Configuration
135
+
136
+ Configuration is stored in XDG-compliant locations:
137
+
138
+ | Platform | Config | Data |
139
+ |----------|--------|------|
140
+ | Linux | `~/.config/pytodo-qt/` | `~/.local/share/pytodo-qt/` |
141
+ | macOS | `~/Library/Application Support/pytodo-qt/` | same |
142
+ | Windows | `%APPDATA%\pytodo-qt\` | same |
143
+
144
+ ### config.toml
145
+
146
+ ```toml
147
+ [database]
148
+ active_list = ""
149
+ sort_key = "priority"
150
+ reverse_sort = false
151
+
152
+ [server]
153
+ enabled = true
154
+ address = "0.0.0.0"
155
+ port = 5364
156
+ allow_pull = true
157
+ allow_push = true
158
+
159
+ [discovery]
160
+ enabled = true
161
+ service_name = "" # defaults to pytodo-{hostname}
162
+
163
+ [appearance]
164
+ theme = "system" # light, dark, system
165
+ ```
166
+
167
+ ## Synchronization
168
+
169
+ pytodo-qt uses a secure peer-to-peer protocol for syncing between instances:
170
+
171
+ 1. **Discovery** - Instances advertise themselves via mDNS (`_pytodo._tcp.local.`)
172
+ 2. **Key exchange** - Ed25519 identity keys with X25519 ephemeral session keys
173
+ 3. **Encryption** - All data encrypted with AES-256-GCM
174
+ 4. **Merge** - Last-write-wins conflict resolution with UUID-based items
175
+
176
+ Identity keys are stored in your system keyring (GNOME Keyring, macOS Keychain, Windows Credential Locker).
177
+
178
+ ## Development
179
+
180
+ ```bash
181
+ # Install dev dependencies
182
+ pip install -e ".[dev]"
183
+
184
+ # Run tests
185
+ pytest
186
+
187
+ # Lint and format
188
+ ruff check src/ tests/
189
+ ruff format src/ tests/
190
+
191
+ # Type check
192
+ basedpyright src/
193
+ ```
194
+
195
+ ## License
196
+
197
+ GPLv3 or later. See [COPYING](COPYING) for details.
198
+
199
+ Copyright 2024 Michael Berry <trismegustis@gmail.com>
@@ -0,0 +1,169 @@
1
+ # pytodo-qt
2
+
3
+ [![CI](https://github.com/berrym/pytodo-qt/actions/workflows/ci.yml/badge.svg)](https://github.com/berrym/pytodo-qt/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/berrym/pytodo-qt/graph/badge.svg)](https://codecov.io/gh/berrym/pytodo-qt)
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
8
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
9
+
10
+ A cross-platform to-do list manager with encrypted peer-to-peer synchronization.
11
+
12
+ ## Features
13
+
14
+ - **Multiple lists** - Organize tasks into separate lists
15
+ - **Priority levels** - High, normal, and low priority with color coding
16
+ - **Encrypted sync** - AES-256-GCM encryption with Ed25519 key exchange
17
+ - **Auto-discovery** - Find other instances on your network via mDNS/Zeroconf
18
+ - **Dark/light themes** - System-following or manual theme selection
19
+ - **Cross-platform** - Linux, macOS, and Windows support
20
+
21
+ ## Requirements
22
+
23
+ - Python 3.11 or later
24
+ - PyQt6
25
+
26
+ ## Installation
27
+
28
+ ### Pre-built Binaries
29
+
30
+ Download the latest release for your platform from the [Releases page](https://github.com/berrym/pytodo-qt/releases).
31
+
32
+ #### macOS
33
+
34
+ 1. Download `pytodo-qt-VERSION-macos-arm64.zip` (Apple Silicon) or `pytodo-qt-VERSION-macos-x86_64.zip` (Intel)
35
+ 2. Extract the zip file
36
+ 3. Move `pytodo-qt.app` to `/Applications` or `~/Applications`
37
+ 4. **First run only:** Right-click the app and select "Open" to bypass Gatekeeper
38
+ - Alternatively, run: `xattr -rd com.apple.quarantine /Applications/pytodo-qt.app`
39
+ 5. After the first run, you can open normally by double-clicking
40
+
41
+ > **Note:** The app is ad-hoc signed (not notarized with an Apple Developer ID), so macOS will show an "unidentified developer" warning on first launch. This is normal for open-source software distributed outside the App Store.
42
+
43
+ #### Linux
44
+
45
+ 1. Download `pytodo-qt-VERSION-linux-x86_64.tar.gz` or `pytodo-qt-VERSION-linux-arm64.tar.gz`
46
+ 2. Extract: `tar -xzf pytodo-qt-VERSION-linux-*.tar.gz`
47
+ 3. Run the install script: `cd pytodo-qt-*/ && ./install.sh`
48
+ 4. Or run directly: `./pytodo-qt`
49
+
50
+ The install script places the binary in `~/.local/bin/` and creates a desktop entry.
51
+
52
+ To uninstall: `~/.local/lib/pytodo-qt/uninstall.sh` (or run `./uninstall.sh` from the extracted archive)
53
+
54
+ #### Windows
55
+
56
+ 1. Download `pytodo-qt-VERSION-windows-x86_64.zip`
57
+ 2. Extract the zip file
58
+ 3. Run `pytodo-qt.exe`
59
+
60
+ ### From PyPI
61
+
62
+ ```bash
63
+ pipx install pytodo-qt # recommended
64
+ pip install pytodo-qt # alternative
65
+ ```
66
+
67
+ ### From source
68
+
69
+ ```bash
70
+ git clone https://github.com/berrym/pytodo-qt.git
71
+ cd pytodo-qt
72
+ pip install .
73
+ ```
74
+
75
+ ### Development install
76
+
77
+ ```bash
78
+ pip install -e ".[dev]"
79
+ ```
80
+
81
+ ## Usage
82
+
83
+ ```bash
84
+ pytodo-qt
85
+ ```
86
+
87
+ ### Command-line options
88
+
89
+ ```
90
+ Server Options:
91
+ -s, --server {yes,no} enable/disable network server
92
+ --pull {yes,no} allow remote pull requests
93
+ --push {yes,no} allow remote push requests
94
+ -i, --ip IP server bind address
95
+ -p, --port PORT server port
96
+
97
+ Discovery Options:
98
+ -d, --discovery {yes,no} enable/disable mDNS discovery
99
+
100
+ Appearance Options:
101
+ -t, --theme {light,dark,system}
102
+ ```
103
+
104
+ ## Configuration
105
+
106
+ Configuration is stored in XDG-compliant locations:
107
+
108
+ | Platform | Config | Data |
109
+ |----------|--------|------|
110
+ | Linux | `~/.config/pytodo-qt/` | `~/.local/share/pytodo-qt/` |
111
+ | macOS | `~/Library/Application Support/pytodo-qt/` | same |
112
+ | Windows | `%APPDATA%\pytodo-qt\` | same |
113
+
114
+ ### config.toml
115
+
116
+ ```toml
117
+ [database]
118
+ active_list = ""
119
+ sort_key = "priority"
120
+ reverse_sort = false
121
+
122
+ [server]
123
+ enabled = true
124
+ address = "0.0.0.0"
125
+ port = 5364
126
+ allow_pull = true
127
+ allow_push = true
128
+
129
+ [discovery]
130
+ enabled = true
131
+ service_name = "" # defaults to pytodo-{hostname}
132
+
133
+ [appearance]
134
+ theme = "system" # light, dark, system
135
+ ```
136
+
137
+ ## Synchronization
138
+
139
+ pytodo-qt uses a secure peer-to-peer protocol for syncing between instances:
140
+
141
+ 1. **Discovery** - Instances advertise themselves via mDNS (`_pytodo._tcp.local.`)
142
+ 2. **Key exchange** - Ed25519 identity keys with X25519 ephemeral session keys
143
+ 3. **Encryption** - All data encrypted with AES-256-GCM
144
+ 4. **Merge** - Last-write-wins conflict resolution with UUID-based items
145
+
146
+ Identity keys are stored in your system keyring (GNOME Keyring, macOS Keychain, Windows Credential Locker).
147
+
148
+ ## Development
149
+
150
+ ```bash
151
+ # Install dev dependencies
152
+ pip install -e ".[dev]"
153
+
154
+ # Run tests
155
+ pytest
156
+
157
+ # Lint and format
158
+ ruff check src/ tests/
159
+ ruff format src/ tests/
160
+
161
+ # Type check
162
+ basedpyright src/
163
+ ```
164
+
165
+ ## License
166
+
167
+ GPLv3 or later. See [COPYING](COPYING) for details.
168
+
169
+ Copyright 2024 Michael Berry <trismegustis@gmail.com>
@@ -0,0 +1,90 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.setuptools.packages.find]
6
+ where = ["src"]
7
+
8
+ [tool.setuptools.package-data]
9
+ pytodo_qt = ["*.png", "*.qss"]
10
+ "pytodo_qt.gui.icons" = ["*.png", "*.svg", "*.ico", "*.icns"]
11
+ "pytodo_qt.gui.styles" = ["*.qss"]
12
+
13
+ [tool.basedpyright]
14
+ typeCheckingMode = "standard"
15
+ pythonVersion = "3.11"
16
+ reportMissingImports = "warning"
17
+ reportMissingTypeStubs = false
18
+
19
+ [tool.ruff]
20
+ target-version = "py311"
21
+ line-length = 100
22
+ src = ["src", "tests"]
23
+
24
+ [tool.ruff.format]
25
+ quote-style = "double"
26
+ indent-style = "space"
27
+ skip-magic-trailing-comma = false
28
+ line-ending = "auto"
29
+ docstring-code-format = true
30
+
31
+ [tool.ruff.lint]
32
+ select = [
33
+ "E", # pycodestyle errors
34
+ "W", # pycodestyle warnings
35
+ "F", # Pyflakes
36
+ "I", # isort
37
+ "B", # flake8-bugbear
38
+ "C4", # flake8-comprehensions
39
+ "UP", # pyupgrade
40
+ "SIM", # flake8-simplify
41
+ ]
42
+ ignore = [
43
+ "E501", # line too long (handled by formatter)
44
+ "SIM108", # allow if-else instead of ternary
45
+ ]
46
+
47
+ [tool.ruff.lint.isort]
48
+ known-first-party = ["pytodo_qt"]
49
+
50
+ [project]
51
+ name = "pytodo-qt"
52
+ version = "0.3.8"
53
+ description = "A cross-platform to-do list manager with encrypted peer-to-peer synchronization"
54
+ readme = "README.md"
55
+ authors = [
56
+ {name = "Michael Berry", email = "trismegustis@gmail.com"},
57
+ ]
58
+ dependencies = [
59
+ "PyQt6>=6.4",
60
+ "cryptography>=41.0",
61
+ "zeroconf>=0.80",
62
+ "keyring>=24.0",
63
+ "qasync>=0.24",
64
+ "rich>=13.0",
65
+ ]
66
+ classifiers = [
67
+ "Programming Language :: Python :: 3",
68
+ "Programming Language :: Python :: 3.11",
69
+ "Programming Language :: Python :: 3.12",
70
+ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
71
+ "Operating System :: OS Independent",
72
+ ]
73
+ license = {text = "GPLv3"}
74
+ requires-python = ">=3.11"
75
+
76
+ [project.optional-dependencies]
77
+ dev = [
78
+ "pytest>=7.0",
79
+ "pytest-qt>=4.2",
80
+ "pytest-asyncio>=0.21",
81
+ "pytest-cov>=4.0",
82
+ "ruff>=0.4",
83
+ "basedpyright>=1.18",
84
+ ]
85
+
86
+ [project.urls]
87
+ Homepage = "https://github.com/berrym/pytodo-qt"
88
+
89
+ [project.scripts]
90
+ pytodo-qt = "pytodo_qt.__main__:main"
@@ -0,0 +1,18 @@
1
+ """pytodo-qt - A modern cross-platform to-do application with secure sync.
2
+
3
+ Version 0.3.0 brings:
4
+ - AES-256-GCM authenticated encryption
5
+ - Ed25519/X25519 key exchange for secure connections
6
+ - UUID-based data model with Lamport timestamps
7
+ - Last-Write-Wins sync with conflict tracking
8
+ - Zeroconf/mDNS service discovery
9
+ - TOML configuration with system keyring integration
10
+ - Modern themed UI with light/dark/system mode support
11
+
12
+ Copyright (C) 2024 Michael Berry
13
+ License: GPLv3
14
+ """
15
+
16
+ from .core.settings import __version__
17
+
18
+ __all__ = ["__version__"]
@@ -0,0 +1,167 @@
1
+ """__main__.py
2
+
3
+ pytodo-qt
4
+
5
+ A modern to-do list application with secure synchronization.
6
+
7
+ Copyright (C) 2024 Michael Berry <trismegustis@gmail.com>
8
+
9
+ This program is free software: you can redistribute it and/or modify
10
+ it under the terms of the GNU General Public License as published by
11
+ the Free Software Foundation, either version 3 of the License, or
12
+ (at your option) any later version.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU General Public License for more details.
18
+
19
+ You should have received a copy of the GNU General Public License
20
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ """
22
+
23
+ import argparse
24
+ import asyncio
25
+ import sys
26
+
27
+ from PyQt6.QtWidgets import QApplication
28
+ from qasync import QEventLoop
29
+
30
+ from .core import settings
31
+ from .core.logger import Logger
32
+
33
+ logger = Logger(__name__)
34
+
35
+
36
+ def main():
37
+ """Application entry point."""
38
+ # Initialize configuration system
39
+ config = settings.init_config()
40
+
41
+ # Create command line argument parser
42
+ arg_parser = argparse.ArgumentParser(
43
+ prog="pytodo-qt",
44
+ description="Modern To-Do List Application with Secure Sync",
45
+ epilog="Copyright (C) 2024 Michael Berry",
46
+ )
47
+
48
+ # Server options
49
+ server_group = arg_parser.add_argument_group("Server Options")
50
+
51
+ server_group.add_argument(
52
+ "-s",
53
+ "--server",
54
+ action="store",
55
+ type=str,
56
+ choices=["yes", "no"],
57
+ help="enable/disable network server",
58
+ )
59
+
60
+ server_group.add_argument(
61
+ "--pull",
62
+ action="store",
63
+ type=str,
64
+ choices=["yes", "no"],
65
+ help="allow remote pull requests",
66
+ )
67
+
68
+ server_group.add_argument(
69
+ "--push",
70
+ action="store",
71
+ type=str,
72
+ choices=["yes", "no"],
73
+ help="allow remote push requests",
74
+ )
75
+
76
+ server_group.add_argument(
77
+ "-i",
78
+ "--ip",
79
+ type=str,
80
+ help="server bind address",
81
+ )
82
+
83
+ server_group.add_argument(
84
+ "-p",
85
+ "--port",
86
+ type=int,
87
+ help="server port",
88
+ )
89
+
90
+ # Discovery options
91
+ discovery_group = arg_parser.add_argument_group("Discovery Options")
92
+
93
+ discovery_group.add_argument(
94
+ "-d",
95
+ "--discovery",
96
+ action="store",
97
+ type=str,
98
+ choices=["yes", "no"],
99
+ help="enable/disable mDNS discovery",
100
+ )
101
+
102
+ # Appearance options
103
+ appearance_group = arg_parser.add_argument_group("Appearance Options")
104
+
105
+ appearance_group.add_argument(
106
+ "-t",
107
+ "--theme",
108
+ type=str,
109
+ choices=["light", "dark", "system"],
110
+ help="UI theme",
111
+ )
112
+
113
+ # General options
114
+ arg_parser.add_argument(
115
+ "-V",
116
+ "--version",
117
+ action="version",
118
+ version=f"%(prog)s v{settings.__version__}",
119
+ )
120
+
121
+ # Parse arguments
122
+ args = arg_parser.parse_args()
123
+
124
+ # Apply command-line overrides to config
125
+ if args.server is not None:
126
+ config.server.enabled = args.server == "yes"
127
+ if args.pull is not None:
128
+ config.server.allow_pull = args.pull == "yes"
129
+ if args.push is not None:
130
+ config.server.allow_push = args.push == "yes"
131
+ if args.ip is not None:
132
+ config.server.address = args.ip
133
+ if args.port is not None:
134
+ config.server.port = args.port
135
+ if args.discovery is not None:
136
+ config.discovery.enabled = args.discovery == "yes"
137
+ if args.theme is not None:
138
+ config.appearance.theme = args.theme
139
+
140
+ # Create Qt application
141
+ app = QApplication(sys.argv)
142
+ app.setApplicationName("pytodo-qt")
143
+ app.setApplicationVersion(settings.__version__)
144
+ app.setOrganizationName("pytodo-qt")
145
+
146
+ # Set up async event loop with qasync
147
+ loop = QEventLoop(app)
148
+ asyncio.set_event_loop(loop)
149
+
150
+ # Apply theme
151
+ from .gui.styles import apply_current_theme
152
+
153
+ apply_current_theme()
154
+
155
+ # Create main window
156
+ logger.log.info("Starting pytodo-qt v%s", settings.__version__)
157
+ from .gui.main_window import MainWindow
158
+
159
+ _window = MainWindow() # noqa: F841 - window must stay alive for event loop
160
+
161
+ # Run application with async event loop
162
+ with loop:
163
+ sys.exit(loop.run_forever())
164
+
165
+
166
+ if __name__ == "__main__":
167
+ main()