notionary 0.3.1__py3-none-any.whl → 0.4.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 (80) hide show
  1. notionary/__init__.py +6 -1
  2. notionary/blocks/enums.py +0 -6
  3. notionary/blocks/schemas.py +32 -78
  4. notionary/comments/schemas.py +2 -29
  5. notionary/data_source/properties/schemas.py +128 -107
  6. notionary/data_source/schemas.py +2 -2
  7. notionary/data_source/service.py +32 -23
  8. notionary/database/schemas.py +2 -2
  9. notionary/database/service.py +3 -5
  10. notionary/exceptions/__init__.py +6 -2
  11. notionary/exceptions/api.py +2 -2
  12. notionary/exceptions/base.py +1 -1
  13. notionary/exceptions/block_parsing.py +3 -3
  14. notionary/exceptions/data_source/builder.py +2 -2
  15. notionary/exceptions/data_source/properties.py +3 -3
  16. notionary/exceptions/file_upload.py +67 -0
  17. notionary/exceptions/properties.py +4 -4
  18. notionary/exceptions/search.py +4 -4
  19. notionary/file_upload/__init__.py +4 -0
  20. notionary/file_upload/client.py +124 -210
  21. notionary/file_upload/config/__init__.py +17 -0
  22. notionary/file_upload/config/config.py +32 -0
  23. notionary/file_upload/config/constants.py +16 -0
  24. notionary/file_upload/file/reader.py +28 -0
  25. notionary/file_upload/query/__init__.py +7 -0
  26. notionary/file_upload/query/builder.py +54 -0
  27. notionary/file_upload/query/models.py +37 -0
  28. notionary/file_upload/schemas.py +78 -0
  29. notionary/file_upload/service.py +152 -289
  30. notionary/file_upload/validation/factory.py +64 -0
  31. notionary/file_upload/validation/impl/file_name_length.py +23 -0
  32. notionary/file_upload/validation/models.py +124 -0
  33. notionary/file_upload/validation/port.py +7 -0
  34. notionary/file_upload/validation/service.py +17 -0
  35. notionary/file_upload/validation/validators/__init__.py +11 -0
  36. notionary/file_upload/validation/validators/file_exists.py +15 -0
  37. notionary/file_upload/validation/validators/file_extension.py +122 -0
  38. notionary/file_upload/validation/validators/file_name_length.py +21 -0
  39. notionary/file_upload/validation/validators/upload_limit.py +31 -0
  40. notionary/http/client.py +6 -22
  41. notionary/page/content/parser/factory.py +8 -5
  42. notionary/page/content/parser/parsers/audio.py +8 -33
  43. notionary/page/content/parser/parsers/embed.py +0 -2
  44. notionary/page/content/parser/parsers/file.py +8 -35
  45. notionary/page/content/parser/parsers/file_like_block.py +89 -0
  46. notionary/page/content/parser/parsers/image.py +8 -35
  47. notionary/page/content/parser/parsers/pdf.py +8 -35
  48. notionary/page/content/parser/parsers/video.py +8 -35
  49. notionary/page/content/renderer/renderers/audio.py +9 -21
  50. notionary/page/content/renderer/renderers/file.py +9 -21
  51. notionary/page/content/renderer/renderers/file_like_block.py +43 -0
  52. notionary/page/content/renderer/renderers/image.py +9 -21
  53. notionary/page/content/renderer/renderers/pdf.py +9 -21
  54. notionary/page/content/renderer/renderers/video.py +9 -21
  55. notionary/page/content/syntax/__init__.py +2 -1
  56. notionary/page/content/syntax/registry.py +38 -60
  57. notionary/page/properties/client.py +1 -1
  58. notionary/page/properties/{models.py → schemas.py} +93 -107
  59. notionary/page/properties/service.py +1 -1
  60. notionary/page/schemas.py +3 -3
  61. notionary/page/service.py +1 -1
  62. notionary/shared/entity/dto_parsers.py +1 -36
  63. notionary/shared/entity/entity_metadata_update_client.py +18 -4
  64. notionary/shared/entity/schemas.py +6 -6
  65. notionary/shared/entity/service.py +53 -30
  66. notionary/shared/models/file.py +34 -6
  67. notionary/shared/models/icon.py +5 -12
  68. notionary/user/bot.py +12 -12
  69. notionary/utils/decorators.py +8 -8
  70. notionary/workspace/__init__.py +2 -2
  71. notionary/workspace/query/__init__.py +2 -1
  72. notionary/workspace/query/service.py +3 -17
  73. notionary/workspace/service.py +45 -45
  74. {notionary-0.3.1.dist-info → notionary-0.4.0.dist-info}/METADATA +1 -1
  75. {notionary-0.3.1.dist-info → notionary-0.4.0.dist-info}/RECORD +77 -58
  76. notionary/file_upload/models.py +0 -69
  77. notionary/page/page_context.py +0 -50
  78. notionary/shared/models/cover.py +0 -20
  79. {notionary-0.3.1.dist-info → notionary-0.4.0.dist-info}/WHEEL +0 -0
  80. {notionary-0.3.1.dist-info → notionary-0.4.0.dist-info}/licenses/LICENSE +0 -0
notionary/__init__.py CHANGED
@@ -1,14 +1,19 @@
1
1
  from .data_source.service import NotionDataSource
2
2
  from .database.service import NotionDatabase
3
+ from .file_upload import FileUploadQuery, FileUploadQueryBuilder, NotionFileUpload
3
4
  from .page.content.markdown.builder import MarkdownBuilder
4
5
  from .page.service import NotionPage
5
- from .workspace import NotionWorkspace, NotionWorkspaceQueryConfigBuilder
6
+ from .workspace import NotionWorkspace, NotionWorkspaceQueryConfigBuilder, WorkspaceQueryConfig
6
7
 
7
8
  __all__ = [
9
+ "FileUploadQuery",
10
+ "FileUploadQueryBuilder",
8
11
  "MarkdownBuilder",
9
12
  "NotionDataSource",
10
13
  "NotionDatabase",
14
+ "NotionFileUpload",
11
15
  "NotionPage",
12
16
  "NotionWorkspace",
13
17
  "NotionWorkspaceQueryConfigBuilder",
18
+ "WorkspaceQueryConfig",
14
19
  ]
notionary/blocks/enums.py CHANGED
@@ -62,12 +62,6 @@ class BlockType(StrEnum):
62
62
  VIDEO = "video"
63
63
 
64
64
 
65
- class FileType(StrEnum):
66
- EXTERNAL = "external"
67
- FILE = "file"
68
- FILE_UPLOAD = "file_upload"
69
-
70
-
71
65
  class CodingLanguage(StrEnum):
72
66
  ABAP = "abap"
73
67
  ARDUINO = "arduino"
@@ -4,41 +4,38 @@ from typing import Annotated, Literal
4
4
 
5
5
  from pydantic import BaseModel, ConfigDict, Field
6
6
 
7
- from notionary.blocks.enums import BlockColor, BlockType, CodingLanguage, FileType
7
+ from notionary.blocks.enums import BlockColor, BlockType, CodingLanguage
8
8
  from notionary.blocks.rich_text.models import RichText
9
+ from notionary.shared.models.file import ExternalFile, FileUploadFile, NotionHostedFile
9
10
  from notionary.shared.models.icon import Icon
10
11
  from notionary.shared.models.parent import Parent
11
12
  from notionary.user.schemas import PartialUserDto
12
13
 
13
14
  # ============================================================================
14
- # File-related models
15
+ # File Data wrapper with caption
15
16
  # ============================================================================
16
17
 
17
18
 
18
- class ExternalFile(BaseModel):
19
- model_config = ConfigDict(from_attributes=True)
20
- url: str
19
+ class CaptionMixin(BaseModel):
20
+ caption: list[RichText] = Field(default_factory=list)
21
+ name: str | None = None
21
22
 
22
23
 
23
- class NotionHostedFile(BaseModel):
24
- model_config = ConfigDict(from_attributes=True)
25
- url: str
26
- expiry_time: str
24
+ class ExternalFileWithCaption(CaptionMixin, ExternalFile):
25
+ pass
27
26
 
28
27
 
29
- class FileUploadFile(BaseModel):
30
- model_config = ConfigDict(from_attributes=True)
31
- id: str
28
+ class NotionHostedFileWithCaption(CaptionMixin, NotionHostedFile):
29
+ pass
32
30
 
33
31
 
34
- class FileData(BaseModel):
35
- model_config = ConfigDict(from_attributes=True)
36
- caption: list[RichText] = Field(default_factory=list)
37
- type: FileType
38
- external: ExternalFile | None = None
39
- file: NotionHostedFile | None = None
40
- file_upload: FileUploadFile | None = None
41
- name: str | None = None
32
+ class FileUploadFileWithCaption(CaptionMixin, FileUploadFile):
33
+ pass
34
+
35
+
36
+ type FileWithCaption = Annotated[
37
+ ExternalFileWithCaption | NotionHostedFileWithCaption | FileUploadFileWithCaption, Field(discriminator="type")
38
+ ]
42
39
 
43
40
 
44
41
  # ============================================================================
@@ -65,24 +62,14 @@ class BaseBlock(BaseModel):
65
62
  # ============================================================================
66
63
 
67
64
 
68
- class AudioData(BaseModel):
69
- model_config = ConfigDict(from_attributes=True)
70
- caption: list[RichText] = Field(default_factory=list)
71
- type: FileType
72
- external: ExternalFile | None = None
73
- file: NotionHostedFile | None = None
74
- file_upload: FileUploadFile | None = None
75
- name: str | None = None
76
-
77
-
78
65
  class AudioBlock(BaseBlock):
79
66
  type: Literal[BlockType.AUDIO] = BlockType.AUDIO
80
- audio: AudioData
67
+ audio: FileWithCaption
81
68
 
82
69
 
83
70
  class CreateAudioBlock(BaseModel):
84
71
  type: Literal[BlockType.AUDIO] = BlockType.AUDIO
85
- audio: AudioData
72
+ audio: FileWithCaption
86
73
 
87
74
 
88
75
  # ============================================================================
@@ -90,8 +77,7 @@ class CreateAudioBlock(BaseModel):
90
77
  # ============================================================================
91
78
 
92
79
 
93
- class BookmarkData(BaseModel):
94
- caption: list[RichText] = Field(default_factory=list)
80
+ class BookmarkData(CaptionMixin):
95
81
  url: str
96
82
 
97
83
 
@@ -224,8 +210,7 @@ class CreateChildDatabaseBlock(BaseModel):
224
210
  # ============================================================================
225
211
 
226
212
 
227
- class CodeData(BaseModel):
228
- caption: list[RichText] = Field(default_factory=list)
213
+ class CodeData(CaptionMixin):
229
214
  rich_text: list[RichText]
230
215
  language: CodingLanguage = CodingLanguage.PLAIN_TEXT
231
216
 
@@ -311,9 +296,8 @@ class CreateDividerBlock(BaseModel):
311
296
  # ============================================================================
312
297
 
313
298
 
314
- class EmbedData(BaseModel):
299
+ class EmbedData(CaptionMixin):
315
300
  url: str
316
- caption: list[RichText] = Field(default_factory=list)
317
301
 
318
302
 
319
303
  class EmbedBlock(BaseBlock):
@@ -352,12 +336,12 @@ class CreateEquationBlock(BaseModel):
352
336
 
353
337
  class FileBlock(BaseBlock):
354
338
  type: Literal[BlockType.FILE] = BlockType.FILE
355
- file: FileData
339
+ file: FileWithCaption
356
340
 
357
341
 
358
342
  class CreateFileBlock(BaseModel):
359
343
  type: Literal[BlockType.FILE] = BlockType.FILE
360
- file: FileData
344
+ file: FileWithCaption
361
345
 
362
346
 
363
347
  # ============================================================================
@@ -416,24 +400,14 @@ CreateHeadingBlock = CreateHeading1Block | CreateHeading2Block | CreateHeading3B
416
400
  # ============================================================================
417
401
 
418
402
 
419
- class ImageData(BaseModel):
420
- model_config = ConfigDict(from_attributes=True)
421
- caption: list[RichText] = Field(default_factory=list)
422
- type: FileType
423
- external: ExternalFile | None = None
424
- file: NotionHostedFile | None = None
425
- file_upload: FileUploadFile | None = None
426
- name: str | None = None
427
-
428
-
429
403
  class ImageBlock(BaseBlock):
430
404
  type: Literal[BlockType.IMAGE] = BlockType.IMAGE
431
- image: ImageData
405
+ image: FileWithCaption
432
406
 
433
407
 
434
408
  class CreateImageBlock(BaseModel):
435
409
  type: Literal[BlockType.IMAGE] = BlockType.IMAGE
436
- image: ImageData
410
+ image: FileWithCaption
437
411
 
438
412
 
439
413
  # ============================================================================
@@ -497,24 +471,14 @@ class CreateParagraphBlock(BaseModel):
497
471
  # ============================================================================
498
472
 
499
473
 
500
- class PdfData(BaseModel):
501
- model_config = ConfigDict(from_attributes=True)
502
- caption: list[RichText] = Field(default_factory=list)
503
- type: FileType
504
- external: ExternalFile | None = None
505
- file: NotionHostedFile | None = None
506
- file_upload: FileUploadFile | None = None
507
- name: str | None = None
508
-
509
-
510
474
  class PdfBlock(BaseBlock):
511
475
  type: Literal[BlockType.PDF] = BlockType.PDF
512
- pdf: PdfData
476
+ pdf: FileWithCaption
513
477
 
514
478
 
515
479
  class CreatePdfBlock(BaseModel):
516
480
  type: Literal[BlockType.PDF] = BlockType.PDF
517
- pdf: PdfData
481
+ pdf: FileWithCaption
518
482
 
519
483
 
520
484
  # ============================================================================
@@ -669,31 +633,21 @@ class CreateToggleBlock(BaseModel):
669
633
  # ============================================================================
670
634
 
671
635
 
672
- class VideoData(BaseModel):
673
- model_config = ConfigDict(from_attributes=True)
674
- caption: list[RichText] = Field(default_factory=list)
675
- type: FileType
676
- external: ExternalFile | None = None
677
- file: NotionHostedFile | None = None
678
- file_upload: FileUploadFile | None = None
679
- name: str | None = None
680
-
681
-
682
636
  class VideoBlock(BaseBlock):
683
637
  type: Literal[BlockType.VIDEO] = BlockType.VIDEO
684
- video: VideoData
638
+ video: FileWithCaption
685
639
 
686
640
 
687
641
  class CreateVideoBlock(BaseModel):
688
642
  type: Literal[BlockType.VIDEO] = BlockType.VIDEO
689
- video: VideoData
643
+ video: FileWithCaption
690
644
 
691
645
 
692
646
  # ============================================================================
693
647
  # Block Union Type
694
648
  # ============================================================================
695
649
 
696
- Block = Annotated[
650
+ type Block = Annotated[
697
651
  (
698
652
  AudioBlock
699
653
  | BookmarkBlock
@@ -743,7 +697,7 @@ class BlockChildrenResponse(BaseModel):
743
697
  request_id: str
744
698
 
745
699
 
746
- BlockCreatePayload = Annotated[
700
+ type BlockCreatePayload = Annotated[
747
701
  (
748
702
  CreateAudioBlock
749
703
  | CreateBookmarkBlock
@@ -8,10 +8,6 @@ from pydantic import BaseModel, Field
8
8
 
9
9
  from notionary.blocks.rich_text.models import RichText
10
10
 
11
- # ---------------------------
12
- # Comment Parent
13
- # ---------------------------
14
-
15
11
 
16
12
  class CommentParentType(StrEnum):
17
13
  PAGE_ID = "page_id"
@@ -28,7 +24,7 @@ class BlockCommentParent(BaseModel):
28
24
  block_id: str
29
25
 
30
26
 
31
- CommentParent = PageCommentParent | BlockCommentParent
27
+ type CommentParent = PageCommentParent | BlockCommentParent
32
28
 
33
29
 
34
30
  # ---------------------------
@@ -96,7 +92,7 @@ class CustomCommentDisplayName(BaseModel):
96
92
  custom: CustomDisplayName
97
93
 
98
94
 
99
- CommentDisplayNameInput = IntegrationDisplayName | UserDisplayName | CustomCommentDisplayName
95
+ type CommentDisplayNameInput = IntegrationDisplayName | UserDisplayName | CustomCommentDisplayName
100
96
 
101
97
 
102
98
  class CommentDisplayNameDto(BaseModel):
@@ -189,8 +185,6 @@ class UserRef(BaseModel):
189
185
 
190
186
 
191
187
  class CommentDto(BaseModel):
192
- """Comment object as returned by the API"""
193
-
194
188
  object: Literal["comment"] = "comment"
195
189
  id: str
196
190
 
@@ -217,24 +211,3 @@ class CommentListResponse(BaseModel):
217
211
  results: list[CommentDto] = Field(default_factory=list)
218
212
  next_cursor: str | None = None
219
213
  has_more: bool = False
220
-
221
-
222
- # ---------------------------
223
- # Convenience Builders
224
- # ---------------------------
225
-
226
-
227
- class CommentDisplayNameBuilder:
228
- """Helper class to build display names easily"""
229
-
230
- @staticmethod
231
- def integration() -> IntegrationDisplayName:
232
- return IntegrationDisplayName()
233
-
234
- @staticmethod
235
- def user() -> UserDisplayName:
236
- return UserDisplayName()
237
-
238
- @staticmethod
239
- def custom(name: str) -> CustomCommentDisplayName:
240
- return CustomCommentDisplayName(custom=CustomDisplayName(name=name))
@@ -1,7 +1,7 @@
1
1
  from enum import StrEnum
2
- from typing import Annotated, Literal, TypeVar
2
+ from typing import Literal, TypeVar
3
3
 
4
- from pydantic import BaseModel, Field
4
+ from pydantic import BaseModel, ConfigDict, Field
5
5
 
6
6
  from notionary.shared.properties.type import PropertyType
7
7
  from notionary.shared.typings import JsonDict
@@ -126,109 +126,11 @@ class DataSourceStatusGroup(BaseModel):
126
126
  option_ids: list[str]
127
127
 
128
128
 
129
- # ============================================================================
130
- # Config Models
131
- # ============================================================================
132
-
133
-
134
129
  class DataSourceStatusConfig(BaseModel):
135
130
  options: list[DataSourcePropertyOption] = Field(default_factory=list)
136
131
  groups: list[DataSourceStatusGroup] = Field(default_factory=list)
137
132
 
138
133
 
139
- class DataSourceSelectConfig(BaseModel):
140
- options: list[DataSourcePropertyOption] = Field(default_factory=list)
141
-
142
-
143
- class DataSourceMultiSelectConfig(BaseModel):
144
- options: list[DataSourcePropertyOption] = Field(default_factory=list)
145
-
146
-
147
- class DataSourceRelationConfig(BaseModel):
148
- data_source_id: str
149
- type: RelationType = RelationType.SINGLE_PROPERTY
150
- single_property: JsonDict = Field(default_factory=dict)
151
-
152
-
153
- class DataSourceNumberConfig(BaseModel):
154
- format: NumberFormat
155
-
156
-
157
- class DataSourceFormulaConfig(BaseModel):
158
- expression: str
159
-
160
-
161
- class DataSourceUniqueIdConfig(BaseModel):
162
- prefix: str | None = None
163
-
164
-
165
- class DataSourceRollupConfig(BaseModel):
166
- function: RollupFunction
167
- relation_property_id: str
168
- relation_property_name: str
169
- rollup_property_id: str
170
- rollup_property_name: str
171
-
172
-
173
- class DataSourceDateConfig(BaseModel): ...
174
-
175
-
176
- class DataSourceCreatedTimeConfig(BaseModel): ...
177
-
178
-
179
- class DataSourceCreatedByConfig(BaseModel): ...
180
-
181
-
182
- class DataSourceLastEditedTimeConfig(BaseModel): ...
183
-
184
-
185
- class DataSourceLastEditedByConfig(BaseModel): ...
186
-
187
-
188
- class DataSourceLastVisitedTimeConfig(BaseModel): ...
189
-
190
-
191
- class DataSourceTitleConfig(BaseModel): ...
192
-
193
-
194
- class DataSourceRichTextConfig(BaseModel): ...
195
-
196
-
197
- class DataSourceURLConfig(BaseModel): ...
198
-
199
-
200
- class DataSourcePeopleConfig(BaseModel): ...
201
-
202
-
203
- class DataSourceCheckboxConfig(BaseModel): ...
204
-
205
-
206
- class DataSourceEmailConfig(BaseModel): ...
207
-
208
-
209
- class DataSourcePhoneNumberConfig(BaseModel): ...
210
-
211
-
212
- class DataSourceFilesConfig(BaseModel): ...
213
-
214
-
215
- class DataSourceButtonConfig(BaseModel): ...
216
-
217
-
218
- class DataSourceLocationConfig(BaseModel): ...
219
-
220
-
221
- class DataSourceVerificationConfig(BaseModel): ...
222
-
223
-
224
- class DataSourcePlaceConfig(BaseModel): ...
225
-
226
-
227
- # ============================================================================
228
- # Property Models
229
- # ============================================================================
230
-
231
-
232
134
  class DataSourceStatusProperty(DataSourceProperty):
233
135
  type: Literal[PropertyType.STATUS] = PropertyType.STATUS
234
136
  status: DataSourceStatusConfig = Field(default_factory=DataSourceStatusConfig)
@@ -242,6 +144,10 @@ class DataSourceStatusProperty(DataSourceProperty):
242
144
  return [group.name for group in self.status.groups]
243
145
 
244
146
 
147
+ class DataSourceSelectConfig(BaseModel):
148
+ options: list[DataSourcePropertyOption] = Field(default_factory=list)
149
+
150
+
245
151
  class DataSourceSelectProperty(DataSourceProperty):
246
152
  type: Literal[PropertyType.SELECT] = PropertyType.SELECT
247
153
  select: DataSourceSelectConfig = Field(default_factory=DataSourceSelectConfig)
@@ -251,6 +157,10 @@ class DataSourceSelectProperty(DataSourceProperty):
251
157
  return [option.name for option in self.select.options]
252
158
 
253
159
 
160
+ class DataSourceMultiSelectConfig(BaseModel):
161
+ options: list[DataSourcePropertyOption] = Field(default_factory=list)
162
+
163
+
254
164
  class DataSourceMultiSelectProperty(DataSourceProperty):
255
165
  type: Literal[PropertyType.MULTI_SELECT] = PropertyType.MULTI_SELECT
256
166
  multi_select: DataSourceMultiSelectConfig = Field(default_factory=DataSourceMultiSelectConfig)
@@ -260,6 +170,13 @@ class DataSourceMultiSelectProperty(DataSourceProperty):
260
170
  return [option.name for option in self.multi_select.options]
261
171
 
262
172
 
173
+ # https://developers.notion.com/reference/property-object
174
+ class DataSourceRelationConfig(BaseModel):
175
+ data_source_id: str | None = None
176
+ type: RelationType = RelationType.SINGLE_PROPERTY
177
+ single_property: JsonDict = Field(default_factory=dict)
178
+
179
+
263
180
  class DataSourceRelationProperty(DataSourceProperty):
264
181
  type: Literal[PropertyType.RELATION] = PropertyType.RELATION
265
182
  relation: DataSourceRelationConfig = Field(default_factory=DataSourceRelationConfig)
@@ -269,51 +186,90 @@ class DataSourceRelationProperty(DataSourceProperty):
269
186
  return self.relation.data_source_id
270
187
 
271
188
 
189
+ class DataSourceDateConfig(BaseModel): ...
190
+
191
+
272
192
  class DataSourceDateProperty(DataSourceProperty):
273
193
  type: Literal[PropertyType.DATE] = PropertyType.DATE
274
194
  date: DataSourceDateConfig = Field(default_factory=DataSourceDateConfig)
275
195
 
276
196
 
197
+ class DataSourceCreatedTimeConfig(BaseModel): ...
198
+
199
+
277
200
  class DataSourceCreatedTimeProperty(DataSourceProperty):
278
201
  type: Literal[PropertyType.CREATED_TIME] = PropertyType.CREATED_TIME
279
202
  created_time: DataSourceCreatedTimeConfig = Field(default_factory=DataSourceCreatedTimeConfig)
280
203
 
281
204
 
205
+ class DataSourceCreatedByConfig(BaseModel): ...
206
+
207
+
282
208
  class DataSourceCreatedByProperty(DataSourceProperty):
283
209
  type: Literal[PropertyType.CREATED_BY] = PropertyType.CREATED_BY
284
210
  created_by: DataSourceCreatedByConfig = Field(default_factory=DataSourceCreatedByConfig)
285
211
 
286
212
 
213
+ class DataSourceLastEditedTimeConfig(BaseModel): ...
214
+
215
+
287
216
  class DataSourceLastEditedTimeProperty(DataSourceProperty):
288
217
  type: Literal[PropertyType.LAST_EDITED_TIME] = PropertyType.LAST_EDITED_TIME
289
218
  last_edited_time: DataSourceLastEditedTimeConfig = Field(default_factory=DataSourceLastEditedTimeConfig)
290
219
 
291
220
 
221
+ class DataSourceLastEditedByConfig(BaseModel): ...
222
+
223
+
292
224
  class DataSourceLastEditedByProperty(DataSourceProperty):
293
225
  type: Literal[PropertyType.LAST_EDITED_BY] = PropertyType.LAST_EDITED_BY
294
226
  last_edited_by: DataSourceLastEditedByConfig = Field(default_factory=DataSourceLastEditedByConfig)
295
227
 
296
228
 
229
+ class DataSourceLastVisitedTimeConfig(BaseModel): ...
230
+
231
+
232
+ class DataSourceLastVisitedTimeProperty(DataSourceProperty):
233
+ type: Literal[PropertyType.LAST_VISITED_TIME] = PropertyType.LAST_VISITED_TIME
234
+ last_visited_time: DataSourceLastVisitedTimeConfig = Field(default_factory=DataSourceLastVisitedTimeConfig)
235
+
236
+
237
+ class DataSourceTitleConfig(BaseModel): ...
238
+
239
+
297
240
  class DataSourceTitleProperty(DataSourceProperty):
298
241
  type: Literal[PropertyType.TITLE] = PropertyType.TITLE
299
242
  title: DataSourceTitleConfig = Field(default_factory=DataSourceTitleConfig)
300
243
 
301
244
 
245
+ class DataSourceRichTextConfig(BaseModel): ...
246
+
247
+
302
248
  class DataSourceRichTextProperty(DataSourceProperty):
303
249
  type: Literal[PropertyType.RICH_TEXT] = PropertyType.RICH_TEXT
304
250
  rich_text: DataSourceRichTextConfig = Field(default_factory=DataSourceRichTextConfig)
305
251
 
306
252
 
253
+ class DataSourceURLConfig(BaseModel): ...
254
+
255
+
307
256
  class DataSourceURLProperty(DataSourceProperty):
308
257
  type: Literal[PropertyType.URL] = PropertyType.URL
309
258
  url: DataSourceURLConfig = Field(default_factory=DataSourceURLConfig)
310
259
 
311
260
 
261
+ class DataSourcePeopleConfig(BaseModel): ...
262
+
263
+
312
264
  class DataSourcePeopleProperty(DataSourceProperty):
313
265
  type: Literal[PropertyType.PEOPLE] = PropertyType.PEOPLE
314
266
  people: DataSourcePeopleConfig = Field(default_factory=DataSourcePeopleConfig)
315
267
 
316
268
 
269
+ class DataSourceNumberConfig(BaseModel):
270
+ format: NumberFormat
271
+
272
+
317
273
  class DataSourceNumberProperty(DataSourceProperty):
318
274
  type: Literal[PropertyType.NUMBER] = PropertyType.NUMBER
319
275
  number: DataSourceNumberConfig
@@ -323,26 +279,42 @@ class DataSourceNumberProperty(DataSourceProperty):
323
279
  return self.number.format
324
280
 
325
281
 
282
+ class DataSourceCheckboxConfig(BaseModel): ...
283
+
284
+
326
285
  class DataSourceCheckboxProperty(DataSourceProperty):
327
286
  type: Literal[PropertyType.CHECKBOX] = PropertyType.CHECKBOX
328
287
  checkbox: DataSourceCheckboxConfig = Field(default_factory=DataSourceCheckboxConfig)
329
288
 
330
289
 
290
+ class DataSourceEmailConfig(BaseModel): ...
291
+
292
+
331
293
  class DataSourceEmailProperty(DataSourceProperty):
332
294
  type: Literal[PropertyType.EMAIL] = PropertyType.EMAIL
333
295
  email: DataSourceEmailConfig = Field(default_factory=DataSourceEmailConfig)
334
296
 
335
297
 
298
+ class DataSourcePhoneNumberConfig(BaseModel): ...
299
+
300
+
336
301
  class DataSourcePhoneNumberProperty(DataSourceProperty):
337
302
  type: Literal[PropertyType.PHONE_NUMBER] = PropertyType.PHONE_NUMBER
338
303
  phone_number: DataSourcePhoneNumberConfig = Field(default_factory=DataSourcePhoneNumberConfig)
339
304
 
340
305
 
306
+ class DataSourceFilesConfig(BaseModel): ...
307
+
308
+
341
309
  class DataSourceFilesProperty(DataSourceProperty):
342
310
  type: Literal[PropertyType.FILES] = PropertyType.FILES
343
311
  files: DataSourceFilesConfig = Field(default_factory=DataSourceFilesConfig)
344
312
 
345
313
 
314
+ class DataSourceFormulaConfig(BaseModel):
315
+ expression: str
316
+
317
+
346
318
  class DataSourceFormulaProperty(DataSourceProperty):
347
319
  type: Literal[PropertyType.FORMULA] = PropertyType.FORMULA
348
320
  formula: DataSourceFormulaConfig
@@ -352,6 +324,14 @@ class DataSourceFormulaProperty(DataSourceProperty):
352
324
  return self.formula.expression
353
325
 
354
326
 
327
+ class DataSourceRollupConfig(BaseModel):
328
+ function: RollupFunction
329
+ relation_property_id: str
330
+ relation_property_name: str
331
+ rollup_property_id: str
332
+ rollup_property_name: str
333
+
334
+
355
335
  class DataSourceRollupProperty(DataSourceProperty):
356
336
  type: Literal[PropertyType.ROLLUP] = PropertyType.ROLLUP
357
337
  rollup: DataSourceRollupConfig
@@ -361,6 +341,10 @@ class DataSourceRollupProperty(DataSourceProperty):
361
341
  return self.rollup.function
362
342
 
363
343
 
344
+ class DataSourceUniqueIdConfig(BaseModel):
345
+ prefix: str | None = None
346
+
347
+
364
348
  class DataSourceUniqueIdProperty(DataSourceProperty):
365
349
  type: Literal[PropertyType.UNIQUE_ID] = PropertyType.UNIQUE_ID
366
350
  unique_id: DataSourceUniqueIdConfig = Field(default_factory=DataSourceUniqueIdConfig)
@@ -370,11 +354,43 @@ class DataSourceUniqueIdProperty(DataSourceProperty):
370
354
  return self.unique_id.prefix
371
355
 
372
356
 
373
- # ============================================================================
374
- # Discriminated Union
375
- # ============================================================================
357
+ class DataSourceButtonConfig(BaseModel): ...
358
+
359
+
360
+ class DataSourceButtonProperty(DataSourceProperty):
361
+ type: Literal[PropertyType.BUTTON] = PropertyType.BUTTON
362
+ button: DataSourceButtonConfig = Field(default_factory=DataSourceButtonConfig)
363
+
364
+
365
+ class DataSourceLocationConfig(BaseModel): ...
366
+
367
+
368
+ class DataSourceLocationProperty(DataSourceProperty):
369
+ type: Literal[PropertyType.LOCATION] = PropertyType.LOCATION
370
+ location: DataSourceLocationConfig = Field(default_factory=DataSourceLocationConfig)
371
+
372
+
373
+ class DataSourcePlaceConfig(BaseModel): ...
374
+
375
+
376
+ class DataSourcePlaceProperty(DataSourceProperty):
377
+ type: Literal[PropertyType.PLACE] = PropertyType.PLACE
378
+ place: DataSourcePlaceConfig = Field(default_factory=DataSourcePlaceConfig)
379
+
380
+
381
+ class DataSourceVerificationConfig(BaseModel): ...
382
+
383
+
384
+ class DataSourceVerificationProperty(DataSourceProperty):
385
+ type: Literal[PropertyType.VERIFICATION] = PropertyType.VERIFICATION
386
+ verification: DataSourceVerificationConfig = Field(default_factory=DataSourceVerificationConfig)
387
+
388
+
389
+ class DataSourceUnknownProperty(BaseModel):
390
+ model_config = ConfigDict(extra="allow")
391
+
376
392
 
377
- DiscriminatedDataSourceProperty = Annotated[
393
+ type AnyDataSourceProperty = (
378
394
  DataSourceStatusProperty
379
395
  | DataSourceSelectProperty
380
396
  | DataSourceMultiSelectProperty
@@ -384,6 +400,7 @@ DiscriminatedDataSourceProperty = Annotated[
384
400
  | DataSourceCreatedByProperty
385
401
  | DataSourceLastEditedTimeProperty
386
402
  | DataSourceLastEditedByProperty
403
+ | DataSourceLastVisitedTimeProperty
387
404
  | DataSourceTitleProperty
388
405
  | DataSourceRichTextProperty
389
406
  | DataSourceURLProperty
@@ -395,8 +412,12 @@ DiscriminatedDataSourceProperty = Annotated[
395
412
  | DataSourceFilesProperty
396
413
  | DataSourceFormulaProperty
397
414
  | DataSourceRollupProperty
398
- | DataSourceUniqueIdProperty,
399
- Field(discriminator="type"),
400
- ]
415
+ | DataSourceUniqueIdProperty
416
+ | DataSourceButtonProperty
417
+ | DataSourceLocationProperty
418
+ | DataSourcePlaceProperty
419
+ | DataSourceVerificationProperty
420
+ | DataSourceUnknownProperty
421
+ )
401
422
 
402
423
  DataSourcePropertyT = TypeVar("DataSourcePropertyT", bound=DataSourceProperty)