gucmail 1.1.0__py3-none-any.whl

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 (259) hide show
  1. gucmail/__init__.py +7 -0
  2. gucmail/__main__.py +6 -0
  3. gucmail/actions.py +200 -0
  4. gucmail/backup_format.py +740 -0
  5. gucmail/bootstrap.py +157 -0
  6. gucmail/cli.py +9024 -0
  7. gucmail/command_catalog.py +2464 -0
  8. gucmail/commands.py +1181 -0
  9. gucmail/config.py +1323 -0
  10. gucmail/constants.py +20 -0
  11. gucmail/credentials.py +309 -0
  12. gucmail/data/__init__.py +1 -0
  13. gucmail/data/builtin-themes.json.gz +0 -0
  14. gucmail/data/command_corpus.json +993 -0
  15. gucmail/data/shortcut_catalog.json +2952 -0
  16. gucmail/dates.py +235 -0
  17. gucmail/doctor.py +155 -0
  18. gucmail/errors.py +196 -0
  19. gucmail/ews/__init__.py +5 -0
  20. gucmail/ews/adapter.py +5601 -0
  21. gucmail/ews/capabilities.py +711 -0
  22. gucmail/ews/delegates.py +115 -0
  23. gucmail/ews/inbox_rules.py +225 -0
  24. gucmail/ews/mapping.py +940 -0
  25. gucmail/ews/native_items.py +166 -0
  26. gucmail/ews/soap.py +267 -0
  27. gucmail/ews/sync.py +101 -0
  28. gucmail/file_completion.py +58 -0
  29. gucmail/formatting.py +183 -0
  30. gucmail/headless.py +1050 -0
  31. gucmail/help/__init__.py +62 -0
  32. gucmail/help/catalog.toml +889 -0
  33. gucmail/help/cli_syntax.py +183 -0
  34. gucmail/help/history.py +159 -0
  35. gucmail/help/links.py +93 -0
  36. gucmail/help/models.py +234 -0
  37. gucmail/help/pages/advanced/ews.md +19 -0
  38. gucmail/help/pages/appearance/branding.md +15 -0
  39. gucmail/help/pages/appearance/layout.md +41 -0
  40. gucmail/help/pages/appearance/themes.md +11 -0
  41. gucmail/help/pages/attachments/safety.md +13 -0
  42. gucmail/help/pages/backup/offline.md +13 -0
  43. gucmail/help/pages/backup/overview.md +49 -0
  44. gucmail/help/pages/diagnostics/doctor.md +11 -0
  45. gucmail/help/pages/faq/common.md +52 -0
  46. gucmail/help/pages/faq/pc-on.md +13 -0
  47. gucmail/help/pages/integrations/discord.md +38 -0
  48. gucmail/help/pages/integrations/providers.md +40 -0
  49. gucmail/help/pages/integrations/webhooks.md +34 -0
  50. gucmail/help/pages/mail/compose.md +53 -0
  51. gucmail/help/pages/mail/deleted-items.md +14 -0
  52. gucmail/help/pages/mail/drafts.md +43 -0
  53. gucmail/help/pages/mail/folders.md +43 -0
  54. gucmail/help/pages/mail/reading.md +62 -0
  55. gucmail/help/pages/mail/scheduled.md +13 -0
  56. gucmail/help/pages/notifications/monitoring.md +17 -0
  57. gucmail/help/pages/notifications/rules.md +75 -0
  58. gucmail/help/pages/notifications/windows-startup.md +64 -0
  59. gucmail/help/pages/notifications/windows.md +59 -0
  60. gucmail/help/pages/palette/overview.md +21 -0
  61. gucmail/help/pages/pim/calendar.md +105 -0
  62. gucmail/help/pages/pim/contacts.md +95 -0
  63. gucmail/help/pages/pim/tasks.md +113 -0
  64. gucmail/help/pages/privacy/credentials.md +11 -0
  65. gucmail/help/pages/privacy/local-data.md +19 -0
  66. gucmail/help/pages/reference/commands.md +11 -0
  67. gucmail/help/pages/reference/glossary.md +127 -0
  68. gucmail/help/pages/reference/shortcuts.md +47 -0
  69. gucmail/help/pages/search/local.md +93 -0
  70. gucmail/help/pages/search/overview.md +56 -0
  71. gucmail/help/pages/server/headless.md +70 -0
  72. gucmail/help/pages/settings/overview.md +25 -0
  73. gucmail/help/pages/start/first-launch.md +47 -0
  74. gucmail/help/pages/start/interface.md +43 -0
  75. gucmail/help/pages/start/login.md +13 -0
  76. gucmail/help/pages/start/overview.md +20 -0
  77. gucmail/help/pages/start/using-help.md +46 -0
  78. gucmail/help/pages/storage/cleanup.md +11 -0
  79. gucmail/help/pages/storage/quota.md +50 -0
  80. gucmail/help/pages/troubleshooting/backup-search.md +47 -0
  81. gucmail/help/pages/troubleshooting/connection.md +32 -0
  82. gucmail/help/pages/troubleshooting/database.md +13 -0
  83. gucmail/help/pages/troubleshooting/notifications.md +35 -0
  84. gucmail/help/pages/troubleshooting/sending.md +13 -0
  85. gucmail/help/pages/tutorials/backup.md +18 -0
  86. gucmail/help/pages/tutorials/first-message.md +16 -0
  87. gucmail/help/pages/tutorials/notifications.md +13 -0
  88. gucmail/help/pages/tutorials/palette.md +13 -0
  89. gucmail/help/pages/tutorials/scheduling.md +16 -0
  90. gucmail/help/reference.py +371 -0
  91. gucmail/help/repository.py +475 -0
  92. gucmail/help/search.py +392 -0
  93. gucmail/help/structure.py +139 -0
  94. gucmail/help/tutorials.py +374 -0
  95. gucmail/help/validation.py +379 -0
  96. gucmail/logging_config.py +47 -0
  97. gucmail/models.py +767 -0
  98. gucmail/nlp.py +3057 -0
  99. gucmail/notification_events.py +386 -0
  100. gucmail/notification_history.py +459 -0
  101. gucmail/notification_policies.py +1239 -0
  102. gucmail/notification_providers/__init__.py +163 -0
  103. gucmail/notification_providers/compat.py +283 -0
  104. gucmail/notification_providers/core.py +712 -0
  105. gucmail/notification_providers/reliability.py +373 -0
  106. gucmail/notification_providers/webhook_payloads.py +734 -0
  107. gucmail/notification_providers/windows.py +493 -0
  108. gucmail/notification_rules.py +1217 -0
  109. gucmail/onboarding.py +122 -0
  110. gucmail/output.py +157 -0
  111. gucmail/palette.py +639 -0
  112. gucmail/platform_scheduler.py +403 -0
  113. gucmail/py.typed +1 -0
  114. gucmail/scheduler_entry.py +23 -0
  115. gucmail/secret_store.py +263 -0
  116. gucmail/security.py +222 -0
  117. gucmail/services/__init__.py +100 -0
  118. gucmail/services/_base.py +169 -0
  119. gucmail/services/attachment_indexing.py +395 -0
  120. gucmail/services/attachment_preferences.py +20 -0
  121. gucmail/services/attachment_uploads.py +40 -0
  122. gucmail/services/attachments.py +454 -0
  123. gucmail/services/automatic_replies.py +158 -0
  124. gucmail/services/backup.py +3005 -0
  125. gucmail/services/calendar.py +1151 -0
  126. gucmail/services/calendar_display.py +151 -0
  127. gucmail/services/calendar_history.py +92 -0
  128. gucmail/services/calendar_paging.py +186 -0
  129. gucmail/services/calendar_preferences.py +88 -0
  130. gucmail/services/calendar_working_time.py +211 -0
  131. gucmail/services/cleanup.py +465 -0
  132. gucmail/services/clusters.py +1048 -0
  133. gucmail/services/compose.py +896 -0
  134. gucmail/services/compose_preferences.py +115 -0
  135. gucmail/services/contact_groups.py +250 -0
  136. gucmail/services/contact_history.py +165 -0
  137. gucmail/services/contact_preferences.py +70 -0
  138. gucmail/services/contacts.py +1265 -0
  139. gucmail/services/contacts_display.py +124 -0
  140. gucmail/services/delegates.py +98 -0
  141. gucmail/services/drafts.py +1601 -0
  142. gucmail/services/editor.py +231 -0
  143. gucmail/services/exchange_values.py +164 -0
  144. gucmail/services/extractors.py +1081 -0
  145. gucmail/services/folders.py +408 -0
  146. gucmail/services/gateway.py +16 -0
  147. gucmail/services/inbox_rules.py +172 -0
  148. gucmail/services/index.py +1134 -0
  149. gucmail/services/insights.py +764 -0
  150. gucmail/services/interchange.py +878 -0
  151. gucmail/services/keyboard_bindings.py +144 -0
  152. gucmail/services/keyboard_preferences.py +165 -0
  153. gucmail/services/layout_presets.py +164 -0
  154. gucmail/services/local_features.py +295 -0
  155. gucmail/services/local_search.py +571 -0
  156. gucmail/services/mail_preferences.py +159 -0
  157. gucmail/services/message_columns.py +99 -0
  158. gucmail/services/message_export.py +146 -0
  159. gucmail/services/message_scan.py +47 -0
  160. gucmail/services/messages.py +521 -0
  161. gucmail/services/monitoring.py +1209 -0
  162. gucmail/services/monitoring_outbox.py +729 -0
  163. gucmail/services/monitoring_preferences.py +154 -0
  164. gucmail/services/notification_configuration.py +2206 -0
  165. gucmail/services/notification_rule_editing.py +88 -0
  166. gucmail/services/notification_simulation.py +84 -0
  167. gucmail/services/notifications.py +787 -0
  168. gucmail/services/ocr.py +550 -0
  169. gucmail/services/pim.py +166 -0
  170. gucmail/services/pim_preferences.py +236 -0
  171. gucmail/services/profiled_notifications.py +683 -0
  172. gucmail/services/quota.py +1050 -0
  173. gucmail/services/recipient_assistance.py +141 -0
  174. gucmail/services/recurrence.py +1776 -0
  175. gucmail/services/recurring.py +642 -0
  176. gucmail/services/restore_journal.py +247 -0
  177. gucmail/services/scheduler.py +1513 -0
  178. gucmail/services/search.py +1386 -0
  179. gucmail/services/semantic.py +568 -0
  180. gucmail/services/semantic_model.py +370 -0
  181. gucmail/services/semantic_search.py +157 -0
  182. gucmail/services/send_attempts.py +138 -0
  183. gucmail/services/shell_preferences.py +69 -0
  184. gucmail/services/shortcuts.py +141 -0
  185. gucmail/services/startup_runtime.py +408 -0
  186. gucmail/services/task_history.py +276 -0
  187. gucmail/services/task_recurrence.py +122 -0
  188. gucmail/services/tasks.py +791 -0
  189. gucmail/services/tasks_display.py +171 -0
  190. gucmail/services/ui_session.py +138 -0
  191. gucmail/services/unanswered.py +235 -0
  192. gucmail/services/watcher_runtime.py +103 -0
  193. gucmail/services/webhooks.py +1064 -0
  194. gucmail/services/windows_desktop.py +503 -0
  195. gucmail/settings.py +4054 -0
  196. gucmail/startup.py +884 -0
  197. gucmail/state.py +4190 -0
  198. gucmail/state_health.py +362 -0
  199. gucmail/toast_entry.py +91 -0
  200. gucmail/tui/__init__.py +10 -0
  201. gucmail/tui/activity_screen.py +955 -0
  202. gucmail/tui/app.py +13098 -0
  203. gucmail/tui/appearance_screen.py +1447 -0
  204. gucmail/tui/area_backends.py +3705 -0
  205. gucmail/tui/area_common.py +685 -0
  206. gucmail/tui/automatic_replies_screen.py +224 -0
  207. gucmail/tui/backup_screen.py +2460 -0
  208. gucmail/tui/branding.py +1414 -0
  209. gucmail/tui/branding_screen.py +750 -0
  210. gucmail/tui/composer_submission.py +373 -0
  211. gucmail/tui/contact_fields.py +103 -0
  212. gucmail/tui/contact_groups_screen.py +360 -0
  213. gucmail/tui/contact_history_screen.py +130 -0
  214. gucmail/tui/delegates_screen.py +137 -0
  215. gucmail/tui/desktop_setup_screen.py +133 -0
  216. gucmail/tui/diagnostics_screen.py +711 -0
  217. gucmail/tui/drafts_attachments_backend.py +1148 -0
  218. gucmail/tui/drafts_attachments_screen.py +1241 -0
  219. gucmail/tui/inbox_rules_screen.py +285 -0
  220. gucmail/tui/keyboard_bindings.py +44 -0
  221. gucmail/tui/keyboard_editor.py +476 -0
  222. gucmail/tui/layout_presets_screen.py +205 -0
  223. gucmail/tui/literal_select.py +23 -0
  224. gucmail/tui/literal_table.py +79 -0
  225. gucmail/tui/local_search_screen.py +562 -0
  226. gucmail/tui/message_columns_preview.py +91 -0
  227. gucmail/tui/message_columns_screen.py +193 -0
  228. gucmail/tui/notification_reader.py +105 -0
  229. gucmail/tui/notification_rule_builder.py +474 -0
  230. gucmail/tui/notification_settings_screen.py +4255 -0
  231. gucmail/tui/ocr_screen.py +236 -0
  232. gucmail/tui/offline_pim_screen.py +345 -0
  233. gucmail/tui/palette_routes.py +2078 -0
  234. gucmail/tui/pim_screens.py +6363 -0
  235. gucmail/tui/pim_submission.py +235 -0
  236. gucmail/tui/recipient_suggester.py +15 -0
  237. gucmail/tui/runtime.py +92 -0
  238. gucmail/tui/saved_search_screen.py +948 -0
  239. gucmail/tui/scheduled_screen.py +1216 -0
  240. gucmail/tui/semantic_screen.py +298 -0
  241. gucmail/tui/settings_form.py +152 -0
  242. gucmail/tui/settings_screen.py +2163 -0
  243. gucmail/tui/shortcuts_screen.py +453 -0
  244. gucmail/tui/stable_footer.py +58 -0
  245. gucmail/tui/startup_screen.py +194 -0
  246. gucmail/tui/storage_screen.py +1082 -0
  247. gucmail/tui/task_delete_screen.py +122 -0
  248. gucmail/tui/theme_repository.py +502 -0
  249. gucmail/tui/themes.py +2482 -0
  250. gucmail/tui/tutorial_screen.py +256 -0
  251. gucmail/tui/unanswered_screen.py +188 -0
  252. gucmail/tui/visual_language.py +187 -0
  253. gucmail/tui/write_coordinator.py +165 -0
  254. gucmail/watcher_entry.py +42 -0
  255. gucmail/windows_identity.py +78 -0
  256. gucmail-1.1.0.dist-info/METADATA +227 -0
  257. gucmail-1.1.0.dist-info/RECORD +259 -0
  258. gucmail-1.1.0.dist-info/WHEEL +4 -0
  259. gucmail-1.1.0.dist-info/entry_points.txt +2 -0
gucmail/__init__.py ADDED
@@ -0,0 +1,7 @@
1
+ """GUC Mail CLI public package metadata."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __all__ = ["__version__"]
6
+
7
+ __version__ = "1.1.0"
gucmail/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """Allow ``python -m gucmail`` to behave like the installed command."""
2
+
3
+ from gucmail.cli import app
4
+
5
+ if __name__ == "__main__":
6
+ app()
gucmail/actions.py ADDED
@@ -0,0 +1,200 @@
1
+ """Legacy action facade backed by the canonical universal-command registry.
2
+
3
+ ``ActionSpec`` and ``DEFAULT_ACTIONS`` remain import-compatible with the first release. All
4
+ safety, availability, shortcut, and Help metadata is projected from ``CORE_COMMANDS`` so the
5
+ compatibility API cannot drift into a second command catalog.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass, replace
11
+ from enum import StrEnum
12
+
13
+ from gucmail.command_catalog import CORE_COMMANDS
14
+ from gucmail.commands import CommandRegistry, CommandSpec, VisibilityLevel
15
+ from gucmail.models import SafetyClass
16
+
17
+
18
+ class UserMode(StrEnum):
19
+ BASIC = "basic"
20
+ ADVANCED = "advanced"
21
+ EXPERT = "expert"
22
+
23
+
24
+ _MODE_BY_VISIBILITY = {
25
+ VisibilityLevel.BASIC: UserMode.BASIC,
26
+ VisibilityLevel.ADVANCED: UserMode.ADVANCED,
27
+ VisibilityLevel.EXPERT: UserMode.EXPERT,
28
+ }
29
+
30
+
31
+ # Stable first-release IDs are aliases only. The values are canonical command IDs and therefore
32
+ # the sole source of behavioral metadata. Keeping this small mapping is what lets old callers
33
+ # migrate without preserving the obsolete parallel action definitions.
34
+ LEGACY_ACTION_ALIASES: dict[str, str] = {
35
+ "messages.list": "mail.open_inbox",
36
+ "messages.open": "mail.open_message",
37
+ "messages.reply": "mail.reply",
38
+ "messages.reply_all": "mail.reply_all",
39
+ "messages.forward": "mail.forward",
40
+ "messages.delete": "mail.delete",
41
+ "messages.hard_delete": "mail.permanently_delete",
42
+ "drafts.open": "drafts.open_drafts",
43
+ "scheduled.open": "scheduled.open",
44
+ "calendar.open": "calendar.open",
45
+ "contacts.open": "contacts.open",
46
+ "tasks.open": "tasks.open",
47
+ "search.open": "search.mail",
48
+ "backup.create": "backup.create",
49
+ "cleanup.plan": "cleanup.analyze",
50
+ "cleanup.execute": "cleanup.execute_cleanup_plan",
51
+ "ews.request_preview": "ews.request_preview",
52
+ }
53
+
54
+
55
+ _LEGACY_LABELS = {
56
+ "messages.list": "List messages",
57
+ "messages.open": "Open message",
58
+ "messages.reply": "Reply",
59
+ "messages.reply_all": "Reply all",
60
+ "messages.forward": "Forward",
61
+ "messages.delete": "Move to Deleted",
62
+ "messages.hard_delete": "Permanently delete",
63
+ "drafts.open": "Open draft",
64
+ "scheduled.open": "Open scheduled messages",
65
+ "calendar.open": "Open calendar",
66
+ "contacts.open": "Open contacts",
67
+ "tasks.open": "Open tasks",
68
+ "search.open": "Search",
69
+ "backup.create": "Create backup",
70
+ "cleanup.plan": "Plan cleanup",
71
+ "cleanup.execute": "Execute cleanup plan",
72
+ "ews.request_preview": "Preview typed EWS operation",
73
+ }
74
+
75
+
76
+ @dataclass(frozen=True, slots=True)
77
+ class ActionSpec:
78
+ """First-release view of one canonical command."""
79
+
80
+ name: str
81
+ label: str
82
+ area: str
83
+ mode: UserMode
84
+ safety: SafetyClass
85
+ online: bool
86
+ offline: bool
87
+ confirmation: bool = False
88
+ shortcut: str | None = None
89
+ help_topic: str | None = None
90
+
91
+ @property
92
+ def canonical_id(self) -> str:
93
+ return LEGACY_ACTION_ALIASES.get(self.name, self.name)
94
+
95
+ def to_command_spec(self) -> CommandSpec:
96
+ """Project this legacy ID without cloning behavioral metadata."""
97
+
98
+ try:
99
+ canonical = CORE_COMMANDS.get(self.canonical_id)
100
+ except KeyError:
101
+ # Retain the public constructor's historical behavior for third-party ActionSpec
102
+ # instances while all built-in actions take the canonical path above.
103
+ visibility = {
104
+ UserMode.BASIC: VisibilityLevel.BASIC,
105
+ UserMode.ADVANCED: VisibilityLevel.ADVANCED,
106
+ UserMode.EXPERT: VisibilityLevel.EXPERT,
107
+ }[self.mode]
108
+ mutates = self.safety is not SafetyClass.READ_ONLY
109
+ words = tuple(dict.fromkeys((self.area, *self.label.casefold().split())))
110
+ return CommandSpec(
111
+ command_id=self.name,
112
+ name=self.label,
113
+ description=f"{self.label} through the shared application action layer.",
114
+ category=self.area,
115
+ keywords=words,
116
+ aliases=(self.label, self.name.replace(".", " ").replace("_", " ")),
117
+ shortcut=self.shortcut,
118
+ safety=self.safety,
119
+ changes_server=mutates,
120
+ confirmation_required=self.confirmation,
121
+ preview_supported=self.confirmation,
122
+ offline=self.offline,
123
+ requires_connection=self.online and not self.offline,
124
+ visibility=visibility,
125
+ help_topic=self.help_topic,
126
+ handler_id=self.name,
127
+ )
128
+ return replace(
129
+ canonical,
130
+ command_id=self.name,
131
+ name=self.label,
132
+ related_commands=(),
133
+ follow_up_commands=(),
134
+ aliases=tuple(
135
+ dict.fromkeys(
136
+ (
137
+ self.label,
138
+ self.name.replace(".", " ").replace("_", " "),
139
+ *canonical.aliases,
140
+ )
141
+ )
142
+ ),
143
+ )
144
+
145
+
146
+ def _legacy_action(legacy_id: str, canonical_id: str) -> ActionSpec:
147
+ command = CORE_COMMANDS.get(canonical_id)
148
+ return ActionSpec(
149
+ name=legacy_id,
150
+ label=_LEGACY_LABELS[legacy_id],
151
+ area=command.category,
152
+ mode=_MODE_BY_VISIBILITY[command.visibility],
153
+ safety=command.safety,
154
+ online=command.requires_connection,
155
+ offline=command.offline,
156
+ confirmation=command.confirmation_required,
157
+ shortcut=command.shortcut,
158
+ help_topic=command.help_topic,
159
+ )
160
+
161
+
162
+ class ActionRegistry:
163
+ """Compatibility lookup whose rows are derived from a canonical registry."""
164
+
165
+ def __init__(
166
+ self,
167
+ aliases: dict[str, str] | None = None,
168
+ *,
169
+ commands: CommandRegistry = CORE_COMMANDS,
170
+ ) -> None:
171
+ mappings = aliases or LEGACY_ACTION_ALIASES
172
+ # Validate against the supplied registry before constructing the immutable projection.
173
+ for canonical_id in mappings.values():
174
+ commands.get(canonical_id)
175
+ self._actions = tuple(
176
+ _legacy_action(legacy_id, canonical_id) for legacy_id, canonical_id in mappings.items()
177
+ )
178
+ self._by_name = {action.name: action for action in self._actions}
179
+
180
+ def get(self, name: str) -> ActionSpec:
181
+ try:
182
+ return self._by_name[name]
183
+ except KeyError as exc:
184
+ raise KeyError(f"Unknown action: {name}") from exc
185
+
186
+ def visible(self, mode: UserMode) -> tuple[ActionSpec, ...]:
187
+ rank = {UserMode.BASIC: 0, UserMode.ADVANCED: 1, UserMode.EXPERT: 2}
188
+ return tuple(action for action in self._actions if rank[action.mode] <= rank[mode])
189
+
190
+ def all(self) -> tuple[ActionSpec, ...]:
191
+ return self._actions
192
+
193
+ def as_command_registry(self) -> CommandRegistry:
194
+ registry = CommandRegistry(action.to_command_spec() for action in self.all())
195
+ registry.assert_valid()
196
+ return registry
197
+
198
+
199
+ DEFAULT_ACTIONS = ActionRegistry()
200
+ DEFAULT_ACTION_COMMANDS = DEFAULT_ACTIONS.as_command_registry()