notionary 0.2.19__py3-none-any.whl → 0.2.21__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 (205) hide show
  1. notionary/__init__.py +8 -4
  2. notionary/base_notion_client.py +3 -1
  3. notionary/blocks/__init__.py +2 -91
  4. notionary/blocks/_bootstrap.py +263 -0
  5. notionary/blocks/audio/__init__.py +8 -2
  6. notionary/blocks/audio/audio_element.py +42 -104
  7. notionary/blocks/audio/audio_markdown_node.py +3 -1
  8. notionary/blocks/audio/audio_models.py +6 -55
  9. notionary/blocks/base_block_element.py +30 -0
  10. notionary/blocks/bookmark/__init__.py +9 -2
  11. notionary/blocks/bookmark/bookmark_element.py +46 -139
  12. notionary/blocks/bookmark/bookmark_markdown_node.py +3 -1
  13. notionary/blocks/bookmark/bookmark_models.py +15 -0
  14. notionary/blocks/breadcrumbs/__init__.py +17 -0
  15. notionary/blocks/breadcrumbs/breadcrumb_element.py +39 -0
  16. notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +32 -0
  17. notionary/blocks/breadcrumbs/breadcrumb_models.py +12 -0
  18. notionary/blocks/bulleted_list/__init__.py +12 -2
  19. notionary/blocks/bulleted_list/bulleted_list_element.py +40 -55
  20. notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +2 -1
  21. notionary/blocks/bulleted_list/bulleted_list_models.py +18 -0
  22. notionary/blocks/callout/__init__.py +9 -2
  23. notionary/blocks/callout/callout_element.py +40 -89
  24. notionary/blocks/callout/callout_markdown_node.py +3 -1
  25. notionary/blocks/callout/callout_models.py +33 -0
  26. notionary/blocks/child_database/__init__.py +7 -0
  27. notionary/blocks/child_database/child_database_models.py +19 -0
  28. notionary/blocks/child_page/__init__.py +9 -0
  29. notionary/blocks/child_page/child_page_models.py +12 -0
  30. notionary/blocks/{shared/block_client.py → client.py} +55 -54
  31. notionary/blocks/code/__init__.py +6 -2
  32. notionary/blocks/code/code_element.py +53 -187
  33. notionary/blocks/code/code_markdown_node.py +13 -13
  34. notionary/blocks/code/code_models.py +94 -0
  35. notionary/blocks/column/__init__.py +25 -1
  36. notionary/blocks/column/column_element.py +40 -314
  37. notionary/blocks/column/column_list_element.py +37 -0
  38. notionary/blocks/column/column_list_markdown_node.py +50 -0
  39. notionary/blocks/column/column_markdown_node.py +59 -0
  40. notionary/blocks/column/column_models.py +26 -0
  41. notionary/blocks/divider/__init__.py +9 -2
  42. notionary/blocks/divider/divider_element.py +26 -49
  43. notionary/blocks/divider/divider_markdown_node.py +2 -1
  44. notionary/blocks/divider/divider_models.py +12 -0
  45. notionary/blocks/embed/__init__.py +9 -2
  46. notionary/blocks/embed/embed_element.py +47 -114
  47. notionary/blocks/embed/embed_markdown_node.py +3 -1
  48. notionary/blocks/embed/embed_models.py +14 -0
  49. notionary/blocks/equation/__init__.py +14 -0
  50. notionary/blocks/equation/equation_element.py +80 -0
  51. notionary/blocks/equation/equation_element_markdown_node.py +36 -0
  52. notionary/blocks/equation/equation_models.py +11 -0
  53. notionary/blocks/file/__init__.py +25 -0
  54. notionary/blocks/file/file_element.py +93 -0
  55. notionary/blocks/file/file_element_markdown_node.py +35 -0
  56. notionary/blocks/file/file_element_models.py +39 -0
  57. notionary/blocks/heading/__init__.py +16 -2
  58. notionary/blocks/heading/heading_element.py +67 -72
  59. notionary/blocks/heading/heading_markdown_node.py +2 -1
  60. notionary/blocks/heading/heading_models.py +29 -0
  61. notionary/blocks/image_block/__init__.py +13 -0
  62. notionary/blocks/image_block/image_element.py +84 -0
  63. notionary/blocks/{image → image_block}/image_markdown_node.py +3 -1
  64. notionary/blocks/image_block/image_models.py +10 -0
  65. notionary/blocks/models.py +172 -0
  66. notionary/blocks/numbered_list/__init__.py +12 -2
  67. notionary/blocks/numbered_list/numbered_list_element.py +33 -58
  68. notionary/blocks/numbered_list/numbered_list_markdown_node.py +3 -1
  69. notionary/blocks/numbered_list/numbered_list_models.py +17 -0
  70. notionary/blocks/paragraph/__init__.py +12 -2
  71. notionary/blocks/paragraph/paragraph_element.py +27 -69
  72. notionary/blocks/paragraph/paragraph_markdown_node.py +2 -1
  73. notionary/blocks/paragraph/paragraph_models.py +16 -0
  74. notionary/blocks/pdf/__init__.py +13 -0
  75. notionary/blocks/pdf/pdf_element.py +91 -0
  76. notionary/blocks/pdf/pdf_markdown_node.py +35 -0
  77. notionary/blocks/pdf/pdf_models.py +11 -0
  78. notionary/blocks/quote/__init__.py +11 -2
  79. notionary/blocks/quote/quote_element.py +31 -65
  80. notionary/blocks/quote/quote_markdown_node.py +4 -1
  81. notionary/blocks/quote/quote_models.py +18 -0
  82. notionary/blocks/registry/__init__.py +4 -0
  83. notionary/blocks/registry/block_registry.py +75 -91
  84. notionary/blocks/registry/block_registry_builder.py +107 -59
  85. notionary/blocks/rich_text/__init__.py +33 -0
  86. notionary/blocks/rich_text/rich_text_models.py +188 -0
  87. notionary/blocks/rich_text/text_inline_formatter.py +125 -0
  88. notionary/blocks/table/__init__.py +16 -2
  89. notionary/blocks/table/table_element.py +48 -241
  90. notionary/blocks/table/table_markdown_node.py +2 -1
  91. notionary/blocks/table/table_models.py +28 -0
  92. notionary/blocks/table_of_contents/__init__.py +19 -0
  93. notionary/blocks/table_of_contents/table_of_contents_element.py +51 -0
  94. notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +35 -0
  95. notionary/blocks/table_of_contents/table_of_contents_models.py +18 -0
  96. notionary/blocks/todo/__init__.py +9 -2
  97. notionary/blocks/todo/todo_element.py +38 -95
  98. notionary/blocks/todo/todo_markdown_node.py +2 -1
  99. notionary/blocks/todo/todo_models.py +19 -0
  100. notionary/blocks/toggle/__init__.py +13 -3
  101. notionary/blocks/toggle/toggle_element.py +57 -264
  102. notionary/blocks/toggle/toggle_markdown_node.py +24 -14
  103. notionary/blocks/toggle/toggle_models.py +17 -0
  104. notionary/blocks/toggleable_heading/__init__.py +6 -2
  105. notionary/blocks/toggleable_heading/toggleable_heading_element.py +74 -244
  106. notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +26 -18
  107. notionary/blocks/types.py +61 -0
  108. notionary/blocks/video/__init__.py +8 -2
  109. notionary/blocks/video/video_element.py +67 -143
  110. notionary/blocks/video/video_element_models.py +10 -0
  111. notionary/blocks/video/video_markdown_node.py +3 -1
  112. notionary/database/client.py +3 -8
  113. notionary/database/database.py +13 -14
  114. notionary/database/database_filter_builder.py +2 -2
  115. notionary/database/database_provider.py +5 -4
  116. notionary/database/models.py +337 -0
  117. notionary/database/notion_database.py +6 -7
  118. notionary/file_upload/client.py +5 -7
  119. notionary/file_upload/models.py +2 -1
  120. notionary/file_upload/notion_file_upload.py +2 -3
  121. notionary/markdown/markdown_builder.py +722 -0
  122. notionary/markdown/markdown_document_model.py +228 -0
  123. notionary/{blocks → markdown}/markdown_node.py +1 -0
  124. notionary/models/notion_database_response.py +0 -338
  125. notionary/page/client.py +9 -10
  126. notionary/page/models.py +327 -0
  127. notionary/page/notion_page.py +99 -52
  128. notionary/page/notion_text_length_utils.py +119 -0
  129. notionary/page/{content/page_content_writer.py → page_content_writer.py} +88 -38
  130. notionary/page/reader/handler/__init__.py +17 -0
  131. notionary/page/reader/handler/base_block_renderer.py +44 -0
  132. notionary/page/reader/handler/block_processing_context.py +35 -0
  133. notionary/page/reader/handler/block_rendering_context.py +43 -0
  134. notionary/page/reader/handler/column_list_renderer.py +51 -0
  135. notionary/page/reader/handler/column_renderer.py +60 -0
  136. notionary/page/reader/handler/line_renderer.py +60 -0
  137. notionary/page/reader/handler/toggle_renderer.py +69 -0
  138. notionary/page/reader/handler/toggleable_heading_renderer.py +89 -0
  139. notionary/page/reader/page_content_retriever.py +69 -0
  140. notionary/page/search_filter_builder.py +2 -1
  141. notionary/page/writer/handler/__init__.py +22 -0
  142. notionary/page/writer/handler/code_handler.py +100 -0
  143. notionary/page/writer/handler/column_handler.py +141 -0
  144. notionary/page/writer/handler/column_list_handler.py +139 -0
  145. notionary/page/writer/handler/line_handler.py +35 -0
  146. notionary/page/writer/handler/line_processing_context.py +54 -0
  147. notionary/page/writer/handler/regular_line_handler.py +92 -0
  148. notionary/page/writer/handler/table_handler.py +130 -0
  149. notionary/page/writer/handler/toggle_handler.py +153 -0
  150. notionary/page/writer/handler/toggleable_heading_handler.py +167 -0
  151. notionary/page/writer/markdown_to_notion_converter.py +76 -0
  152. notionary/telemetry/__init__.py +2 -2
  153. notionary/telemetry/service.py +4 -3
  154. notionary/user/__init__.py +2 -2
  155. notionary/user/base_notion_user.py +2 -1
  156. notionary/user/client.py +2 -3
  157. notionary/user/models.py +1 -0
  158. notionary/user/notion_bot_user.py +4 -5
  159. notionary/user/notion_user.py +3 -4
  160. notionary/user/notion_user_manager.py +3 -2
  161. notionary/user/notion_user_provider.py +1 -1
  162. notionary/util/__init__.py +3 -2
  163. notionary/util/fuzzy.py +2 -1
  164. notionary/util/logging_mixin.py +2 -2
  165. notionary/util/singleton_metaclass.py +1 -1
  166. notionary/workspace.py +3 -2
  167. {notionary-0.2.19.dist-info → notionary-0.2.21.dist-info}/METADATA +12 -8
  168. notionary-0.2.21.dist-info/RECORD +185 -0
  169. notionary/blocks/document/__init__.py +0 -7
  170. notionary/blocks/document/document_element.py +0 -102
  171. notionary/blocks/document/document_markdown_node.py +0 -31
  172. notionary/blocks/image/__init__.py +0 -7
  173. notionary/blocks/image/image_element.py +0 -151
  174. notionary/blocks/markdown_builder.py +0 -356
  175. notionary/blocks/mention/__init__.py +0 -7
  176. notionary/blocks/mention/mention_element.py +0 -229
  177. notionary/blocks/mention/mention_markdown_node.py +0 -38
  178. notionary/blocks/prompts/element_prompt_builder.py +0 -83
  179. notionary/blocks/prompts/element_prompt_content.py +0 -41
  180. notionary/blocks/shared/__init__.py +0 -0
  181. notionary/blocks/shared/models.py +0 -713
  182. notionary/blocks/shared/notion_block_element.py +0 -37
  183. notionary/blocks/shared/text_inline_formatter.py +0 -262
  184. notionary/blocks/shared/text_inline_formatter_new.py +0 -139
  185. notionary/blocks/toggleable_heading/toggleable_heading_models.py +0 -0
  186. notionary/database/models/page_result.py +0 -10
  187. notionary/elements/__init__.py +0 -0
  188. notionary/models/notion_block_response.py +0 -264
  189. notionary/models/notion_page_response.py +0 -78
  190. notionary/models/search_response.py +0 -0
  191. notionary/page/__init__.py +0 -0
  192. notionary/page/content/notion_text_length_utils.py +0 -87
  193. notionary/page/content/page_content_retriever.py +0 -60
  194. notionary/page/formatting/line_processor.py +0 -153
  195. notionary/page/formatting/markdown_to_notion_converter.py +0 -153
  196. notionary/page/markdown_syntax_prompt_generator.py +0 -114
  197. notionary/page/notion_to_markdown_converter.py +0 -179
  198. notionary/page/properites/property_value_extractor.py +0 -0
  199. notionary-0.2.19.dist-info/RECORD +0 -150
  200. /notionary/{blocks/document/document_models.py → markdown/___init__.py} +0 -0
  201. /notionary/{blocks/image/image_models.py → markdown/makdown_document_model.py} +0 -0
  202. /notionary/page/{content/markdown_whitespace_processor.py → markdown_whitespace_processor.py} +0 -0
  203. /notionary/{blocks/mention/mention_models.py → page/reader/handler/context.py} +0 -0
  204. {notionary-0.2.19.dist-info → notionary-0.2.21.dist-info}/LICENSE +0 -0
  205. {notionary-0.2.19.dist-info → notionary-0.2.21.dist-info}/WHEEL +0 -0
@@ -0,0 +1,228 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal, Optional, Union
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from notionary.blocks.bookmark.bookmark_markdown_node import BookmarkMarkdownBlockParams
8
+ from notionary.blocks.bulleted_list.bulleted_list_markdown_node import (
9
+ BulletedListMarkdownBlockParams,
10
+ )
11
+ from notionary.blocks.callout.callout_markdown_node import CalloutMarkdownBlockParams
12
+ from notionary.blocks.divider.divider_markdown_node import DividerMarkdownBlockParams
13
+ from notionary.blocks.embed.embed_markdown_node import EmbedMarkdownBlockParams
14
+ from notionary.blocks.equation.equation_element_markdown_node import (
15
+ EquationMarkdownBlockParams,
16
+ )
17
+ from notionary.blocks.file.file_element_markdown_node import FileMarkdownNodeParams
18
+
19
+ # Import all the existing params models
20
+ from notionary.blocks.heading.heading_markdown_node import HeadingMarkdownBlockParams
21
+ from notionary.blocks.image_block.image_markdown_node import ImageMarkdownBlockParams
22
+ from notionary.blocks.numbered_list.numbered_list_markdown_node import (
23
+ NumberedListMarkdownBlockParams,
24
+ )
25
+ from notionary.blocks.paragraph.paragraph_markdown_node import (
26
+ ParagraphMarkdownBlockParams,
27
+ )
28
+ from notionary.blocks.quote.quote_markdown_node import QuoteMarkdownBlockParams
29
+ from notionary.blocks.table.table_markdown_node import TableMarkdownBlockParams
30
+ from notionary.blocks.table_of_contents.table_of_contents_markdown_node import (
31
+ TableOfContentsMarkdownBlockParams,
32
+ )
33
+ from notionary.blocks.todo.todo_markdown_node import TodoMarkdownBlockParams
34
+ from notionary.blocks.video.video_markdown_node import VideoMarkdownBlockParams
35
+
36
+
37
+ class HeadingBlock(BaseModel):
38
+ type: Literal["heading"] = "heading"
39
+ params: HeadingMarkdownBlockParams
40
+
41
+
42
+ class ParagraphBlock(BaseModel):
43
+ type: Literal["paragraph"] = "paragraph"
44
+ params: ParagraphMarkdownBlockParams
45
+
46
+
47
+ class QuoteBlock(BaseModel):
48
+ type: Literal["quote"] = "quote"
49
+ params: QuoteMarkdownBlockParams
50
+
51
+
52
+ class BulletedListBlock(BaseModel):
53
+ type: Literal["bulleted_list"] = "bulleted_list"
54
+ params: BulletedListMarkdownBlockParams
55
+
56
+
57
+ class NumberedListBlock(BaseModel):
58
+ type: Literal["numbered_list"] = "numbered_list"
59
+ params: NumberedListMarkdownBlockParams
60
+
61
+
62
+ class TodoBlock(BaseModel):
63
+ type: Literal["todo"] = "todo"
64
+ params: TodoMarkdownBlockParams
65
+
66
+
67
+ class CalloutBlock(BaseModel):
68
+ type: Literal["callout"] = "callout"
69
+ params: CalloutMarkdownBlockParams
70
+
71
+
72
+ class CodeBlock(BaseModel):
73
+ type: Literal["code"] = "code"
74
+ params: CodeBlock
75
+
76
+
77
+ class ImageBlock(BaseModel):
78
+ type: Literal["image"] = "image"
79
+ params: ImageMarkdownBlockParams
80
+
81
+
82
+ class VideoBlock(BaseModel):
83
+ type: Literal["video"] = "video"
84
+ params: VideoMarkdownBlockParams
85
+
86
+
87
+ class AudioBlock(BaseModel):
88
+ type: Literal["audio"] = "audio"
89
+ params: FileMarkdownNodeParams
90
+
91
+
92
+ class FileBlock(BaseModel):
93
+ type: Literal["file"] = "file"
94
+ params: FileMarkdownNodeParams
95
+
96
+
97
+ class PdfBlock(BaseModel):
98
+ type: Literal["pdf"] = "pdf"
99
+ params: FileMarkdownNodeParams
100
+
101
+
102
+ class BookmarkBlock(BaseModel):
103
+ type: Literal["bookmark"] = "bookmark"
104
+ params: BookmarkMarkdownBlockParams
105
+
106
+
107
+ class EmbedBlock(BaseModel):
108
+ type: Literal["embed"] = "embed"
109
+ params: EmbedMarkdownBlockParams
110
+
111
+
112
+ class TableBlock(BaseModel):
113
+ type: Literal["table"] = "table"
114
+ params: TableMarkdownBlockParams
115
+
116
+
117
+ class DividerBlock(BaseModel):
118
+ type: Literal["divider"] = "divider"
119
+ params: DividerMarkdownBlockParams
120
+
121
+
122
+ class EquationBlock(BaseModel):
123
+ type: Literal["equation"] = "equation"
124
+ params: EquationMarkdownBlockParams
125
+
126
+
127
+ class TableOfContentsBlock(BaseModel):
128
+ type: Literal["table_of_contents"] = "table_of_contents"
129
+ params: TableOfContentsMarkdownBlockParams
130
+
131
+
132
+ # Special blocks for nested content
133
+ class ToggleBlockParams(BaseModel):
134
+ title: str
135
+ children: list[MarkdownBlock] = Field(default_factory=list)
136
+
137
+
138
+ class ToggleBlock(BaseModel):
139
+ type: Literal["toggle"] = "toggle"
140
+ params: ToggleBlockParams
141
+
142
+
143
+ class ToggleableHeadingBlockParams(BaseModel):
144
+ text: str
145
+ level: int = Field(ge=1, le=3)
146
+ children: list[MarkdownBlock] = Field(default_factory=list)
147
+
148
+
149
+ class ToggleableHeadingBlock(BaseModel):
150
+ type: Literal["toggleable_heading"] = "toggleable_heading"
151
+ params: ToggleableHeadingBlockParams
152
+
153
+
154
+ class ColumnBlockParams(BaseModel):
155
+ columns: list[list[MarkdownBlock]] = Field(default_factory=list)
156
+ width_ratios: Optional[list[float]] = None
157
+
158
+
159
+ class ColumnBlock(BaseModel):
160
+ type: Literal["columns"] = "columns"
161
+ params: ColumnBlockParams
162
+
163
+
164
+ # Union of all possible blocks
165
+ MarkdownBlock = Union[
166
+ HeadingBlock,
167
+ ParagraphBlock,
168
+ QuoteBlock,
169
+ BulletedListBlock,
170
+ NumberedListBlock,
171
+ TodoBlock,
172
+ CalloutBlock,
173
+ CodeBlock,
174
+ ImageBlock,
175
+ VideoBlock,
176
+ AudioBlock,
177
+ FileBlock,
178
+ PdfBlock,
179
+ BookmarkBlock,
180
+ EmbedBlock,
181
+ TableBlock,
182
+ DividerBlock,
183
+ EquationBlock,
184
+ TableOfContentsBlock,
185
+ ToggleBlock,
186
+ ToggleableHeadingBlock,
187
+ ColumnBlock,
188
+ ]
189
+
190
+
191
+ # Update forward references
192
+ ToggleBlockParams.model_rebuild()
193
+ ToggleableHeadingBlockParams.model_rebuild()
194
+ ColumnBlockParams.model_rebuild()
195
+
196
+
197
+ class MarkdownDocumentModel(BaseModel):
198
+ """
199
+ Complete document model for generating Markdown via MarkdownBuilder.
200
+ Perfect for LLM structured output!
201
+
202
+ Example:
203
+ {
204
+ "blocks": [
205
+ {
206
+ "type": "heading",
207
+ "params": {"text": "My Document", "level": 1}
208
+ },
209
+ {
210
+ "type": "paragraph",
211
+ "params": {"text": "Introduction text"}
212
+ },
213
+ {
214
+ "type": "pdf",
215
+ "params": {"url": "https://example.com/doc.pdf", "caption": "Important PDF"}
216
+ }
217
+ ]
218
+ }
219
+ """
220
+
221
+ blocks: list[MarkdownBlock] = Field(default_factory=list)
222
+
223
+ def to_markdown(self) -> str:
224
+ """Convert the model directly to markdown string."""
225
+ from notionary.markdown.markdown_builder import MarkdownBuilder
226
+
227
+ builder = MarkdownBuilder.from_model(self)
228
+ return builder.build()
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+
2
3
  from abc import ABC, abstractmethod
3
4
 
4
5
 
@@ -1,338 +0,0 @@
1
- from pydantic import BaseModel
2
- from dataclasses import dataclass
3
- from typing import Optional, List, Dict, Any, Literal, Union
4
-
5
- from notionary.models.notion_page_response import Cover, Icon
6
-
7
-
8
- # Reusing existing types from your codebase
9
- @dataclass
10
- class TextContent:
11
- content: str
12
- link: Optional[str] = None
13
-
14
-
15
- @dataclass
16
- class RichText:
17
- type: str
18
- text: TextContent
19
- plain_text: str
20
- href: Optional[str]
21
-
22
-
23
- @dataclass
24
- class User:
25
- object: str
26
- id: str
27
-
28
-
29
- @dataclass
30
- class Parent:
31
- type: Literal["page_id", "workspace", "block_id", "database_id"]
32
- page_id: Optional[str] = None
33
- block_id: Optional[str] = None
34
- database_id: Optional[str] = None
35
-
36
-
37
- # Rich text types for Pydantic models
38
- class TextContentPydantic(BaseModel):
39
- content: str
40
- link: Optional[Dict[str, str]] = None
41
-
42
-
43
- class Annotations(BaseModel):
44
- bold: bool
45
- italic: bool
46
- strikethrough: bool
47
- underline: bool
48
- code: bool
49
- color: str
50
-
51
-
52
- class RichTextItemPydantic(BaseModel):
53
- type: str # 'text', 'mention', 'equation'
54
- text: Optional[TextContentPydantic] = None
55
- annotations: Annotations
56
- plain_text: str
57
- href: Optional[str] = None
58
-
59
-
60
- # Database property schema types (these are schema definitions, not values)
61
- class StatusOption(BaseModel):
62
- id: str
63
- name: str
64
- color: str
65
- description: Optional[str] = None
66
-
67
-
68
- class StatusGroup(BaseModel):
69
- id: str
70
- name: str
71
- color: str
72
- option_ids: List[str]
73
-
74
-
75
- class StatusPropertySchema(BaseModel):
76
- options: List[StatusOption]
77
- groups: List[StatusGroup]
78
-
79
-
80
- class DatabaseStatusProperty(BaseModel):
81
- id: str
82
- name: str
83
- type: Literal["status"]
84
- status: StatusPropertySchema
85
-
86
-
87
- class RelationPropertySchema(BaseModel):
88
- database_id: str
89
- type: str # "single_property"
90
- single_property: Dict[str, Any]
91
-
92
-
93
- class DatabaseRelationProperty(BaseModel):
94
- id: str
95
- name: str
96
- type: Literal["relation"]
97
- relation: RelationPropertySchema
98
-
99
-
100
- class DatabaseUrlProperty(BaseModel):
101
- id: str
102
- name: str
103
- type: Literal["url"]
104
- url: Dict[str, Any] # Usually empty dict
105
-
106
-
107
- class DatabaseRichTextProperty(BaseModel):
108
- id: str
109
- name: str
110
- type: Literal["rich_text"]
111
- rich_text: Dict[str, Any] # Usually empty dict
112
-
113
-
114
- class MultiSelectOption(BaseModel):
115
- id: str
116
- name: str
117
- color: str
118
- description: Optional[str] = None
119
-
120
-
121
- class MultiSelectPropertySchema(BaseModel):
122
- options: List[MultiSelectOption]
123
-
124
-
125
- class DatabaseMultiSelectProperty(BaseModel):
126
- id: str
127
- name: str
128
- type: Literal["multi_select"]
129
- multi_select: MultiSelectPropertySchema
130
-
131
-
132
- class DatabaseTitleProperty(BaseModel):
133
- id: str
134
- name: str
135
- type: Literal["title"]
136
- title: Dict[str, Any] # Usually empty dict
137
-
138
-
139
- # Generic database property for unknown types
140
- class GenericDatabaseProperty(BaseModel):
141
- id: str
142
- name: str
143
- type: str
144
-
145
- class Config:
146
- extra = "allow"
147
-
148
-
149
- # Union of all database property types
150
- DatabaseProperty = Union[
151
- DatabaseStatusProperty,
152
- DatabaseRelationProperty,
153
- DatabaseUrlProperty,
154
- DatabaseRichTextProperty,
155
- DatabaseMultiSelectProperty,
156
- DatabaseTitleProperty,
157
- GenericDatabaseProperty,
158
- ]
159
-
160
-
161
- # Page property value types (these are actual values, not schemas)
162
- class StatusValue(BaseModel):
163
- id: str
164
- name: str
165
- color: str
166
-
167
-
168
- class StatusProperty(BaseModel):
169
- id: str
170
- type: str # 'status'
171
- status: Optional[StatusValue] = None
172
-
173
-
174
- class RelationItem(BaseModel):
175
- id: str
176
-
177
-
178
- class RelationProperty(BaseModel):
179
- id: str
180
- type: str # 'relation'
181
- relation: List[RelationItem]
182
- has_more: bool
183
-
184
-
185
- class UrlProperty(BaseModel):
186
- id: str
187
- type: str # 'url'
188
- url: Optional[str] = None
189
-
190
-
191
- class RichTextProperty(BaseModel):
192
- id: str
193
- type: str # 'rich_text'
194
- rich_text: List[RichTextItemPydantic]
195
-
196
-
197
- class MultiSelectItem(BaseModel):
198
- id: str
199
- name: str
200
- color: str
201
-
202
-
203
- class MultiSelectProperty(BaseModel):
204
- id: str
205
- type: str # 'multi_select'
206
- multi_select: List[MultiSelectItem]
207
-
208
-
209
- class TitleProperty(BaseModel):
210
- id: str
211
- type: str # 'title'
212
- title: List[RichTextItemPydantic]
213
-
214
-
215
- # Cover types
216
- class ExternalCover(BaseModel):
217
- url: str
218
-
219
-
220
- class NotionCover(BaseModel):
221
- type: str # 'external', 'file'
222
- external: Optional[ExternalCover] = None
223
-
224
-
225
- # Parent types for Pydantic
226
- class NotionParent(BaseModel):
227
- type: str # 'database_id', 'page_id', 'workspace'
228
- database_id: Optional[str] = None
229
- page_id: Optional[str] = None
230
-
231
-
232
- # User type for Pydantic
233
- class NotionUser(BaseModel):
234
- object: str # 'user'
235
- id: str
236
-
237
-
238
- # Database object
239
- class NotionDatabaseResponse(BaseModel):
240
- """
241
- Represents the response from the Notion API when retrieving a database.
242
- """
243
-
244
- object: Literal["database"]
245
- id: str
246
- cover: Optional[Any] = None
247
- icon: Optional[Icon] = None
248
- cover: Optional[Cover]
249
- created_time: str
250
- last_edited_time: str
251
- created_by: NotionUser
252
- last_edited_by: NotionUser
253
- title: List[RichTextItemPydantic]
254
- description: List[Any]
255
- is_inline: bool
256
- properties: Dict[
257
- str, Any
258
- ] # Using Any for flexibility with different property schemas
259
- parent: NotionParent
260
- url: str
261
- public_url: Optional[str] = None
262
- archived: bool
263
- in_trash: bool
264
-
265
-
266
- class NotionPageResponse(BaseModel):
267
- object: Literal["page"]
268
- id: str
269
- created_time: str
270
- last_edited_time: str
271
- created_by: NotionUser
272
- last_edited_by: NotionUser
273
- cover: Optional[NotionCover] = None
274
- icon: Optional[Icon] = None
275
- parent: NotionParent
276
- archived: bool
277
- in_trash: bool
278
- properties: Dict[str, Any]
279
- url: str
280
- public_url: Optional[str] = None
281
-
282
-
283
- class NotionQueryResponse(BaseModel):
284
- """
285
- Complete Notion search/query response model that can contain both pages and databases.
286
- """
287
-
288
- object: Literal["list"]
289
- results: List[Union[NotionPageResponse, NotionDatabaseResponse]]
290
- next_cursor: Optional[str] = None
291
- has_more: bool
292
- type: Literal["page_or_database"]
293
- page_or_database: Dict[str, Any]
294
- request_id: str
295
-
296
-
297
- # Specific response type for database queries (pages only)
298
- class NotionQueryDatabaseResponse(BaseModel):
299
- """
300
- Notion database query response model for querying pages within a database.
301
- """
302
-
303
- object: Literal["list"]
304
- results: List[NotionPageResponse]
305
- next_cursor: Optional[str] = None
306
- has_more: bool
307
- type: Literal["page_or_database"]
308
- page_or_database: Dict[str, Any]
309
- request_id: str
310
-
311
-
312
- # Specific response type for search results (can be mixed)
313
- class NotionSearchResponse(BaseModel):
314
- """
315
- Notion search response model that can return both pages and databases.
316
- """
317
-
318
- object: Literal["list"]
319
- results: List[Union[NotionPageResponse, NotionDatabaseResponse]]
320
- next_cursor: Optional[str] = None
321
- has_more: bool
322
- type: Literal["page_or_database"]
323
- page_or_database: Dict[str, Any]
324
- request_id: str
325
-
326
-
327
- class NotionDatabaseSearchResponse(BaseModel):
328
- """
329
- Notion search response model for database-only searches.
330
- """
331
-
332
- object: Literal["list"]
333
- results: List[NotionDatabaseResponse]
334
- next_cursor: Optional[str] = None
335
- has_more: bool
336
- type: Literal["page_or_database"]
337
- page_or_database: Dict[str, Any]
338
- request_id: str
notionary/page/client.py CHANGED
@@ -1,11 +1,10 @@
1
- from typing import Dict, Any, List, Optional
1
+ from typing import Any, Optional
2
+
2
3
  from notionary.base_notion_client import BaseNotionClient
3
- from notionary.models.notion_page_response import NotionPageResponse
4
- from notionary.models.notion_database_response import NotionQueryDatabaseResponse
5
- from notionary.util import singleton
4
+ from notionary.database.models import NotionQueryDatabaseResponse
5
+ from notionary.page.models import NotionPageResponse
6
6
 
7
7
 
8
- @singleton
9
8
  class NotionPageClient(BaseNotionClient):
10
9
  """
11
10
  Client for Notion page-specific operations.
@@ -22,7 +21,7 @@ class NotionPageClient(BaseNotionClient):
22
21
  async def create_page(
23
22
  self,
24
23
  parent_database_id: Optional[str] = None,
25
- properties: Optional[Dict[str, Any]] = None,
24
+ properties: Optional[dict[str, Any]] = None,
26
25
  ) -> NotionPageResponse:
27
26
  """
28
27
  Creates a new page in a Notion database or as a child page.
@@ -36,7 +35,7 @@ class NotionPageClient(BaseNotionClient):
36
35
  return NotionPageResponse.model_validate(response)
37
36
 
38
37
  async def patch_page(
39
- self, page_id: str, data: Optional[Dict[str, Any]] = None
38
+ self, page_id: str, data: Optional[dict[str, Any]] = None
40
39
  ) -> NotionPageResponse:
41
40
  """
42
41
  Updates a Notion page with the provided data.
@@ -73,7 +72,7 @@ class NotionPageClient(BaseNotionClient):
73
72
  return NotionQueryDatabaseResponse.model_validate(result)
74
73
 
75
74
  async def update_page_properties(
76
- self, page_id: str, properties: Dict[str, Any]
75
+ self, page_id: str, properties: dict[str, Any]
77
76
  ) -> NotionPageResponse:
78
77
  """
79
78
  Updates only the properties of a Notion page.
@@ -95,14 +94,14 @@ class NotionPageClient(BaseNotionClient):
95
94
  data = {"archived": False}
96
95
  return await self.patch_page(page_id, data)
97
96
 
98
- async def get_page_blocks(self, page_id: str) -> List[Dict[str, Any]]:
97
+ async def get_page_blocks(self, page_id: str) -> list[dict[str, Any]]:
99
98
  """
100
99
  Retrieves all blocks of a Notion page.
101
100
  """
102
101
  response = await self.get(f"blocks/{page_id}/children")
103
102
  return response.get("results", [])
104
103
 
105
- async def get_block_children(self, block_id: str) -> List[Dict[str, Any]]:
104
+ async def get_block_children(self, block_id: str) -> list[dict[str, Any]]:
106
105
  """
107
106
  Retrieves all children blocks of a specific block.
108
107
  """