notionary 0.2.19__py3-none-any.whl → 0.2.22__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 +271 -0
- notionary/blocks/audio/__init__.py +8 -2
- notionary/blocks/audio/audio_element.py +69 -106
- notionary/blocks/audio/audio_markdown_node.py +13 -5
- notionary/blocks/audio/audio_models.py +6 -55
- notionary/blocks/base_block_element.py +42 -0
- notionary/blocks/bookmark/__init__.py +9 -2
- notionary/blocks/bookmark/bookmark_element.py +49 -139
- notionary/blocks/bookmark/bookmark_markdown_node.py +19 -18
- 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 +55 -53
- 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 +53 -86
- notionary/blocks/callout/callout_markdown_node.py +3 -1
- notionary/blocks/callout/callout_models.py +33 -0
- notionary/blocks/child_database/__init__.py +14 -0
- notionary/blocks/child_database/child_database_element.py +61 -0
- notionary/blocks/child_database/child_database_models.py +12 -0
- notionary/blocks/child_page/__init__.py +9 -0
- notionary/blocks/child_page/child_page_element.py +94 -0
- notionary/blocks/child_page/child_page_models.py +12 -0
- notionary/blocks/{shared/block_client.py → client.py} +54 -54
- notionary/blocks/code/__init__.py +6 -2
- notionary/blocks/code/code_element.py +96 -181
- notionary/blocks/code/code_markdown_node.py +64 -13
- notionary/blocks/code/code_models.py +94 -0
- notionary/blocks/column/__init__.py +25 -1
- notionary/blocks/column/column_element.py +44 -312
- notionary/blocks/column/column_list_element.py +52 -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 +18 -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 +65 -111
- 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 +133 -0
- notionary/blocks/equation/equation_element_markdown_node.py +35 -0
- notionary/blocks/equation/equation_models.py +11 -0
- notionary/blocks/file/__init__.py +25 -0
- notionary/blocks/file/file_element.py +112 -0
- notionary/blocks/file/file_element_markdown_node.py +37 -0
- notionary/blocks/file/file_element_models.py +39 -0
- notionary/blocks/guards.py +22 -0
- notionary/blocks/heading/__init__.py +16 -2
- notionary/blocks/heading/heading_element.py +83 -69
- 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 +89 -0
- notionary/blocks/{image → image_block}/image_markdown_node.py +13 -6
- notionary/blocks/image_block/image_models.py +10 -0
- notionary/blocks/mixins/captions/__init__.py +4 -0
- notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +31 -0
- notionary/blocks/mixins/captions/caption_mixin.py +92 -0
- notionary/blocks/models.py +174 -0
- notionary/blocks/numbered_list/__init__.py +12 -2
- notionary/blocks/numbered_list/numbered_list_element.py +48 -56
- 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 +40 -66
- 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 +97 -0
- notionary/blocks/pdf/pdf_markdown_node.py +37 -0
- notionary/blocks/pdf/pdf_models.py +11 -0
- notionary/blocks/quote/__init__.py +11 -2
- notionary/blocks/quote/quote_element.py +45 -62
- notionary/blocks/quote/quote_markdown_node.py +6 -3
- notionary/blocks/quote/quote_models.py +18 -0
- notionary/blocks/registry/__init__.py +4 -0
- notionary/blocks/registry/block_registry.py +60 -121
- notionary/blocks/registry/block_registry_builder.py +115 -59
- notionary/blocks/rich_text/__init__.py +33 -0
- notionary/blocks/rich_text/name_to_id_resolver.py +205 -0
- notionary/blocks/rich_text/rich_text_models.py +221 -0
- notionary/blocks/rich_text/text_inline_formatter.py +456 -0
- notionary/blocks/syntax_prompt_builder.py +137 -0
- notionary/blocks/table/__init__.py +16 -2
- notionary/blocks/table/table_element.py +136 -228
- 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 +68 -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 +52 -92
- 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 +69 -260
- notionary/blocks/toggle/toggle_markdown_node.py +25 -15
- notionary/blocks/toggle/toggle_models.py +17 -0
- notionary/blocks/toggleable_heading/__init__.py +6 -2
- notionary/blocks/toggleable_heading/toggleable_heading_element.py +86 -241
- notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +26 -18
- notionary/blocks/types.py +130 -0
- notionary/blocks/video/__init__.py +8 -2
- notionary/blocks/video/video_element.py +70 -141
- notionary/blocks/video/video_element_models.py +10 -0
- notionary/blocks/video/video_markdown_node.py +13 -6
- notionary/database/client.py +26 -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 +3 -2
- notionary/file_upload/notion_file_upload.py +2 -3
- notionary/markdown/markdown_builder.py +729 -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 +34 -15
- notionary/page/models.py +327 -0
- notionary/page/notion_page.py +136 -58
- notionary/page/{content/page_content_writer.py → page_content_deleting_service.py} +25 -59
- notionary/page/page_content_writer.py +177 -0
- notionary/page/page_context.py +65 -0
- notionary/page/reader/handler/__init__.py +19 -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 +48 -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 +73 -0
- notionary/page/reader/handler/numbered_list_renderer.py +85 -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 +81 -0
- notionary/page/search_filter_builder.py +2 -1
- notionary/page/writer/handler/__init__.py +24 -0
- notionary/page/writer/handler/code_handler.py +72 -0
- notionary/page/writer/handler/column_handler.py +141 -0
- notionary/page/writer/handler/column_list_handler.py +139 -0
- notionary/page/writer/handler/equation_handler.py +74 -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 +86 -0
- notionary/page/writer/handler/table_handler.py +66 -0
- notionary/page/writer/handler/toggle_handler.py +155 -0
- notionary/page/writer/handler/toggleable_heading_handler.py +173 -0
- notionary/page/writer/markdown_to_notion_converter.py +95 -0
- notionary/page/writer/markdown_to_notion_converter_context.py +30 -0
- notionary/page/writer/markdown_to_notion_formatting_post_processor.py +73 -0
- notionary/page/writer/notion_text_length_processor.py +150 -0
- notionary/telemetry/__init__.py +2 -2
- notionary/telemetry/service.py +3 -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 +23 -95
- 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 +6 -5
- notionary-0.2.22.dist-info/METADATA +237 -0
- notionary-0.2.22.dist-info/RECORD +200 -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/models.py +0 -713
- 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/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/markdown_whitespace_processor.py +0 -80
- notionary/page/content/notion_text_length_utils.py +0 -87
- notionary/page/content/page_content_retriever.py +0 -60
- 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/user/notion_user_provider.py +0 -1
- notionary-0.2.19.dist-info/METADATA +0 -225
- notionary-0.2.19.dist-info/RECORD +0 -150
- /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/{blocks/mention/mention_models.py → page/reader/handler/equation_renderer.py} +0 -0
- /notionary/{blocks/shared/__init__.py → page/writer/markdown_to_notion_post_processor.py} +0 -0
- /notionary/{blocks/toggleable_heading/toggleable_heading_models.py → page/writer/markdown_to_notion_text_length_post_processor.py} +0 -0
- /notionary/{elements/__init__.py → util/concurrency_limiter.py} +0 -0
- {notionary-0.2.19.dist-info → notionary-0.2.22.dist-info}/LICENSE +0 -0
- {notionary-0.2.19.dist-info → notionary-0.2.22.dist-info}/WHEEL +0 -0
notionary/__init__.py
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
from .
|
1
|
+
from notionary.blocks import bootstrap_blocks
|
2
|
+
|
3
|
+
bootstrap_blocks()
|
4
|
+
|
5
|
+
from .database import DatabaseFilterBuilder, NotionDatabase
|
6
|
+
from .file_upload import NotionFileUpload
|
7
|
+
from .markdown.markdown_builder import MarkdownBuilder
|
2
8
|
from .page.notion_page import NotionPage
|
9
|
+
from .user import NotionBotUser, NotionUser, NotionUserManager
|
3
10
|
from .workspace import NotionWorkspace
|
4
|
-
from .user import NotionUser, NotionUserManager, NotionBotUser
|
5
|
-
from .file_upload import NotionFileUpload
|
6
|
-
from .blocks.markdown_builder import MarkdownBuilder
|
7
11
|
|
8
12
|
__all__ = [
|
9
13
|
"NotionDatabase",
|
notionary/base_notion_client.py
CHANGED
@@ -2,9 +2,11 @@ import asyncio
|
|
2
2
|
import os
|
3
3
|
from abc import ABC
|
4
4
|
from enum import Enum
|
5
|
-
from typing import
|
5
|
+
from typing import Any, Dict, Optional, Union
|
6
|
+
|
6
7
|
import httpx
|
7
8
|
from dotenv import load_dotenv
|
9
|
+
|
8
10
|
from notionary.util import LoggingMixin
|
9
11
|
|
10
12
|
load_dotenv()
|
notionary/blocks/__init__.py
CHANGED
@@ -1,92 +1,3 @@
|
|
1
|
-
|
2
|
-
from .prompts.element_prompt_content import ElementPromptContent
|
3
|
-
from .prompts.element_prompt_builder import ElementPromptBuilder
|
1
|
+
from ._bootstrap import bootstrap_blocks
|
4
2
|
|
5
|
-
|
6
|
-
NotionBlockElement,
|
7
|
-
NotionBlockResult,
|
8
|
-
NotionBlock,
|
9
|
-
)
|
10
|
-
|
11
|
-
from .audio import AudioElement, AudioMarkdownNode
|
12
|
-
from .bulleted_list import BulletedListElement, BulletedListMarkdownNode
|
13
|
-
from .callout import CalloutElement, CalloutMarkdownNode
|
14
|
-
from .code import CodeElement, CodeMarkdownNode
|
15
|
-
from .column.column_element import ColumnElement
|
16
|
-
from .divider import DividerElement, DividerMarkdownNode
|
17
|
-
from .embed import EmbedElement, EmbedMarkdownNode
|
18
|
-
from .heading import HeadingElement, HeadingMarkdownNode
|
19
|
-
from .image import ImageElement, ImageMarkdownNode
|
20
|
-
from .numbered_list import NumberedListElement, NumberedListMarkdownNode
|
21
|
-
from .paragraph import ParagraphElement, ParagraphMarkdownNode
|
22
|
-
from .table import TableElement, TableMarkdownNode
|
23
|
-
from .toggle import ToggleElement, ToggleMarkdownNode
|
24
|
-
from .todo import TodoElement, TodoMarkdownNode
|
25
|
-
from .video import VideoElement, VideoMarkdownNode
|
26
|
-
from .toggleable_heading import ToggleableHeadingElement, ToggleableHeadingMarkdownNode
|
27
|
-
from .bookmark import BookmarkElement, BookmarkMarkdownNode
|
28
|
-
from .divider import DividerElement, DividerMarkdownNode
|
29
|
-
from .heading import HeadingElement, HeadingMarkdownNode
|
30
|
-
from .mention import MentionElement, MentionMarkdownNode
|
31
|
-
from .quote import QuoteElement, QuoteMarkdownNode
|
32
|
-
from .document import DocumentElement, DocumentMarkdownNode
|
33
|
-
from .shared.text_inline_formatter import TextInlineFormatter
|
34
|
-
|
35
|
-
from .markdown_node import MarkdownNode
|
36
|
-
|
37
|
-
from .registry.block_registry import BlockRegistry
|
38
|
-
from .registry.block_registry_builder import BlockRegistryBuilder
|
39
|
-
|
40
|
-
from .shared.block_client import NotionBlockClient
|
41
|
-
|
42
|
-
__all__ = [
|
43
|
-
"MarkdownNode",
|
44
|
-
"ElementPromptContent",
|
45
|
-
"ElementPromptBuilder",
|
46
|
-
"NotionBlockElement",
|
47
|
-
"AudioElement",
|
48
|
-
"AudioMarkdownNode",
|
49
|
-
"BulletedListElement",
|
50
|
-
"BulletedListMarkdownNode",
|
51
|
-
"CalloutElement",
|
52
|
-
"CalloutMarkdownNode",
|
53
|
-
"CodeElement",
|
54
|
-
"CodeMarkdownNode",
|
55
|
-
"ColumnElement",
|
56
|
-
"DividerElement",
|
57
|
-
"DividerMarkdownNode",
|
58
|
-
"EmbedElement",
|
59
|
-
"EmbedMarkdownNode",
|
60
|
-
"HeadingElement",
|
61
|
-
"HeadingMarkdownNode",
|
62
|
-
"ImageElement",
|
63
|
-
"ImageMarkdownNode",
|
64
|
-
"NumberedListElement",
|
65
|
-
"NumberedListMarkdownNode",
|
66
|
-
"ParagraphElement",
|
67
|
-
"ParagraphMarkdownNode",
|
68
|
-
"TableElement",
|
69
|
-
"TableMarkdownNode",
|
70
|
-
"ToggleElement",
|
71
|
-
"ToggleMarkdownNode",
|
72
|
-
"TodoElement",
|
73
|
-
"TodoMarkdownNode",
|
74
|
-
"VideoElement",
|
75
|
-
"VideoMarkdownNode",
|
76
|
-
"ToggleableHeadingElement",
|
77
|
-
"ToggleableHeadingMarkdownNode",
|
78
|
-
"BookmarkElement",
|
79
|
-
"BookmarkMarkdownNode",
|
80
|
-
"MentionElement",
|
81
|
-
"MentionMarkdownNode",
|
82
|
-
"QuoteElement",
|
83
|
-
"QuoteMarkdownNode",
|
84
|
-
"DocumentElement",
|
85
|
-
"DocumentMarkdownNode",
|
86
|
-
"BlockRegistry",
|
87
|
-
"BlockRegistryBuilder",
|
88
|
-
"TextInlineFormatter",
|
89
|
-
"NotionBlockResult",
|
90
|
-
"NotionBlock",
|
91
|
-
"NotionBlockClient",
|
92
|
-
]
|
3
|
+
__all__ = ["bootstrap_blocks"]
|
@@ -0,0 +1,271 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Optional, Union
|
4
|
+
|
5
|
+
_bootstrapped = False
|
6
|
+
|
7
|
+
|
8
|
+
def bootstrap_blocks() -> None:
|
9
|
+
global _bootstrapped
|
10
|
+
if _bootstrapped:
|
11
|
+
return
|
12
|
+
|
13
|
+
from notionary.blocks import (
|
14
|
+
bookmark,
|
15
|
+
breadcrumbs,
|
16
|
+
bulleted_list,
|
17
|
+
callout,
|
18
|
+
child_page,
|
19
|
+
code,
|
20
|
+
column,
|
21
|
+
divider,
|
22
|
+
embed,
|
23
|
+
equation,
|
24
|
+
file,
|
25
|
+
heading,
|
26
|
+
image_block,
|
27
|
+
models,
|
28
|
+
numbered_list,
|
29
|
+
paragraph,
|
30
|
+
quote,
|
31
|
+
table,
|
32
|
+
table_of_contents,
|
33
|
+
todo,
|
34
|
+
toggle,
|
35
|
+
toggleable_heading,
|
36
|
+
video,
|
37
|
+
child_database,
|
38
|
+
)
|
39
|
+
|
40
|
+
# Collect all exports from modules
|
41
|
+
ns = {}
|
42
|
+
for m in (
|
43
|
+
bookmark,
|
44
|
+
breadcrumbs,
|
45
|
+
bulleted_list,
|
46
|
+
callout,
|
47
|
+
child_page,
|
48
|
+
code,
|
49
|
+
column,
|
50
|
+
divider,
|
51
|
+
embed,
|
52
|
+
equation,
|
53
|
+
file,
|
54
|
+
heading,
|
55
|
+
image_block,
|
56
|
+
numbered_list,
|
57
|
+
paragraph,
|
58
|
+
quote,
|
59
|
+
table,
|
60
|
+
todo,
|
61
|
+
toggle,
|
62
|
+
video,
|
63
|
+
toggleable_heading,
|
64
|
+
table_of_contents,
|
65
|
+
child_database,
|
66
|
+
):
|
67
|
+
ns.update(vars(m))
|
68
|
+
|
69
|
+
# Add missing types that are needed for model rebuilding
|
70
|
+
# These are the types that are only defined in TYPE_CHECKING in block_models
|
71
|
+
from notionary.blocks.bookmark.bookmark_models import (
|
72
|
+
BookmarkBlock,
|
73
|
+
CreateBookmarkBlock,
|
74
|
+
)
|
75
|
+
from notionary.blocks.breadcrumbs.breadcrumb_models import (
|
76
|
+
BreadcrumbBlock,
|
77
|
+
CreateBreadcrumbBlock,
|
78
|
+
)
|
79
|
+
from notionary.blocks.bulleted_list.bulleted_list_models import (
|
80
|
+
BulletedListItemBlock,
|
81
|
+
CreateBulletedListItemBlock,
|
82
|
+
)
|
83
|
+
from notionary.blocks.callout.callout_models import CalloutBlock, CreateCalloutBlock
|
84
|
+
from notionary.blocks.child_page.child_page_models import (
|
85
|
+
ChildPageBlock,
|
86
|
+
CreateChildPageBlock,
|
87
|
+
)
|
88
|
+
from notionary.blocks.code.code_models import CodeBlock, CreateCodeBlock
|
89
|
+
from notionary.blocks.column.column_models import (
|
90
|
+
ColumnBlock,
|
91
|
+
ColumnListBlock,
|
92
|
+
CreateColumnBlock,
|
93
|
+
CreateColumnListBlock,
|
94
|
+
)
|
95
|
+
from notionary.blocks.divider.divider_models import CreateDividerBlock, DividerBlock
|
96
|
+
from notionary.blocks.embed.embed_models import CreateEmbedBlock, EmbedBlock
|
97
|
+
from notionary.blocks.equation.equation_models import (
|
98
|
+
CreateEquationBlock,
|
99
|
+
EquationBlock,
|
100
|
+
)
|
101
|
+
from notionary.blocks.file.file_element_models import CreateFileBlock, FileBlock
|
102
|
+
from notionary.blocks.heading.heading_models import (
|
103
|
+
CreateHeading1Block,
|
104
|
+
CreateHeading2Block,
|
105
|
+
CreateHeading3Block,
|
106
|
+
HeadingBlock,
|
107
|
+
)
|
108
|
+
from notionary.blocks.image_block.image_models import CreateImageBlock
|
109
|
+
from notionary.blocks.numbered_list.numbered_list_models import (
|
110
|
+
CreateNumberedListItemBlock,
|
111
|
+
NumberedListItemBlock,
|
112
|
+
)
|
113
|
+
from notionary.blocks.paragraph.paragraph_models import (
|
114
|
+
CreateParagraphBlock,
|
115
|
+
ParagraphBlock,
|
116
|
+
)
|
117
|
+
from notionary.blocks.pdf.pdf_models import CreatePdfBlock
|
118
|
+
from notionary.blocks.quote.quote_models import CreateQuoteBlock, QuoteBlock
|
119
|
+
from notionary.blocks.table.table_models import TableBlock, TableRowBlock
|
120
|
+
from notionary.blocks.table_of_contents.table_of_contents_models import (
|
121
|
+
CreateTableOfContentsBlock,
|
122
|
+
TableOfContentsBlock,
|
123
|
+
)
|
124
|
+
from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
|
125
|
+
from notionary.blocks.toggle.toggle_models import CreateToggleBlock, ToggleBlock
|
126
|
+
from notionary.blocks.types import BlockType
|
127
|
+
from notionary.blocks.video.video_element_models import CreateVideoBlock
|
128
|
+
from notionary.blocks.child_database.child_database_models import (
|
129
|
+
CreateChildDatabaseBlock,
|
130
|
+
ChildDatabaseBlock,
|
131
|
+
)
|
132
|
+
|
133
|
+
# Define the Union types that are needed for model rebuilding
|
134
|
+
BlockCreateRequest = Union[
|
135
|
+
CreateBookmarkBlock,
|
136
|
+
CreateBreadcrumbBlock,
|
137
|
+
CreateBulletedListItemBlock,
|
138
|
+
CreateCalloutBlock,
|
139
|
+
CreateChildPageBlock,
|
140
|
+
CreateCodeBlock,
|
141
|
+
CreateColumnListBlock,
|
142
|
+
CreateColumnBlock,
|
143
|
+
CreateDividerBlock,
|
144
|
+
CreateEmbedBlock,
|
145
|
+
CreateEquationBlock,
|
146
|
+
CreateFileBlock,
|
147
|
+
CreateHeading1Block,
|
148
|
+
CreateHeading2Block,
|
149
|
+
CreateHeading3Block,
|
150
|
+
CreateImageBlock,
|
151
|
+
CreateNumberedListItemBlock,
|
152
|
+
CreateParagraphBlock,
|
153
|
+
CreateQuoteBlock,
|
154
|
+
CreateToDoBlock,
|
155
|
+
CreateToggleBlock,
|
156
|
+
CreateVideoBlock,
|
157
|
+
CreateTableOfContentsBlock,
|
158
|
+
CreatePdfBlock,
|
159
|
+
CreateChildDatabaseBlock,
|
160
|
+
]
|
161
|
+
|
162
|
+
BlockCreateResult = Optional[BlockCreateRequest]
|
163
|
+
|
164
|
+
# Add all block types to namespace
|
165
|
+
ns.update(
|
166
|
+
{
|
167
|
+
"BlockType": BlockType,
|
168
|
+
"BookmarkBlock": BookmarkBlock,
|
169
|
+
"CreateBookmarkBlock": CreateBookmarkBlock,
|
170
|
+
"BreadcrumbBlock": BreadcrumbBlock,
|
171
|
+
"CreateBreadcrumbBlock": CreateBreadcrumbBlock,
|
172
|
+
"BulletedListItemBlock": BulletedListItemBlock,
|
173
|
+
"CreateBulletedListItemBlock": CreateBulletedListItemBlock,
|
174
|
+
"CalloutBlock": CalloutBlock,
|
175
|
+
"CreateCalloutBlock": CreateCalloutBlock,
|
176
|
+
"ChildPageBlock": ChildPageBlock,
|
177
|
+
"CreateChildPageBlock": CreateChildPageBlock,
|
178
|
+
"CodeBlock": CodeBlock,
|
179
|
+
"CreateCodeBlock": CreateCodeBlock,
|
180
|
+
"ColumnBlock": ColumnBlock,
|
181
|
+
"ColumnListBlock": ColumnListBlock,
|
182
|
+
"CreateColumnBlock": CreateColumnBlock,
|
183
|
+
"CreateColumnListBlock": CreateColumnListBlock,
|
184
|
+
"DividerBlock": DividerBlock,
|
185
|
+
"CreateDividerBlock": CreateDividerBlock,
|
186
|
+
"EmbedBlock": EmbedBlock,
|
187
|
+
"CreateEmbedBlock": CreateEmbedBlock,
|
188
|
+
"EquationBlock": EquationBlock,
|
189
|
+
"CreateEquationBlock": CreateEquationBlock,
|
190
|
+
"FileBlock": FileBlock,
|
191
|
+
"CreateFileBlock": CreateFileBlock,
|
192
|
+
"HeadingBlock": HeadingBlock,
|
193
|
+
"CreateHeading1Block": CreateHeading1Block,
|
194
|
+
"CreateHeading2Block": CreateHeading2Block,
|
195
|
+
"CreateHeading3Block": CreateHeading3Block,
|
196
|
+
"CreateImageBlock": CreateImageBlock,
|
197
|
+
"NumberedListItemBlock": NumberedListItemBlock,
|
198
|
+
"CreateNumberedListItemBlock": CreateNumberedListItemBlock,
|
199
|
+
"ParagraphBlock": ParagraphBlock,
|
200
|
+
"CreateParagraphBlock": CreateParagraphBlock,
|
201
|
+
"QuoteBlock": QuoteBlock,
|
202
|
+
"CreateQuoteBlock": CreateQuoteBlock,
|
203
|
+
"TableBlock": TableBlock,
|
204
|
+
"TableRowBlock": TableRowBlock,
|
205
|
+
"ToDoBlock": ToDoBlock,
|
206
|
+
"CreateToDoBlock": CreateToDoBlock,
|
207
|
+
"ToggleBlock": ToggleBlock,
|
208
|
+
"CreateToggleBlock": CreateToggleBlock,
|
209
|
+
"CreateVideoBlock": CreateVideoBlock,
|
210
|
+
"TableOfContentsBlock": TableOfContentsBlock,
|
211
|
+
"CreateTableOfContentsBlock": CreateTableOfContentsBlock,
|
212
|
+
"ChildDatabaseBlock": ChildDatabaseBlock,
|
213
|
+
# Add the Union types
|
214
|
+
"BlockCreateRequest": BlockCreateRequest,
|
215
|
+
"BlockCreateResult": BlockCreateResult,
|
216
|
+
}
|
217
|
+
)
|
218
|
+
|
219
|
+
# Now rebuild with complete namespace
|
220
|
+
models.Block.model_rebuild(_types_namespace=ns)
|
221
|
+
models.BlockChildrenResponse.model_rebuild(_types_namespace=ns)
|
222
|
+
|
223
|
+
# Rebuild all individual block models
|
224
|
+
BookmarkBlock.model_rebuild()
|
225
|
+
BreadcrumbBlock.model_rebuild()
|
226
|
+
BulletedListItemBlock.model_rebuild()
|
227
|
+
CalloutBlock.model_rebuild()
|
228
|
+
ChildPageBlock.model_rebuild()
|
229
|
+
CodeBlock.model_rebuild()
|
230
|
+
ColumnBlock.model_rebuild()
|
231
|
+
ColumnListBlock.model_rebuild()
|
232
|
+
DividerBlock.model_rebuild()
|
233
|
+
EmbedBlock.model_rebuild()
|
234
|
+
EquationBlock.model_rebuild()
|
235
|
+
FileBlock.model_rebuild()
|
236
|
+
HeadingBlock.model_rebuild()
|
237
|
+
NumberedListItemBlock.model_rebuild()
|
238
|
+
ParagraphBlock.model_rebuild()
|
239
|
+
QuoteBlock.model_rebuild()
|
240
|
+
TableBlock.model_rebuild()
|
241
|
+
TableRowBlock.model_rebuild()
|
242
|
+
ToDoBlock.model_rebuild()
|
243
|
+
ToggleBlock.model_rebuild()
|
244
|
+
TableOfContentsBlock.model_rebuild()
|
245
|
+
|
246
|
+
# Rebuild create models
|
247
|
+
CreateBookmarkBlock.model_rebuild()
|
248
|
+
CreateBreadcrumbBlock.model_rebuild()
|
249
|
+
CreateBulletedListItemBlock.model_rebuild()
|
250
|
+
CreateCalloutBlock.model_rebuild()
|
251
|
+
CreateChildPageBlock.model_rebuild()
|
252
|
+
CreateCodeBlock.model_rebuild()
|
253
|
+
CreateColumnListBlock.model_rebuild()
|
254
|
+
CreateColumnBlock.model_rebuild()
|
255
|
+
CreateDividerBlock.model_rebuild()
|
256
|
+
CreateEmbedBlock.model_rebuild()
|
257
|
+
CreateEquationBlock.model_rebuild()
|
258
|
+
CreateFileBlock.model_rebuild()
|
259
|
+
CreateHeading1Block.model_rebuild()
|
260
|
+
CreateHeading2Block.model_rebuild()
|
261
|
+
CreateHeading3Block.model_rebuild()
|
262
|
+
CreateImageBlock.model_rebuild()
|
263
|
+
CreateNumberedListItemBlock.model_rebuild()
|
264
|
+
CreateParagraphBlock.model_rebuild()
|
265
|
+
CreateQuoteBlock.model_rebuild()
|
266
|
+
CreateToDoBlock.model_rebuild()
|
267
|
+
CreateToggleBlock.model_rebuild()
|
268
|
+
CreateVideoBlock.model_rebuild()
|
269
|
+
CreateTableOfContentsBlock.model_rebuild()
|
270
|
+
|
271
|
+
_bootstrapped = True
|
@@ -1,7 +1,13 @@
|
|
1
|
-
from .audio_element import AudioElement
|
2
|
-
from .audio_markdown_node import
|
1
|
+
from notionary.blocks.audio.audio_element import AudioElement
|
2
|
+
from notionary.blocks.audio.audio_markdown_node import (
|
3
|
+
AudioMarkdownBlockParams,
|
4
|
+
AudioMarkdownNode,
|
5
|
+
)
|
6
|
+
from notionary.blocks.audio.audio_models import CreateAudioBlock
|
3
7
|
|
4
8
|
__all__ = [
|
5
9
|
"AudioElement",
|
10
|
+
"CreateAudioBlock",
|
6
11
|
"AudioMarkdownNode",
|
12
|
+
"AudioMarkdownBlockParams",
|
7
13
|
]
|
@@ -1,152 +1,115 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import re
|
2
|
-
from typing import
|
4
|
+
from typing import Optional
|
3
5
|
|
4
|
-
from notionary.blocks import
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
from notionary.blocks.shared.models import RichTextObject
|
6
|
+
from notionary.blocks.audio.audio_models import CreateAudioBlock
|
7
|
+
from notionary.blocks.base_block_element import BaseBlockElement
|
8
|
+
from notionary.blocks.file.file_element_models import ExternalFile, FileBlock, FileType
|
9
|
+
from notionary.blocks.mixins.captions import CaptionMixin
|
10
|
+
from notionary.blocks.syntax_prompt_builder import BlockElementMarkdownInformation
|
11
|
+
from notionary.blocks.models import Block, BlockCreateResult, BlockType
|
11
12
|
|
12
13
|
|
13
|
-
class AudioElement(
|
14
|
+
class AudioElement(BaseBlockElement, CaptionMixin):
|
14
15
|
"""
|
15
16
|
Handles conversion between Markdown audio embeds and Notion audio blocks.
|
16
17
|
|
17
18
|
Markdown audio syntax:
|
18
19
|
- [audio](https://example.com/audio.mp3) - Simple audio embed
|
19
|
-
- [audio](https://example.com/audio.mp3
|
20
|
+
- [audio](https://example.com/audio.mp3)(caption:Episode 1) - Audio with caption
|
21
|
+
- (caption:Background music)[audio](https://example.com/song.mp3) - caption before URL
|
20
22
|
|
21
23
|
Where:
|
22
24
|
- URL is the required audio file URL
|
23
|
-
- Caption
|
25
|
+
- Caption supports rich text formatting and is optional
|
24
26
|
"""
|
25
27
|
|
26
|
-
#
|
27
|
-
|
28
|
-
CAPTION_PATTERN = r'(?:\s+"([^"]+)")?'
|
28
|
+
# Simple pattern that matches just the audio link, CaptionMixin handles caption separately
|
29
|
+
AUDIO_PATTERN = re.compile(r"\[audio\]\((https?://[^\s\"]+)\)")
|
29
30
|
|
30
|
-
|
31
|
+
@classmethod
|
32
|
+
def _extract_audio_url(cls, text: str) -> Optional[str]:
|
33
|
+
"""Extract audio URL from text, handling caption patterns."""
|
34
|
+
# First remove any captions to get clean text for URL extraction
|
35
|
+
clean_text = cls.remove_caption(text)
|
31
36
|
|
32
|
-
|
33
|
-
|
37
|
+
# Now extract the URL from clean text
|
38
|
+
match = cls.AUDIO_PATTERN.search(clean_text)
|
39
|
+
if match:
|
40
|
+
return match.group(1)
|
34
41
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
if not m:
|
39
|
-
return False
|
40
|
-
url = m.group(1)
|
41
|
-
return cls._is_likely_audio_url(url)
|
42
|
+
return None
|
43
|
+
|
44
|
+
SUPPORTED_EXTENSIONS = {".mp3", ".wav", ".ogg", ".oga", ".m4a"}
|
42
45
|
|
43
46
|
@classmethod
|
44
|
-
def match_notion(cls, block:
|
45
|
-
"""Check if
|
46
|
-
return block.
|
47
|
+
def match_notion(cls, block: Block) -> bool:
|
48
|
+
"""Check if this element can handle the given Notion block."""
|
49
|
+
return block.type == BlockType.AUDIO
|
47
50
|
|
48
51
|
@classmethod
|
49
|
-
def markdown_to_notion(cls, text: str) ->
|
52
|
+
async def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
50
53
|
"""Convert markdown audio embed to Notion audio block."""
|
51
|
-
|
52
|
-
|
53
|
-
return None
|
54
|
-
|
55
|
-
url = audio_match.group(1)
|
56
|
-
caption_text = audio_match.group(2)
|
57
|
-
|
54
|
+
# Use our helper method to extract the URL
|
55
|
+
url = cls._extract_audio_url(text.strip())
|
58
56
|
if not url:
|
59
57
|
return None
|
60
58
|
|
61
|
-
# Validate URL if possible
|
62
59
|
if not cls._is_likely_audio_url(url):
|
63
|
-
|
64
|
-
pass
|
60
|
+
return None
|
65
61
|
|
66
|
-
|
62
|
+
# Use mixin to extract caption (if present anywhere in text)
|
63
|
+
caption_text = cls.extract_caption(text.strip())
|
64
|
+
caption_rich_text = cls.build_caption_rich_text(caption_text or "")
|
67
65
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
audio_data["caption"] = []
|
66
|
+
audio_content = FileBlock(
|
67
|
+
type=FileType.EXTERNAL,
|
68
|
+
external=ExternalFile(url=url),
|
69
|
+
caption=caption_rich_text,
|
70
|
+
)
|
74
71
|
|
75
|
-
return
|
72
|
+
return CreateAudioBlock(audio=audio_content)
|
76
73
|
|
77
74
|
@classmethod
|
78
|
-
def notion_to_markdown(cls, block:
|
75
|
+
async def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
79
76
|
"""Convert Notion audio block to markdown audio embed."""
|
80
|
-
if block.
|
77
|
+
if block.type != BlockType.AUDIO or block.audio is None:
|
81
78
|
return None
|
82
79
|
|
83
|
-
|
80
|
+
audio = block.audio
|
84
81
|
|
85
|
-
#
|
86
|
-
if
|
87
|
-
url = audio_data.get("external", {}).get("url", "")
|
88
|
-
else:
|
89
|
-
# Handle file or file_upload types if needed
|
82
|
+
# Only handle external audio
|
83
|
+
if audio.type != FileType.EXTERNAL or audio.external is None:
|
90
84
|
return None
|
91
|
-
|
85
|
+
url = audio.external.url
|
92
86
|
if not url:
|
93
87
|
return None
|
94
88
|
|
95
|
-
|
96
|
-
|
97
|
-
if
|
98
|
-
|
99
|
-
|
89
|
+
result = f"[audio]({url})"
|
90
|
+
|
91
|
+
# Add caption if present
|
92
|
+
caption_markdown = await cls.format_caption_for_markdown(audio.caption or [])
|
93
|
+
if caption_markdown:
|
94
|
+
result += caption_markdown
|
100
95
|
|
101
|
-
return
|
96
|
+
return result
|
102
97
|
|
103
98
|
@classmethod
|
104
|
-
def
|
105
|
-
"""
|
106
|
-
return
|
99
|
+
def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
|
100
|
+
"""Get system prompt information for audio blocks."""
|
101
|
+
return BlockElementMarkdownInformation(
|
102
|
+
block_type=cls.__name__,
|
103
|
+
description="Audio blocks embed audio files from external URLs with optional captions",
|
104
|
+
syntax_examples=[
|
105
|
+
"[audio](https://example.com/song.mp3)",
|
106
|
+
"[audio](https://example.com/podcast.wav)(caption:Episode 1)",
|
107
|
+
"(caption:Background music)[audio](https://soundcloud.com/track/123)",
|
108
|
+
"[audio](https://example.com/interview.mp3)(caption:**Live** interview)",
|
109
|
+
],
|
110
|
+
usage_guidelines="Use for embedding audio files like music, podcasts, or sound effects. Supports common audio formats (mp3, wav, ogg, m4a). Caption supports rich text formatting and is optional.",
|
111
|
+
)
|
107
112
|
|
108
113
|
@classmethod
|
109
114
|
def _is_likely_audio_url(cls, url: str) -> bool:
|
110
|
-
"""Check if URL likely points to an audio file."""
|
111
115
|
return any(url.lower().endswith(ext) for ext in cls.SUPPORTED_EXTENSIONS)
|
112
|
-
|
113
|
-
@classmethod
|
114
|
-
def _extract_text_content(cls, rich_text: List[dict[str, Any]]) -> str:
|
115
|
-
"""Extract plain text content from Notion rich_text elements."""
|
116
|
-
result = ""
|
117
|
-
for text_obj in rich_text:
|
118
|
-
if text_obj.get("type") == "text":
|
119
|
-
result += text_obj.get("text", {}).get("content", "")
|
120
|
-
elif "plain_text" in text_obj:
|
121
|
-
result += text_obj.get("plain_text", "")
|
122
|
-
return result
|
123
|
-
|
124
|
-
@classmethod
|
125
|
-
def get_llm_prompt_content(cls) -> ElementPromptContent:
|
126
|
-
"""
|
127
|
-
Returns structured LLM prompt metadata for the audio element.
|
128
|
-
"""
|
129
|
-
return (
|
130
|
-
ElementPromptBuilder()
|
131
|
-
.with_description(
|
132
|
-
"Embeds an audio file that can be played directly in the page."
|
133
|
-
)
|
134
|
-
.with_usage_guidelines(
|
135
|
-
"Use audio embeds when you want to include sound files, music, podcasts, "
|
136
|
-
"or voice recordings. Supports common audio formats like MP3, WAV, OGG, and M4A."
|
137
|
-
)
|
138
|
-
.with_syntax('')
|
139
|
-
.with_examples(
|
140
|
-
[
|
141
|
-
"[audio](https://example.com/song.mp3)",
|
142
|
-
'[audio](https://example.com/podcast.mp3 "Episode 1: Introduction")',
|
143
|
-
'[audio](https://example.com/sound.wav "Sound effect for presentation")',
|
144
|
-
'[audio](https://example.com/recording.m4a "Voice memo from meeting")',
|
145
|
-
]
|
146
|
-
)
|
147
|
-
.with_avoidance_guidelines(
|
148
|
-
"Ensure the URL points to a valid audio file. "
|
149
|
-
"Some audio formats may not be supported by all browsers."
|
150
|
-
)
|
151
|
-
.build()
|
152
|
-
)
|
@@ -1,8 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
|
2
3
|
from typing import Optional
|
4
|
+
|
3
5
|
from pydantic import BaseModel
|
4
6
|
|
5
|
-
from notionary.
|
7
|
+
from notionary.markdown.markdown_node import MarkdownNode
|
8
|
+
from notionary.blocks.mixins.captions import CaptionMarkdownNodeMixin
|
6
9
|
|
7
10
|
|
8
11
|
class AudioMarkdownBlockParams(BaseModel):
|
@@ -10,7 +13,7 @@ class AudioMarkdownBlockParams(BaseModel):
|
|
10
13
|
caption: Optional[str] = None
|
11
14
|
|
12
15
|
|
13
|
-
class AudioMarkdownNode(MarkdownNode):
|
16
|
+
class AudioMarkdownNode(MarkdownNode, CaptionMarkdownNodeMixin):
|
14
17
|
"""
|
15
18
|
Programmatic interface for creating Notion-style audio blocks.
|
16
19
|
"""
|
@@ -24,6 +27,11 @@ class AudioMarkdownNode(MarkdownNode):
|
|
24
27
|
return cls(url=params.url, caption=params.caption)
|
25
28
|
|
26
29
|
def to_markdown(self) -> str:
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
"""Return the Markdown representation.
|
31
|
+
|
32
|
+
Examples:
|
33
|
+
- [audio](https://example.com/song.mp3)
|
34
|
+
- [audio](https://example.com/song.mp3)(caption:Background music)
|
35
|
+
"""
|
36
|
+
base_markdown = f"[audio]({self.url})"
|
37
|
+
return self.append_caption_to_markdown(base_markdown, self.caption)
|