contextbase-plugin-reminders-local 0.2.6__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.
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.3
2
+ Name: contextbase-plugin-reminders-local
3
+ Version: 0.2.6
4
+ Summary: Apple Reminders local plugin for ContextBase
5
+ Author: Alizain Feerasta
6
+ Author-email: Alizain Feerasta <alizain.feerasta@gmail.com>
7
+ Requires-Dist: contextbase-shared-plugins==0.2.6
8
+ Requires-Dist: dagster==1.12.14
9
+ Requires-Dist: dagster-dlt==0.28.14
10
+ Requires-Dist: dlt>=1.26.0
11
+ Requires-Dist: pydantic>=2.12.0
12
+ Requires-Dist: sqlalchemy>=2.0.0
13
+ Requires-Python: >=3.14, <3.15
@@ -0,0 +1,16 @@
1
+ plugin_reminders_local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ plugin_reminders_local/binding_config.py,sha256=YBgQFhcTujAPYs94JeSJAgyCMQfTVj_aAbfVfoKMTjM,488
3
+ plugin_reminders_local/component.py,sha256=Mldw0sLSJ2aZD2pNj_yFsGuO2_ZCreuLJCUz7hlaIFw,3817
4
+ plugin_reminders_local/defs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ plugin_reminders_local/defs/defs.yaml,sha256=UJHl2J8qyF0WMEqRXdw8yoocNEWLZWHxRGAP00W8rbE,67
6
+ plugin_reminders_local/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ plugin_reminders_local/models/base.py,sha256=Fp7n4EfxQOxzqm34-D-rYyu60P88eZUIewCBNP_Iuc4,119
8
+ plugin_reminders_local/models/ctx.py,sha256=HwkxlYl3jcHtIq-EyrkNYpm-elGJ7N4IvkPD7Tm_t7o,14456
9
+ plugin_reminders_local/models/ingress.py,sha256=hB6vGyc0MRGT41igYdoD_XrmB9murM-Nk8JZHUj4TgY,31515
10
+ plugin_reminders_local/models/translators.py,sha256=d784hsQAKynd2klgdXVj1wJlybbXrQOqufbRPtTJBrI,27815
11
+ plugin_reminders_local/plugin.json,sha256=AsvjcdjaWFh-LBANQ8d0lqGkmYToA7Ccp_wj_M83lc0,88
12
+ plugin_reminders_local/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ plugin_reminders_local/sources/snapshot.py,sha256=k1rrBaVQXaiPPMHZZH7lpBIpWZAKUmkGwJ-v_gVvYU0,15492
14
+ contextbase_plugin_reminders_local-0.2.6.dist-info/WHEEL,sha256=i9aSRDivn5iP9LaR1BLQX2GNAuriQWPsFwbbWygTX2k,81
15
+ contextbase_plugin_reminders_local-0.2.6.dist-info/METADATA,sha256=qAL8DZgyjuTf4DfbvyKKzGYsDScCY1bdFGkEDUWFdc8,457
16
+ contextbase_plugin_reminders_local-0.2.6.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.15
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
File without changes
@@ -0,0 +1,20 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from pydantic import Field
6
+
7
+ from shared_plugins.bindings import BaseBindingConfigModel, ResolvedPath
8
+
9
+
10
+ class RemindersLocalBindingConfig(BaseBindingConfigModel):
11
+ stores_dir: ResolvedPath = Field(
12
+ default_factory=lambda: (
13
+ Path.home()
14
+ / "Library"
15
+ / "Group Containers"
16
+ / "group.com.apple.reminders"
17
+ / "Container_v1"
18
+ / "Stores"
19
+ ),
20
+ )
@@ -0,0 +1,113 @@
1
+ import dagster as dg
2
+ from dagster import AssetExecutionContext
3
+ from dagster_dlt import DagsterDltResource
4
+ from shared_plugins.automation import non_overlapping_automation_condition
5
+ from shared_plugins.bindings import parse_binding_config
6
+ from shared_plugins.control_plane import ControlPlaneClient
7
+ from shared_plugins.dlt import resolve_partition_binding, run_dlt_pipeline
8
+ from shared_plugins.naming import (
9
+ dagster_asset_group_name,
10
+ dagster_asset_tags,
11
+ dagster_dlt_asset_key,
12
+ dagster_partition_def_name,
13
+ dagster_pool_name,
14
+ dlt_source_name,
15
+ plugin_id_from_module,
16
+ )
17
+ from shared_plugins.resources import DLT_RESOURCE
18
+
19
+ from .binding_config import RemindersLocalBindingConfig
20
+ from .sources.snapshot import reminders_local_snapshot_source
21
+
22
+ PLUGIN_ID = plugin_id_from_module(__file__)
23
+ SNAPSHOT_JOB = "snapshot"
24
+
25
+ _SNAPSHOT_RESOURCE_NAMES = (
26
+ "list",
27
+ "reminder",
28
+ "hashtag_label",
29
+ "saved_attachment",
30
+ "alarm",
31
+ "shared_with",
32
+ "hashtag_join",
33
+ "recurrence_rule",
34
+ "attachment_entity",
35
+ )
36
+
37
+
38
+ def _build_snapshot_specs(
39
+ partitions_def: dg.PartitionsDefinition,
40
+ automation_condition: dg.AutomationCondition,
41
+ ) -> list[dg.AssetSpec]:
42
+ snapshot_source_name = dlt_source_name(PLUGIN_ID, SNAPSHOT_JOB)
43
+ shared = dict(
44
+ group_name=dagster_asset_group_name(PLUGIN_ID),
45
+ tags=dagster_asset_tags(PLUGIN_ID),
46
+ automation_condition=automation_condition,
47
+ partitions_def=partitions_def,
48
+ )
49
+ return [
50
+ dg.AssetSpec(
51
+ key=dagster_dlt_asset_key(snapshot_source_name, resource_name),
52
+ **shared,
53
+ )
54
+ for resource_name in _SNAPSHOT_RESOURCE_NAMES
55
+ ]
56
+
57
+
58
+ class RemindersLocalSyncComponent(dg.Component):
59
+ def build_defs(self, context: dg.ComponentLoadContext) -> dg.Definitions:
60
+ partitions_def = dg.DynamicPartitionsDefinition(
61
+ name=dagster_partition_def_name(PLUGIN_ID)
62
+ )
63
+ snapshot_specs = _build_snapshot_specs(
64
+ partitions_def=partitions_def,
65
+ automation_condition=non_overlapping_automation_condition(
66
+ dg.AutomationCondition.on_missing()
67
+ | dg.AutomationCondition.on_cron("*/15 * * * *")
68
+ ),
69
+ )
70
+
71
+ @dg.multi_asset(
72
+ specs=snapshot_specs,
73
+ can_subset=True,
74
+ name="reminders_local_snapshot",
75
+ pool=dagster_pool_name(PLUGIN_ID),
76
+ )
77
+ def reminders_local_snapshot_assets(
78
+ context: AssetExecutionContext,
79
+ dlt_resource: DagsterDltResource,
80
+ control_plane: dg.ResourceParam[ControlPlaneClient],
81
+ ):
82
+ binding = resolve_partition_binding(
83
+ context=context,
84
+ control_plane=control_plane,
85
+ plugin_id=PLUGIN_ID,
86
+ )
87
+ binding_id = str(binding.binding_id)
88
+ cfg = parse_binding_config(binding, RemindersLocalBindingConfig)
89
+
90
+ source = reminders_local_snapshot_source(binding_id, cfg)
91
+ yield from run_dlt_pipeline(
92
+ context=context,
93
+ dlt_resource=dlt_resource,
94
+ source=source,
95
+ plugin_id=PLUGIN_ID,
96
+ binding_id=binding_id,
97
+ job_name=SNAPSHOT_JOB,
98
+ )
99
+
100
+ automation_sensor = dg.AutomationConditionSensorDefinition(
101
+ name="reminders_local_automation_sensor",
102
+ target=dg.AssetSelection.assets(reminders_local_snapshot_assets),
103
+ default_status=dg.DefaultSensorStatus.RUNNING,
104
+ minimum_interval_seconds=30,
105
+ )
106
+
107
+ return dg.Definitions(
108
+ assets=[reminders_local_snapshot_assets],
109
+ sensors=[automation_sensor],
110
+ resources={
111
+ "dlt_resource": DLT_RESOURCE,
112
+ },
113
+ )
File without changes
@@ -0,0 +1 @@
1
+ type: plugin_reminders_local.component.RemindersLocalSyncComponent
File without changes
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from sqlalchemy.orm import DeclarativeBase
4
+
5
+
6
+ class Base(DeclarativeBase):
7
+ pass
@@ -0,0 +1,377 @@
1
+ """Pydantic CtxModels emitted by the Reminders plugin resources.
2
+
3
+ Shape mirrors the ingress ORM 1:1 for maximum source fidelity.
4
+ Operational/cached ``_ctx_*`` metadata is added by the CtxModel base.
5
+
6
+ Every ctx row carries ``store_guid`` — the Apple account-store UUID
7
+ (from the ``Data-<UUID>.sqlite`` filename). Multiple stores coexist
8
+ under one binding; ``store_guid`` tells you which account produced
9
+ the row.
10
+
11
+ Source primary keys use Apple UUIDs (``ck_identifier`` VARCHAR form)
12
+ which are globally unique across accounts, so ``store_guid`` is
13
+ provenance, not disambiguation.
14
+
15
+ Rows derived from the ``ZREMCDOBJECT`` polymorphic table are split into
16
+ narrow ctx models per ``Z_ENT`` (Alarm/Sharee/HashtagJoin/RecurrenceRule/
17
+ AttachmentEntity) — a single fat ingress row becomes one typed ctx row
18
+ matching its semantic entity.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from pydantic import AwareDatetime
24
+ from shared_plugins.models import CtxModel
25
+
26
+
27
+ class ListRow(CtxModel):
28
+ """From ZREMCDBASELIST. Regular lists (Z_ENT=3) and smart lists (Z_ENT=4)."""
29
+
30
+ store_guid: str
31
+ pk: int
32
+ ent: int | None = None
33
+ opt: int | None = None
34
+ guid: str # = ck_identifier, the CloudKit UUID
35
+ identifier: bytes | None = None # raw 16-byte UUID form
36
+ name: str | None = None
37
+ smart_list_type: str | None = None
38
+ sorting_style: str | None = None
39
+ badge_emblem: str | None = None
40
+ color: bytes | None = None # bplist NSColor
41
+ filter_data: bytes | None = None # smart-list predicate
42
+ account: int | None = None
43
+ parent_account: int | None = None
44
+ parent_list: int | None = None
45
+ parent_account1: int | None = None
46
+ parent_list1: int | None = None
47
+ is_group: int | None = None
48
+ is_pinned_by_current_user: int | None = None
49
+ sharing_status: int | None = None
50
+ should_categorize_grocery_items: int | None = None
51
+ should_suggest_conversion_to_grocery_list: int | None = None
52
+ showing_large_attachments: int | None = None
53
+ spotlight_index_count: int | None = None
54
+ da_display_order: int | None = None
55
+ da_is_event_only_container: int | None = None
56
+ da_is_immutable: int | None = None
57
+ da_is_notifications_collection: int | None = None
58
+ da_is_read_only: int | None = None
59
+ da_external_identification_tag: str | None = None
60
+ da_bulk_requests: bytes | None = None
61
+ marked_for_deletion: int | None = None
62
+ ck_dirty_flags: int | None = None
63
+ ck_cloud_state: int | None = None
64
+ ck_needs_initial_fetch_from_cloud: int | None = None
65
+ ck_needs_to_be_fetched_from_cloud: int | None = None
66
+ ck_zone_owner_name: str | None = None
67
+ ck_server_record_data: bytes | None = None
68
+ ck_server_share_data: bytes | None = None
69
+ shared_owner_address: str | None = None
70
+ shared_owner_name: str | None = None
71
+ shared_owner_identifier: bytes | None = None
72
+ pinned_date: AwareDatetime | None = None
73
+ last_user_access_date: AwareDatetime | None = None
74
+ external_identifier: str | None = None
75
+ external_modification_tag: str | None = None
76
+ da_push_key: str | None = None
77
+ da_sync_token: str | None = None
78
+ effective_minimum_supported_app_version: int | None = None
79
+ minimum_supported_app_version: int | None = None
80
+ memberships_of_reminders_in_sections_checksum: str | None = None
81
+ memberships_of_reminders_in_sections_as_data: bytes | None = None
82
+ resolution_token_map: bytes | None = None
83
+ resolution_token_map_v2_json: bytes | None = None
84
+ resolution_token_map_v3_json_data: bytes | None = None
85
+ section_ids_ordering_as_data: bytes | None = None
86
+ grocery_local_corrections_checksum: str | None = None
87
+ grocery_locale_id: str | None = None
88
+ grocery_local_corrections_as_data: bytes | None = None
89
+ most_recent_target_template_identifier: bytes | None = None
90
+ most_recent_target_template_identifier_by_current_user: bytes | None = None
91
+ reminder_ids_mergeable_ordering: bytes | None = None
92
+ reminder_ids_mergeable_ordering_v2_json: bytes | None = None
93
+ fok_parent_list: int | None = None
94
+ fok_parent_account: int | None = None
95
+ fok_parent_list1: int | None = None
96
+ fok_parent_account1: int | None = None
97
+
98
+
99
+ class ReminderRow(CtxModel):
100
+ """From ZREMCDREMINDER. One row per reminder (incl. subtasks)."""
101
+
102
+ store_guid: str
103
+ pk: int
104
+ ent: int | None = None
105
+ opt: int | None = None
106
+ guid: str # = ck_identifier
107
+ identifier: bytes | None = None
108
+ title: str | None = None
109
+ notes: str | None = None
110
+ notes_document: bytes | None = None # gzipped NSAttributedString
111
+ title_document: bytes | None = None # gzipped NSAttributedString
112
+ priority: int | None = None
113
+ flagged: int | None = None
114
+ completed: int | None = None
115
+ completion_date: AwareDatetime | None = None
116
+ creation_date: AwareDatetime | None = None
117
+ last_modified_date: AwareDatetime | None = None
118
+ due_date: AwareDatetime | None = None
119
+ display_date_date: AwareDatetime | None = None
120
+ display_date_is_all_day: int | None = None
121
+ display_date_timezone: str | None = None
122
+ display_date_updated_for_seconds_from_gmt: int | None = None
123
+ alternative_display_date_date_for_calendar: AwareDatetime | None = None
124
+ start_date: AwareDatetime | None = None
125
+ all_day: int | None = None
126
+ timezone: str | None = None
127
+ last_banner_presentation_date: AwareDatetime | None = None
128
+ list_pk: int | None = None
129
+ list_guid: str | None = None # resolved from ZLIST via list_lookup
130
+ parent_reminder_pk: int | None = None
131
+ parent_reminder_guid: str | None = (
132
+ None # resolved; also ck_parent_reminder_identifier
133
+ )
134
+ ck_parent_reminder_identifier: str | None = None
135
+ account: int | None = None
136
+ ics_display_order: int | None = None
137
+ ics_url: str | None = None
138
+ imported_ics_data: bytes | None = None
139
+ da_calendar_item_unique_identifier: str | None = None
140
+ shared_to_me_reminder_placeholder: int | None = None
141
+ z15_reminders: int | None = None
142
+ fok_list: int | None = None
143
+ marked_for_deletion: int | None = None
144
+ ck_dirty_flags: int | None = None
145
+ ck_cloud_state: int | None = None
146
+ ck_needs_initial_fetch_from_cloud: int | None = None
147
+ ck_needs_to_be_fetched_from_cloud: int | None = None
148
+ ck_zone_owner_name: str | None = None
149
+ ck_server_record_data: bytes | None = None
150
+ ck_server_share_data: bytes | None = None
151
+ contact_handles: bytes | None = None
152
+ due_date_delta_alerts_data: bytes | None = None
153
+ siri_found_in_apps_data: bytes | None = None
154
+ user_activity: bytes | None = None
155
+ external_identifier: str | None = None
156
+ external_modification_tag: str | None = None
157
+ da_push_key: str | None = None
158
+ da_sync_token: str | None = None
159
+ effective_minimum_supported_app_version: int | None = None
160
+ minimum_supported_app_version: int | None = None
161
+ resolution_token_map: bytes | None = None
162
+ resolution_token_map_v2_json: bytes | None = None
163
+ resolution_token_map_v3_json_data: bytes | None = None
164
+ spotlight_index_count: int | None = None
165
+
166
+
167
+ class HashtagLabelRow(CtxModel):
168
+ """From ZREMCDHASHTAGLABEL. Tag vocabulary."""
169
+
170
+ store_guid: str
171
+ pk: int
172
+ ent: int | None = None
173
+ opt: int | None = None
174
+ name: str | None = None
175
+ canonical_name: str | None = None
176
+ account_identifier: str | None = None
177
+ first_occurrence_creation_date: AwareDatetime | None = None
178
+ recency_date: AwareDatetime | None = None
179
+ uuid_for_change_tracking: bytes | None = None
180
+
181
+
182
+ class SavedAttachmentRow(CtxModel):
183
+ """From ZREMCDSAVEDATTACHMENT. File-attachment metadata (content lives in filesystem)."""
184
+
185
+ store_guid: str
186
+ pk: int
187
+ ent: int | None = None
188
+ opt: int | None = None
189
+ guid: str # = ck_identifier
190
+ identifier: bytes | None = None
191
+ reminder_pk: int | None = None
192
+ reminder_guid: str | None = None # resolved via reminder_lookup
193
+ filename: str | None = None
194
+ uti: str | None = None
195
+ attachment_type_raw_value: str | None = None
196
+ sha512_sum: str | None = None
197
+ metadata_blob: bytes | None = None # bplist dict
198
+ last_modified_date: AwareDatetime | None = None
199
+ account: int | None = None
200
+ marked_for_deletion: int | None = None
201
+ ck_dirty_flags: int | None = None
202
+ ck_cloud_state: int | None = None
203
+ ck_needs_initial_fetch_from_cloud: int | None = None
204
+ ck_needs_to_be_fetched_from_cloud: int | None = None
205
+ ck_zone_owner_name: str | None = None
206
+ ck_server_record_data: bytes | None = None
207
+ ck_server_share_data: bytes | None = None
208
+ external_identifier: str | None = None
209
+ external_modification_tag: str | None = None
210
+ da_push_key: str | None = None
211
+ da_sync_token: str | None = None
212
+ effective_minimum_supported_app_version: int | None = None
213
+ minimum_supported_app_version: int | None = None
214
+ resolution_token_map: bytes | None = None
215
+ resolution_token_map_v2_json: bytes | None = None
216
+ resolution_token_map_v3_json_data: bytes | None = None
217
+
218
+
219
+ class AlarmRow(CtxModel):
220
+ """From ZREMCDOBJECT where Z_ENT=16 (REMCDAlarm). Flattens the linked
221
+ trigger row (Z_ENT=18 date / 19 location / 20 time-interval) into
222
+ ``trigger_*`` fields so consumers see one row per alarm with the
223
+ trigger semantics inlined.
224
+ """
225
+
226
+ store_guid: str
227
+ pk: int
228
+ ent: int # = 16
229
+ opt: int | None = None
230
+ guid: str # alarm ck_identifier
231
+ identifier: bytes | None = None
232
+ reminder_pk: int | None = None
233
+ reminder_guid: str | None = None
234
+ trigger_pk: int | None = None
235
+ z17_trigger_pk: int | None = None
236
+ acknowledged_date: AwareDatetime | None = None
237
+ alarm_uid: str | None = None
238
+ original_alarm_uid: str | None = None
239
+ is_extraneous: int | None = None
240
+ due_date_resolution_token_as_nonce: float | None = None
241
+ # Inlined from trigger row
242
+ trigger_ent: int | None = None # 18, 19, 20
243
+ trigger_type: str | None = None # 'date' | 'location' | 'time_interval'
244
+ trigger_guid: str | None = None
245
+ trigger_identifier: bytes | None = None
246
+ # Date trigger (ent=18)
247
+ trigger_date_components_data: bytes | None = None # JSON NSDateComponents
248
+ # Location trigger (ent=19)
249
+ trigger_latitude: float | None = None
250
+ trigger_longitude: float | None = None
251
+ trigger_radius: float | None = None
252
+ trigger_proximity: int | None = None
253
+ trigger_address: str | None = None
254
+ trigger_contact_label: str | None = None
255
+ trigger_location_uid: str | None = None
256
+ trigger_reference_frame_string: str | None = None
257
+ trigger_routing: str | None = None
258
+ trigger_title: str | None = None
259
+ trigger_mapkit_handle: bytes | None = None
260
+ # Time interval trigger (ent=20)
261
+ trigger_time_interval: float | None = None
262
+ # CK / sync
263
+ account: int | None = None
264
+ marked_for_deletion: int | None = None
265
+ ck_dirty_flags: int | None = None
266
+ ck_cloud_state: int | None = None
267
+ ck_server_record_data: bytes | None = None
268
+
269
+
270
+ class SharedWithRow(CtxModel):
271
+ """From ZREMCDOBJECT where Z_ENT=37 (REMCDSharee)."""
272
+
273
+ store_guid: str
274
+ pk: int
275
+ ent: int # = 37
276
+ opt: int | None = None
277
+ guid: str # = ck_identifier
278
+ identifier: bytes | None = None
279
+ list_pk: int | None = None
280
+ list_guid: str | None = None
281
+ access_level: int | None = None
282
+ status1: int | None = None
283
+ first_name: str | None = None
284
+ last_name: str | None = None
285
+ middle_name: str | None = None
286
+ name_prefix: str | None = None
287
+ name_suffix: str | None = None
288
+ nickname: str | None = None
289
+ display_name: str | None = None
290
+ address1: str | None = None
291
+ account: int | None = None
292
+ marked_for_deletion: int | None = None
293
+ ck_dirty_flags: int | None = None
294
+ ck_cloud_state: int | None = None
295
+
296
+
297
+ class HashtagJoinRow(CtxModel):
298
+ """From ZREMCDOBJECT where Z_ENT=33 (REMCDHashtag). Joins a reminder
299
+ to a label (from ZREMCDHASHTAGLABEL). 0 rows in the probed DB — shape
300
+ inferred from schema only.
301
+ """
302
+
303
+ store_guid: str
304
+ pk: int
305
+ ent: int # = 33
306
+ opt: int | None = None
307
+ guid: str
308
+ identifier: bytes | None = None
309
+ hashtag_label_pk: int | None = None
310
+ hashtag_label_name: str | None = None # resolved via hashtag_label_lookup
311
+ reminder_pk: int | None = None # via reminder3_pk/reminder4_pk/reminder5_pk
312
+ reminder_guid: str | None = None
313
+ account: int | None = None
314
+ marked_for_deletion: int | None = None
315
+ ck_dirty_flags: int | None = None
316
+ ck_cloud_state: int | None = None
317
+
318
+
319
+ class RecurrenceRuleRow(CtxModel):
320
+ """From ZREMCDOBJECT where Z_ENT=35 (REMCDRecurrenceRule). 0 rows in
321
+ the probed DB — shape inferred from schema only."""
322
+
323
+ store_guid: str
324
+ pk: int
325
+ ent: int # = 35
326
+ opt: int | None = None
327
+ guid: str
328
+ identifier: bytes | None = None
329
+ reminder_pk: int | None = None
330
+ reminder_guid: str | None = None
331
+ frequency: int | None = None
332
+ interval: int | None = None
333
+ first_day_of_the_week: int | None = None
334
+ occurrence_count: int | None = None
335
+ end_date: AwareDatetime | None = None
336
+ days_of_the_week: bytes | None = None
337
+ days_of_the_month: bytes | None = None
338
+ days_of_the_year: bytes | None = None
339
+ months_of_the_year: bytes | None = None
340
+ weeks_of_the_year: bytes | None = None
341
+ set_positions: bytes | None = None
342
+ account: int | None = None
343
+ marked_for_deletion: int | None = None
344
+ ck_dirty_flags: int | None = None
345
+ ck_cloud_state: int | None = None
346
+
347
+
348
+ class AttachmentEntityRow(CtxModel):
349
+ """From ZREMCDOBJECT where Z_ENT in (24,25,26,27) — File/Audio/Image/URL
350
+ attachment subtypes unified into one resource with ``attachment_type``
351
+ discriminator. 0 rows in probed DB — shape inferred from schema.
352
+ """
353
+
354
+ store_guid: str
355
+ pk: int
356
+ ent: int # 24/25/26/27
357
+ attachment_type: str # 'file' | 'audio' | 'image' | 'url'
358
+ opt: int | None = None
359
+ guid: str
360
+ identifier: bytes | None = None
361
+ reminder_pk: int | None = None
362
+ reminder_guid: str | None = None
363
+ filename: str | None = None
364
+ uti: str | None = None
365
+ file_size: int | None = None
366
+ height: int | None = None
367
+ width: int | None = None
368
+ length: float | None = None # audio duration
369
+ sha512_sum: str | None = None
370
+ transcribed_text: str | None = None
371
+ url: str | None = None
372
+ host_url: str | None = None
373
+ metadata_blob: bytes | None = None
374
+ account: int | None = None
375
+ marked_for_deletion: int | None = None
376
+ ck_dirty_flags: int | None = None
377
+ ck_cloud_state: int | None = None