notionary 0.2.18__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.
- notionary/__init__.py +8 -4
- notionary/base_notion_client.py +3 -1
- notionary/blocks/__init__.py +2 -91
- notionary/blocks/_bootstrap.py +263 -0
- notionary/blocks/audio/__init__.py +8 -2
- notionary/blocks/audio/audio_element.py +42 -104
- notionary/blocks/audio/audio_markdown_node.py +3 -1
- notionary/blocks/audio/audio_models.py +6 -55
- notionary/blocks/base_block_element.py +30 -0
- notionary/blocks/bookmark/__init__.py +9 -2
- notionary/blocks/bookmark/bookmark_element.py +46 -139
- notionary/blocks/bookmark/bookmark_markdown_node.py +3 -1
- notionary/blocks/bookmark/bookmark_models.py +15 -0
- notionary/blocks/breadcrumbs/__init__.py +17 -0
- notionary/blocks/breadcrumbs/breadcrumb_element.py +39 -0
- notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +32 -0
- notionary/blocks/breadcrumbs/breadcrumb_models.py +12 -0
- notionary/blocks/bulleted_list/__init__.py +12 -2
- notionary/blocks/bulleted_list/bulleted_list_element.py +40 -55
- notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +2 -1
- notionary/blocks/bulleted_list/bulleted_list_models.py +18 -0
- notionary/blocks/callout/__init__.py +9 -2
- notionary/blocks/callout/callout_element.py +40 -89
- notionary/blocks/callout/callout_markdown_node.py +3 -1
- notionary/blocks/callout/callout_models.py +33 -0
- notionary/blocks/child_database/__init__.py +7 -0
- notionary/blocks/child_database/child_database_models.py +19 -0
- notionary/blocks/child_page/__init__.py +9 -0
- notionary/blocks/child_page/child_page_models.py +12 -0
- notionary/blocks/{shared/block_client.py → client.py} +55 -54
- notionary/blocks/code/__init__.py +6 -2
- notionary/blocks/code/code_element.py +53 -187
- notionary/blocks/code/code_markdown_node.py +13 -13
- notionary/blocks/code/code_models.py +94 -0
- notionary/blocks/column/__init__.py +25 -1
- notionary/blocks/column/column_element.py +40 -314
- notionary/blocks/column/column_list_element.py +37 -0
- notionary/blocks/column/column_list_markdown_node.py +50 -0
- notionary/blocks/column/column_markdown_node.py +59 -0
- notionary/blocks/column/column_models.py +26 -0
- notionary/blocks/divider/__init__.py +9 -2
- notionary/blocks/divider/divider_element.py +26 -49
- notionary/blocks/divider/divider_markdown_node.py +2 -1
- notionary/blocks/divider/divider_models.py +12 -0
- notionary/blocks/embed/__init__.py +9 -2
- notionary/blocks/embed/embed_element.py +47 -114
- notionary/blocks/embed/embed_markdown_node.py +3 -1
- notionary/blocks/embed/embed_models.py +14 -0
- notionary/blocks/equation/__init__.py +14 -0
- notionary/blocks/equation/equation_element.py +80 -0
- notionary/blocks/equation/equation_element_markdown_node.py +36 -0
- notionary/blocks/equation/equation_models.py +11 -0
- notionary/blocks/file/__init__.py +25 -0
- notionary/blocks/file/file_element.py +93 -0
- notionary/blocks/file/file_element_markdown_node.py +35 -0
- notionary/blocks/file/file_element_models.py +39 -0
- notionary/blocks/heading/__init__.py +16 -2
- notionary/blocks/heading/heading_element.py +67 -72
- notionary/blocks/heading/heading_markdown_node.py +2 -1
- notionary/blocks/heading/heading_models.py +29 -0
- notionary/blocks/image_block/__init__.py +13 -0
- notionary/blocks/image_block/image_element.py +84 -0
- notionary/blocks/{image → image_block}/image_markdown_node.py +3 -1
- notionary/blocks/image_block/image_models.py +10 -0
- notionary/blocks/models.py +172 -0
- notionary/blocks/numbered_list/__init__.py +12 -2
- notionary/blocks/numbered_list/numbered_list_element.py +33 -58
- notionary/blocks/numbered_list/numbered_list_markdown_node.py +3 -1
- notionary/blocks/numbered_list/numbered_list_models.py +17 -0
- notionary/blocks/paragraph/__init__.py +12 -2
- notionary/blocks/paragraph/paragraph_element.py +27 -69
- notionary/blocks/paragraph/paragraph_markdown_node.py +2 -1
- notionary/blocks/paragraph/paragraph_models.py +16 -0
- notionary/blocks/pdf/__init__.py +13 -0
- notionary/blocks/pdf/pdf_element.py +91 -0
- notionary/blocks/pdf/pdf_markdown_node.py +35 -0
- notionary/blocks/pdf/pdf_models.py +11 -0
- notionary/blocks/quote/__init__.py +11 -2
- notionary/blocks/quote/quote_element.py +31 -65
- notionary/blocks/quote/quote_markdown_node.py +4 -1
- notionary/blocks/quote/quote_models.py +18 -0
- notionary/blocks/registry/__init__.py +4 -0
- notionary/blocks/registry/block_registry.py +75 -91
- notionary/blocks/registry/block_registry_builder.py +107 -59
- notionary/blocks/rich_text/__init__.py +33 -0
- notionary/blocks/rich_text/rich_text_models.py +188 -0
- notionary/blocks/rich_text/text_inline_formatter.py +125 -0
- notionary/blocks/table/__init__.py +16 -2
- notionary/blocks/table/table_element.py +48 -241
- notionary/blocks/table/table_markdown_node.py +2 -1
- notionary/blocks/table/table_models.py +28 -0
- notionary/blocks/table_of_contents/__init__.py +19 -0
- notionary/blocks/table_of_contents/table_of_contents_element.py +51 -0
- notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +35 -0
- notionary/blocks/table_of_contents/table_of_contents_models.py +18 -0
- notionary/blocks/todo/__init__.py +9 -2
- notionary/blocks/todo/todo_element.py +38 -95
- notionary/blocks/todo/todo_markdown_node.py +2 -1
- notionary/blocks/todo/todo_models.py +19 -0
- notionary/blocks/toggle/__init__.py +13 -3
- notionary/blocks/toggle/toggle_element.py +57 -264
- notionary/blocks/toggle/toggle_markdown_node.py +24 -14
- notionary/blocks/toggle/toggle_models.py +17 -0
- notionary/blocks/toggleable_heading/__init__.py +6 -2
- notionary/blocks/toggleable_heading/toggleable_heading_element.py +74 -244
- notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +26 -18
- notionary/blocks/types.py +61 -0
- notionary/blocks/video/__init__.py +8 -2
- notionary/blocks/video/video_element.py +67 -143
- notionary/blocks/video/video_element_models.py +10 -0
- notionary/blocks/video/video_markdown_node.py +3 -1
- notionary/database/client.py +3 -8
- notionary/database/database.py +13 -14
- notionary/database/database_filter_builder.py +2 -2
- notionary/database/database_provider.py +5 -4
- notionary/database/models.py +337 -0
- notionary/database/notion_database.py +6 -7
- notionary/file_upload/client.py +5 -7
- notionary/file_upload/models.py +2 -1
- notionary/file_upload/notion_file_upload.py +2 -3
- notionary/markdown/markdown_builder.py +722 -0
- notionary/markdown/markdown_document_model.py +228 -0
- notionary/{blocks → markdown}/markdown_node.py +1 -0
- notionary/models/notion_database_response.py +0 -338
- notionary/page/client.py +9 -10
- notionary/page/models.py +327 -0
- notionary/page/notion_page.py +99 -52
- notionary/page/notion_text_length_utils.py +119 -0
- notionary/page/{content/page_content_writer.py → page_content_writer.py} +88 -38
- notionary/page/reader/handler/__init__.py +17 -0
- notionary/page/reader/handler/base_block_renderer.py +44 -0
- notionary/page/reader/handler/block_processing_context.py +35 -0
- notionary/page/reader/handler/block_rendering_context.py +43 -0
- notionary/page/reader/handler/column_list_renderer.py +51 -0
- notionary/page/reader/handler/column_renderer.py +60 -0
- notionary/page/reader/handler/line_renderer.py +60 -0
- notionary/page/reader/handler/toggle_renderer.py +69 -0
- notionary/page/reader/handler/toggleable_heading_renderer.py +89 -0
- notionary/page/reader/page_content_retriever.py +69 -0
- notionary/page/search_filter_builder.py +2 -1
- notionary/page/writer/handler/__init__.py +22 -0
- notionary/page/writer/handler/code_handler.py +100 -0
- notionary/page/writer/handler/column_handler.py +141 -0
- notionary/page/writer/handler/column_list_handler.py +139 -0
- notionary/page/writer/handler/line_handler.py +35 -0
- notionary/page/writer/handler/line_processing_context.py +54 -0
- notionary/page/writer/handler/regular_line_handler.py +92 -0
- notionary/page/writer/handler/table_handler.py +130 -0
- notionary/page/writer/handler/toggle_handler.py +153 -0
- notionary/page/writer/handler/toggleable_heading_handler.py +167 -0
- notionary/page/writer/markdown_to_notion_converter.py +76 -0
- notionary/telemetry/__init__.py +2 -2
- notionary/telemetry/service.py +4 -3
- notionary/user/__init__.py +2 -2
- notionary/user/base_notion_user.py +2 -1
- notionary/user/client.py +2 -3
- notionary/user/models.py +1 -0
- notionary/user/notion_bot_user.py +4 -5
- notionary/user/notion_user.py +3 -4
- notionary/user/notion_user_manager.py +3 -2
- notionary/user/notion_user_provider.py +1 -1
- notionary/util/__init__.py +3 -2
- notionary/util/fuzzy.py +2 -1
- notionary/util/logging_mixin.py +2 -2
- notionary/util/singleton_metaclass.py +1 -1
- notionary/workspace.py +3 -2
- {notionary-0.2.18.dist-info → notionary-0.2.21.dist-info}/METADATA +12 -8
- notionary-0.2.21.dist-info/RECORD +185 -0
- notionary/blocks/document/__init__.py +0 -7
- notionary/blocks/document/document_element.py +0 -102
- notionary/blocks/document/document_markdown_node.py +0 -31
- notionary/blocks/image/__init__.py +0 -7
- notionary/blocks/image/image_element.py +0 -151
- notionary/blocks/markdown_builder.py +0 -356
- notionary/blocks/mention/__init__.py +0 -7
- notionary/blocks/mention/mention_element.py +0 -229
- notionary/blocks/mention/mention_markdown_node.py +0 -38
- notionary/blocks/prompts/element_prompt_builder.py +0 -83
- notionary/blocks/prompts/element_prompt_content.py +0 -41
- notionary/blocks/shared/__init__.py +0 -0
- notionary/blocks/shared/models.py +0 -710
- notionary/blocks/shared/notion_block_element.py +0 -37
- notionary/blocks/shared/text_inline_formatter.py +0 -262
- notionary/blocks/shared/text_inline_formatter_new.py +0 -139
- notionary/blocks/toggleable_heading/toggleable_heading_models.py +0 -0
- notionary/database/models/page_result.py +0 -10
- notionary/models/notion_block_response.py +0 -264
- notionary/models/notion_page_response.py +0 -78
- notionary/models/search_response.py +0 -0
- notionary/page/__init__.py +0 -0
- notionary/page/content/notion_text_length_utils.py +0 -87
- notionary/page/content/page_content_retriever.py +0 -52
- notionary/page/formatting/line_processor.py +0 -153
- notionary/page/formatting/markdown_to_notion_converter.py +0 -153
- notionary/page/markdown_syntax_prompt_generator.py +0 -114
- notionary/page/notion_to_markdown_converter.py +0 -179
- notionary/page/properites/property_value_extractor.py +0 -0
- notionary-0.2.18.dist-info/RECORD +0 -149
- /notionary/{blocks/document/document_models.py → markdown/___init__.py} +0 -0
- /notionary/{blocks/image/image_models.py → markdown/makdown_document_model.py} +0 -0
- /notionary/page/{content/markdown_whitespace_processor.py → markdown_whitespace_processor.py} +0 -0
- /notionary/{blocks/mention/mention_models.py → page/reader/handler/context.py} +0 -0
- {notionary-0.2.18.dist-info → notionary-0.2.21.dist-info}/LICENSE +0 -0
- {notionary-0.2.18.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,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
|
1
|
+
from typing import Any, Optional
|
2
|
+
|
2
3
|
from notionary.base_notion_client import BaseNotionClient
|
3
|
-
from notionary.models
|
4
|
-
from notionary.models
|
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[
|
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[
|
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:
|
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) ->
|
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) ->
|
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
|
"""
|