notionary 0.2.19__tar.gz → 0.2.21__tar.gz
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-0.2.19 → notionary-0.2.21}/PKG-INFO +12 -8
- {notionary-0.2.19 → notionary-0.2.21}/README.md +10 -7
- {notionary-0.2.19 → notionary-0.2.21}/notionary/__init__.py +8 -4
- {notionary-0.2.19 → notionary-0.2.21}/notionary/base_notion_client.py +3 -1
- notionary-0.2.21/notionary/blocks/__init__.py +3 -0
- notionary-0.2.21/notionary/blocks/_bootstrap.py +263 -0
- notionary-0.2.21/notionary/blocks/audio/__init__.py +13 -0
- notionary-0.2.21/notionary/blocks/audio/audio_element.py +90 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/audio/audio_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/audio/audio_models.py +10 -0
- notionary-0.2.21/notionary/blocks/base_block_element.py +30 -0
- notionary-0.2.21/notionary/blocks/bookmark/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/bookmark/bookmark_element.py +80 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/bookmark/bookmark_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/bookmark/bookmark_models.py +15 -0
- notionary-0.2.21/notionary/blocks/breadcrumbs/__init__.py +17 -0
- notionary-0.2.21/notionary/blocks/breadcrumbs/breadcrumb_element.py +39 -0
- notionary-0.2.21/notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +32 -0
- notionary-0.2.21/notionary/blocks/breadcrumbs/breadcrumb_models.py +12 -0
- notionary-0.2.21/notionary/blocks/bulleted_list/__init__.py +17 -0
- notionary-0.2.21/notionary/blocks/bulleted_list/bulleted_list_element.py +57 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/bulleted_list/bulleted_list_models.py +18 -0
- notionary-0.2.21/notionary/blocks/callout/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/callout/callout_element.py +83 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/callout/callout_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/callout/callout_models.py +33 -0
- notionary-0.2.21/notionary/blocks/child_database/__init__.py +7 -0
- notionary-0.2.21/notionary/blocks/child_database/child_database_models.py +19 -0
- notionary-0.2.21/notionary/blocks/child_page/__init__.py +9 -0
- notionary-0.2.21/notionary/blocks/child_page/child_page_models.py +12 -0
- notionary-0.2.19/notionary/blocks/shared/block_client.py → notionary-0.2.21/notionary/blocks/client.py +55 -54
- notionary-0.2.21/notionary/blocks/code/__init__.py +11 -0
- notionary-0.2.21/notionary/blocks/code/code_element.py +100 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/code/code_markdown_node.py +13 -13
- notionary-0.2.21/notionary/blocks/code/code_models.py +94 -0
- notionary-0.2.21/notionary/blocks/column/__init__.py +29 -0
- notionary-0.2.21/notionary/blocks/column/column_element.py +59 -0
- notionary-0.2.21/notionary/blocks/column/column_list_element.py +37 -0
- notionary-0.2.21/notionary/blocks/column/column_list_markdown_node.py +50 -0
- notionary-0.2.21/notionary/blocks/column/column_markdown_node.py +59 -0
- notionary-0.2.21/notionary/blocks/column/column_models.py +26 -0
- notionary-0.2.21/notionary/blocks/divider/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/divider/divider_element.py +49 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/divider/divider_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/divider/divider_models.py +12 -0
- notionary-0.2.21/notionary/blocks/embed/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/embed/embed_element.py +77 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/embed/embed_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/embed/embed_models.py +14 -0
- notionary-0.2.21/notionary/blocks/equation/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/equation/equation_element.py +80 -0
- notionary-0.2.21/notionary/blocks/equation/equation_element_markdown_node.py +36 -0
- notionary-0.2.21/notionary/blocks/equation/equation_models.py +11 -0
- notionary-0.2.21/notionary/blocks/file/__init__.py +25 -0
- notionary-0.2.21/notionary/blocks/file/file_element.py +93 -0
- notionary-0.2.21/notionary/blocks/file/file_element_markdown_node.py +35 -0
- notionary-0.2.21/notionary/blocks/file/file_element_models.py +39 -0
- notionary-0.2.21/notionary/blocks/heading/__init__.py +21 -0
- notionary-0.2.21/notionary/blocks/heading/heading_element.py +93 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/heading/heading_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/heading/heading_models.py +29 -0
- notionary-0.2.21/notionary/blocks/image_block/__init__.py +13 -0
- notionary-0.2.21/notionary/blocks/image_block/image_element.py +84 -0
- {notionary-0.2.19/notionary/blocks/image → notionary-0.2.21/notionary/blocks/image_block}/image_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/image_block/image_models.py +10 -0
- notionary-0.2.21/notionary/blocks/models.py +172 -0
- notionary-0.2.21/notionary/blocks/numbered_list/__init__.py +17 -0
- notionary-0.2.21/notionary/blocks/numbered_list/numbered_list_element.py +48 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/numbered_list/numbered_list_markdown_node.py +3 -1
- notionary-0.2.21/notionary/blocks/numbered_list/numbered_list_models.py +17 -0
- notionary-0.2.21/notionary/blocks/paragraph/__init__.py +17 -0
- notionary-0.2.21/notionary/blocks/paragraph/paragraph_element.py +42 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/paragraph/paragraph_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/paragraph/paragraph_models.py +16 -0
- notionary-0.2.21/notionary/blocks/pdf/__init__.py +13 -0
- notionary-0.2.21/notionary/blocks/pdf/pdf_element.py +91 -0
- notionary-0.2.21/notionary/blocks/pdf/pdf_markdown_node.py +35 -0
- notionary-0.2.21/notionary/blocks/pdf/pdf_models.py +11 -0
- notionary-0.2.21/notionary/blocks/quote/__init__.py +16 -0
- notionary-0.2.21/notionary/blocks/quote/quote_element.py +58 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/quote/quote_markdown_node.py +4 -1
- notionary-0.2.21/notionary/blocks/quote/quote_models.py +18 -0
- notionary-0.2.21/notionary/blocks/registry/__init__.py +4 -0
- notionary-0.2.21/notionary/blocks/registry/block_registry.py +140 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/registry/block_registry_builder.py +107 -59
- notionary-0.2.21/notionary/blocks/rich_text/__init__.py +33 -0
- notionary-0.2.21/notionary/blocks/rich_text/rich_text_models.py +188 -0
- notionary-0.2.21/notionary/blocks/rich_text/text_inline_formatter.py +125 -0
- notionary-0.2.21/notionary/blocks/table/__init__.py +21 -0
- notionary-0.2.21/notionary/blocks/table/table_element.py +124 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/table/table_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/table/table_models.py +28 -0
- notionary-0.2.21/notionary/blocks/table_of_contents/__init__.py +19 -0
- notionary-0.2.21/notionary/blocks/table_of_contents/table_of_contents_element.py +51 -0
- notionary-0.2.21/notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +35 -0
- notionary-0.2.21/notionary/blocks/table_of_contents/table_of_contents_models.py +18 -0
- notionary-0.2.21/notionary/blocks/todo/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/todo/todo_element.py +64 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/todo/todo_markdown_node.py +2 -1
- notionary-0.2.21/notionary/blocks/todo/todo_models.py +19 -0
- notionary-0.2.21/notionary/blocks/toggle/__init__.py +14 -0
- notionary-0.2.21/notionary/blocks/toggle/toggle_element.py +96 -0
- notionary-0.2.21/notionary/blocks/toggle/toggle_markdown_node.py +45 -0
- notionary-0.2.21/notionary/blocks/toggle/toggle_models.py +17 -0
- notionary-0.2.21/notionary/blocks/toggleable_heading/__init__.py +13 -0
- notionary-0.2.21/notionary/blocks/toggleable_heading/toggleable_heading_element.py +100 -0
- notionary-0.2.21/notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +51 -0
- notionary-0.2.21/notionary/blocks/types.py +61 -0
- notionary-0.2.21/notionary/blocks/video/__init__.py +13 -0
- notionary-0.2.21/notionary/blocks/video/video_element.py +106 -0
- notionary-0.2.21/notionary/blocks/video/video_element_models.py +10 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/blocks/video/video_markdown_node.py +3 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/client.py +3 -8
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/database.py +13 -14
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/database_filter_builder.py +2 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/database_provider.py +5 -4
- notionary-0.2.19/notionary/models/notion_database_response.py → notionary-0.2.21/notionary/database/models.py +5 -6
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/notion_database.py +6 -7
- {notionary-0.2.19 → notionary-0.2.21}/notionary/file_upload/client.py +5 -7
- {notionary-0.2.19 → notionary-0.2.21}/notionary/file_upload/models.py +2 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/file_upload/notion_file_upload.py +2 -3
- notionary-0.2.21/notionary/markdown/markdown_builder.py +722 -0
- notionary-0.2.21/notionary/markdown/markdown_document_model.py +228 -0
- {notionary-0.2.19/notionary/blocks → notionary-0.2.21/notionary/markdown}/markdown_node.py +1 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/page/client.py +9 -10
- notionary-0.2.21/notionary/page/models.py +327 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/page/notion_page.py +99 -52
- notionary-0.2.21/notionary/page/notion_text_length_utils.py +119 -0
- {notionary-0.2.19/notionary/page/content → notionary-0.2.21/notionary/page}/page_content_writer.py +88 -38
- notionary-0.2.21/notionary/page/reader/handler/__init__.py +17 -0
- notionary-0.2.21/notionary/page/reader/handler/base_block_renderer.py +44 -0
- notionary-0.2.21/notionary/page/reader/handler/block_processing_context.py +35 -0
- notionary-0.2.21/notionary/page/reader/handler/block_rendering_context.py +43 -0
- notionary-0.2.21/notionary/page/reader/handler/column_list_renderer.py +51 -0
- notionary-0.2.21/notionary/page/reader/handler/column_renderer.py +60 -0
- notionary-0.2.21/notionary/page/reader/handler/line_renderer.py +60 -0
- notionary-0.2.21/notionary/page/reader/handler/toggle_renderer.py +69 -0
- notionary-0.2.21/notionary/page/reader/handler/toggleable_heading_renderer.py +89 -0
- notionary-0.2.21/notionary/page/reader/page_content_retriever.py +69 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/page/search_filter_builder.py +2 -1
- notionary-0.2.21/notionary/page/writer/handler/__init__.py +22 -0
- notionary-0.2.21/notionary/page/writer/handler/code_handler.py +100 -0
- notionary-0.2.21/notionary/page/writer/handler/column_handler.py +141 -0
- notionary-0.2.21/notionary/page/writer/handler/column_list_handler.py +139 -0
- notionary-0.2.21/notionary/page/writer/handler/line_handler.py +35 -0
- notionary-0.2.21/notionary/page/writer/handler/line_processing_context.py +54 -0
- notionary-0.2.21/notionary/page/writer/handler/regular_line_handler.py +92 -0
- notionary-0.2.21/notionary/page/writer/handler/table_handler.py +130 -0
- notionary-0.2.21/notionary/page/writer/handler/toggle_handler.py +153 -0
- notionary-0.2.21/notionary/page/writer/handler/toggleable_heading_handler.py +167 -0
- notionary-0.2.21/notionary/page/writer/markdown_to_notion_converter.py +76 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/telemetry/__init__.py +2 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/telemetry/service.py +4 -3
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/__init__.py +2 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/base_notion_user.py +2 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/client.py +2 -3
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/models.py +1 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/notion_bot_user.py +4 -5
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/notion_user.py +3 -4
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/notion_user_manager.py +3 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/user/notion_user_provider.py +1 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/__init__.py +3 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/fuzzy.py +2 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/logging_mixin.py +2 -2
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/singleton_metaclass.py +1 -1
- {notionary-0.2.19 → notionary-0.2.21}/notionary/workspace.py +3 -2
- {notionary-0.2.19 → notionary-0.2.21}/pyproject.toml +5 -2
- notionary-0.2.19/notionary/blocks/__init__.py +0 -92
- notionary-0.2.19/notionary/blocks/audio/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/audio/audio_element.py +0 -152
- notionary-0.2.19/notionary/blocks/audio/audio_models.py +0 -59
- notionary-0.2.19/notionary/blocks/bookmark/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/bookmark/bookmark_element.py +0 -173
- notionary-0.2.19/notionary/blocks/bulleted_list/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/bulleted_list/bulleted_list_element.py +0 -72
- notionary-0.2.19/notionary/blocks/callout/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/callout/callout_element.py +0 -132
- notionary-0.2.19/notionary/blocks/code/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/code/code_element.py +0 -234
- notionary-0.2.19/notionary/blocks/column/__init__.py +0 -5
- notionary-0.2.19/notionary/blocks/column/column_element.py +0 -333
- notionary-0.2.19/notionary/blocks/column/column_models.py +0 -0
- notionary-0.2.19/notionary/blocks/divider/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/divider/divider_element.py +0 -72
- notionary-0.2.19/notionary/blocks/divider/divider_models.py +0 -0
- notionary-0.2.19/notionary/blocks/document/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/document/document_element.py +0 -102
- notionary-0.2.19/notionary/blocks/document/document_markdown_node.py +0 -31
- notionary-0.2.19/notionary/blocks/document/document_models.py +0 -0
- notionary-0.2.19/notionary/blocks/embed/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/embed/embed_element.py +0 -144
- notionary-0.2.19/notionary/blocks/embed/embed_models.py +0 -0
- notionary-0.2.19/notionary/blocks/heading/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/heading/heading_element.py +0 -98
- notionary-0.2.19/notionary/blocks/heading/heading_models.py +0 -0
- notionary-0.2.19/notionary/blocks/image/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/image/image_element.py +0 -151
- notionary-0.2.19/notionary/blocks/image/image_models.py +0 -0
- notionary-0.2.19/notionary/blocks/markdown_builder.py +0 -356
- notionary-0.2.19/notionary/blocks/mention/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/mention/mention_element.py +0 -229
- notionary-0.2.19/notionary/blocks/mention/mention_markdown_node.py +0 -38
- notionary-0.2.19/notionary/blocks/mention/mention_models.py +0 -0
- notionary-0.2.19/notionary/blocks/numbered_list/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/numbered_list/numbered_list_element.py +0 -73
- notionary-0.2.19/notionary/blocks/numbered_list/numbered_list_models.py +0 -0
- notionary-0.2.19/notionary/blocks/paragraph/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/paragraph/paragraph_element.py +0 -84
- notionary-0.2.19/notionary/blocks/paragraph/paragraph_models.py +0 -0
- notionary-0.2.19/notionary/blocks/prompts/element_prompt_builder.py +0 -83
- notionary-0.2.19/notionary/blocks/prompts/element_prompt_content.py +0 -41
- notionary-0.2.19/notionary/blocks/quote/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/quote/quote_element.py +0 -92
- notionary-0.2.19/notionary/blocks/quote/quote_models.py +0 -0
- notionary-0.2.19/notionary/blocks/registry/block_registry.py +0 -156
- notionary-0.2.19/notionary/blocks/shared/__init__.py +0 -0
- notionary-0.2.19/notionary/blocks/shared/models.py +0 -713
- notionary-0.2.19/notionary/blocks/shared/notion_block_element.py +0 -37
- notionary-0.2.19/notionary/blocks/shared/text_inline_formatter.py +0 -262
- notionary-0.2.19/notionary/blocks/shared/text_inline_formatter_new.py +0 -139
- notionary-0.2.19/notionary/blocks/table/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/table/table_element.py +0 -317
- notionary-0.2.19/notionary/blocks/table/table_models.py +0 -0
- notionary-0.2.19/notionary/blocks/todo/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/todo/todo_element.py +0 -121
- notionary-0.2.19/notionary/blocks/todo/todo_models.py +0 -0
- notionary-0.2.19/notionary/blocks/toggle/__init__.py +0 -4
- notionary-0.2.19/notionary/blocks/toggle/toggle_element.py +0 -303
- notionary-0.2.19/notionary/blocks/toggle/toggle_markdown_node.py +0 -35
- notionary-0.2.19/notionary/blocks/toggle/toggle_models.py +0 -0
- notionary-0.2.19/notionary/blocks/toggleable_heading/__init__.py +0 -9
- notionary-0.2.19/notionary/blocks/toggleable_heading/toggleable_heading_element.py +0 -270
- notionary-0.2.19/notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +0 -43
- notionary-0.2.19/notionary/blocks/toggleable_heading/toggleable_heading_models.py +0 -0
- notionary-0.2.19/notionary/blocks/video/__init__.py +0 -7
- notionary-0.2.19/notionary/blocks/video/video_element.py +0 -182
- notionary-0.2.19/notionary/database/models/page_result.py +0 -10
- notionary-0.2.19/notionary/elements/__init__.py +0 -0
- notionary-0.2.19/notionary/models/notion_block_response.py +0 -264
- notionary-0.2.19/notionary/models/notion_page_response.py +0 -78
- notionary-0.2.19/notionary/models/search_response.py +0 -0
- notionary-0.2.19/notionary/page/__init__.py +0 -0
- notionary-0.2.19/notionary/page/content/notion_text_length_utils.py +0 -87
- notionary-0.2.19/notionary/page/content/page_content_retriever.py +0 -60
- notionary-0.2.19/notionary/page/formatting/line_processor.py +0 -153
- notionary-0.2.19/notionary/page/formatting/markdown_to_notion_converter.py +0 -153
- notionary-0.2.19/notionary/page/markdown_syntax_prompt_generator.py +0 -114
- notionary-0.2.19/notionary/page/notion_to_markdown_converter.py +0 -179
- notionary-0.2.19/notionary/page/properites/property_value_extractor.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/LICENSE +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/__init__.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/exceptions.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/database/factory.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/file_upload/__init__.py +0 -0
- /notionary-0.2.19/notionary/blocks/bookmark/bookmark_models.py → /notionary-0.2.21/notionary/markdown/___init__.py +0 -0
- /notionary-0.2.19/notionary/blocks/bulleted_list/bulleted_list_models.py → /notionary-0.2.21/notionary/markdown/makdown_document_model.py +0 -0
- /notionary-0.2.19/notionary/blocks/callout/callout_models.py → /notionary-0.2.21/notionary/models/notion_database_response.py +0 -0
- {notionary-0.2.19/notionary/page/content → notionary-0.2.21/notionary/page}/markdown_whitespace_processor.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/page/property_formatter.py +0 -0
- /notionary-0.2.19/notionary/blocks/code/code_models.py → /notionary-0.2.21/notionary/page/reader/handler/context.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/page/utils.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/telemetry/views.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/factory_decorator.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/factory_only.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/page_id_utils.py +0 -0
- {notionary-0.2.19 → notionary-0.2.21}/notionary/util/singleton.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: notionary
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.21
|
4
4
|
Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
|
5
5
|
License: MIT
|
6
6
|
Author: Mathis Arends
|
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
16
|
Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
|
17
17
|
Requires-Dist: httpx (>=0.28.0)
|
18
|
+
Requires-Dist: isort (>=6.0.1,<7.0.0)
|
18
19
|
Requires-Dist: posthog (>=6.3.1,<7.0.0)
|
19
20
|
Requires-Dist: pydantic (>=2.11.4)
|
20
21
|
Requires-Dist: python-dotenv (>=1.1.0)
|
@@ -36,11 +37,11 @@ Description-Content-Type: text/markdown
|
|
36
37
|
- **Rich Markdown to Notion**: Convert extended Markdown (callouts, toggles, columns) directly into beautiful Notion blocks
|
37
38
|
- **Smart Discovery**: Find pages and databases by name with fuzzy matching - no more hunting for URLs
|
38
39
|
- **Async-First Architecture**: Built for modern Python with full async/await support and high performance
|
39
|
-
- **AI-Ready Integration**: Generate LLM system prompts and let AI agents create Notion content seamlessly
|
40
40
|
|
41
41
|
---
|
42
42
|
|
43
43
|
# Quick start
|
44
|
+
|
44
45
|
```bash
|
45
46
|
pip install notionary
|
46
47
|
```
|
@@ -53,29 +54,30 @@ NOTION_SECRET=YOUR_INTEGRATION_KEY
|
|
53
54
|
```
|
54
55
|
|
55
56
|
### Creating and Managing Pages 🚀
|
57
|
+
|
56
58
|
```python
|
57
59
|
from notionary import NotionPage
|
58
60
|
|
59
61
|
async def main():
|
60
62
|
# Simpy find an existing page by its title
|
61
63
|
page = await NotionPage.from_page_name("My Test Page")
|
62
|
-
|
64
|
+
|
63
65
|
# Add rich content with custom Markdown
|
64
66
|
content = """
|
65
67
|
# 🚀 Generated with Notionary
|
66
|
-
|
68
|
+
|
67
69
|
!> [💡] This page was created programmatically!
|
68
|
-
|
70
|
+
|
69
71
|
## Features
|
70
72
|
- **Rich** Markdown support
|
71
73
|
- Database integration
|
72
74
|
- AI-ready content generation
|
73
|
-
|
75
|
+
|
74
76
|
+++ Click to see more details
|
75
77
|
| Notionary makes it easy to create beautiful Notion pages
|
76
78
|
| directly from Python code with intuitive Markdown syntax.
|
77
79
|
"""
|
78
|
-
|
80
|
+
|
79
81
|
await page.replace_content(content)
|
80
82
|
print(f"✅ Page updated: {page.url}")
|
81
83
|
|
@@ -99,7 +101,7 @@ async def main():
|
|
99
101
|
await page.set_title("🆕 New Project Entry")
|
100
102
|
await page.set_property_value_by_name("Status", "In Progress")
|
101
103
|
await page.set_property_value_by_name("Priority", "High")
|
102
|
-
|
104
|
+
|
103
105
|
# find pages created in the last 7 days
|
104
106
|
count = 0
|
105
107
|
async for page in db.iter_pages_with_filter(
|
@@ -201,6 +203,7 @@ def hello_world():
|
|
201
203
|
Explore the `examples/` directory for comprehensive guides:
|
202
204
|
|
203
205
|
### 🚀 Core Examples
|
206
|
+
|
204
207
|
- [**Page Management**](examples/page_example.py) - Create, update, and manage Notion pages
|
205
208
|
- [**Page Operations**](examples/page.py) - Advanced page manipulation and content handling
|
206
209
|
- [**Database Operations**](examples/database.py) - Connect to and manage Notion databases
|
@@ -208,6 +211,7 @@ Explore the `examples/` directory for comprehensive guides:
|
|
208
211
|
- [**Workspace Discovery**](examples/workspace_discovery.py) - Explore and discover your Notion workspace
|
209
212
|
|
210
213
|
### 📝 Markdown Examples
|
214
|
+
|
211
215
|
- [**Basic Formatting**](examples/markdown/basic.py) - Text formatting, lists, and basic elements
|
212
216
|
- [**Callouts**](examples/markdown/callout.py) - Create beautiful callout blocks with icons
|
213
217
|
- [**Toggles**](examples/markdown/toggle.py) - Collapsible content sections
|
@@ -13,11 +13,11 @@
|
|
13
13
|
- **Rich Markdown to Notion**: Convert extended Markdown (callouts, toggles, columns) directly into beautiful Notion blocks
|
14
14
|
- **Smart Discovery**: Find pages and databases by name with fuzzy matching - no more hunting for URLs
|
15
15
|
- **Async-First Architecture**: Built for modern Python with full async/await support and high performance
|
16
|
-
- **AI-Ready Integration**: Generate LLM system prompts and let AI agents create Notion content seamlessly
|
17
16
|
|
18
17
|
---
|
19
18
|
|
20
19
|
# Quick start
|
20
|
+
|
21
21
|
```bash
|
22
22
|
pip install notionary
|
23
23
|
```
|
@@ -30,29 +30,30 @@ NOTION_SECRET=YOUR_INTEGRATION_KEY
|
|
30
30
|
```
|
31
31
|
|
32
32
|
### Creating and Managing Pages 🚀
|
33
|
+
|
33
34
|
```python
|
34
35
|
from notionary import NotionPage
|
35
36
|
|
36
37
|
async def main():
|
37
38
|
# Simpy find an existing page by its title
|
38
39
|
page = await NotionPage.from_page_name("My Test Page")
|
39
|
-
|
40
|
+
|
40
41
|
# Add rich content with custom Markdown
|
41
42
|
content = """
|
42
43
|
# 🚀 Generated with Notionary
|
43
|
-
|
44
|
+
|
44
45
|
!> [💡] This page was created programmatically!
|
45
|
-
|
46
|
+
|
46
47
|
## Features
|
47
48
|
- **Rich** Markdown support
|
48
49
|
- Database integration
|
49
50
|
- AI-ready content generation
|
50
|
-
|
51
|
+
|
51
52
|
+++ Click to see more details
|
52
53
|
| Notionary makes it easy to create beautiful Notion pages
|
53
54
|
| directly from Python code with intuitive Markdown syntax.
|
54
55
|
"""
|
55
|
-
|
56
|
+
|
56
57
|
await page.replace_content(content)
|
57
58
|
print(f"✅ Page updated: {page.url}")
|
58
59
|
|
@@ -76,7 +77,7 @@ async def main():
|
|
76
77
|
await page.set_title("🆕 New Project Entry")
|
77
78
|
await page.set_property_value_by_name("Status", "In Progress")
|
78
79
|
await page.set_property_value_by_name("Priority", "High")
|
79
|
-
|
80
|
+
|
80
81
|
# find pages created in the last 7 days
|
81
82
|
count = 0
|
82
83
|
async for page in db.iter_pages_with_filter(
|
@@ -178,6 +179,7 @@ def hello_world():
|
|
178
179
|
Explore the `examples/` directory for comprehensive guides:
|
179
180
|
|
180
181
|
### 🚀 Core Examples
|
182
|
+
|
181
183
|
- [**Page Management**](examples/page_example.py) - Create, update, and manage Notion pages
|
182
184
|
- [**Page Operations**](examples/page.py) - Advanced page manipulation and content handling
|
183
185
|
- [**Database Operations**](examples/database.py) - Connect to and manage Notion databases
|
@@ -185,6 +187,7 @@ Explore the `examples/` directory for comprehensive guides:
|
|
185
187
|
- [**Workspace Discovery**](examples/workspace_discovery.py) - Explore and discover your Notion workspace
|
186
188
|
|
187
189
|
### 📝 Markdown Examples
|
190
|
+
|
188
191
|
- [**Basic Formatting**](examples/markdown/basic.py) - Text formatting, lists, and basic elements
|
189
192
|
- [**Callouts**](examples/markdown/callout.py) - Create beautiful callout blocks with icons
|
190
193
|
- [**Toggles**](examples/markdown/toggle.py) - Collapsible content sections
|
@@ -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",
|
@@ -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()
|
@@ -0,0 +1,263 @@
|
|
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
|
+
)
|
38
|
+
|
39
|
+
# Collect all exports from modules
|
40
|
+
ns = {}
|
41
|
+
for m in (
|
42
|
+
bookmark,
|
43
|
+
breadcrumbs,
|
44
|
+
bulleted_list,
|
45
|
+
callout,
|
46
|
+
child_page,
|
47
|
+
code,
|
48
|
+
column,
|
49
|
+
divider,
|
50
|
+
embed,
|
51
|
+
equation,
|
52
|
+
file,
|
53
|
+
heading,
|
54
|
+
image_block,
|
55
|
+
numbered_list,
|
56
|
+
paragraph,
|
57
|
+
quote,
|
58
|
+
table,
|
59
|
+
todo,
|
60
|
+
toggle,
|
61
|
+
video,
|
62
|
+
toggleable_heading,
|
63
|
+
table_of_contents,
|
64
|
+
):
|
65
|
+
ns.update(vars(m))
|
66
|
+
|
67
|
+
# Add missing types that are needed for model rebuilding
|
68
|
+
# These are the types that are only defined in TYPE_CHECKING in block_models
|
69
|
+
from notionary.blocks.bookmark.bookmark_models import (
|
70
|
+
BookmarkBlock,
|
71
|
+
CreateBookmarkBlock,
|
72
|
+
)
|
73
|
+
from notionary.blocks.breadcrumbs.breadcrumb_models import (
|
74
|
+
BreadcrumbBlock,
|
75
|
+
CreateBreadcrumbBlock,
|
76
|
+
)
|
77
|
+
from notionary.blocks.bulleted_list.bulleted_list_models import (
|
78
|
+
BulletedListItemBlock,
|
79
|
+
CreateBulletedListItemBlock,
|
80
|
+
)
|
81
|
+
from notionary.blocks.callout.callout_models import CalloutBlock, CreateCalloutBlock
|
82
|
+
from notionary.blocks.child_page.child_page_models import (
|
83
|
+
ChildPageBlock,
|
84
|
+
CreateChildPageBlock,
|
85
|
+
)
|
86
|
+
from notionary.blocks.code.code_models import CodeBlock, CreateCodeBlock
|
87
|
+
from notionary.blocks.column.column_models import (
|
88
|
+
ColumnBlock,
|
89
|
+
ColumnListBlock,
|
90
|
+
CreateColumnBlock,
|
91
|
+
CreateColumnListBlock,
|
92
|
+
)
|
93
|
+
from notionary.blocks.divider.divider_models import CreateDividerBlock, DividerBlock
|
94
|
+
from notionary.blocks.embed.embed_models import CreateEmbedBlock, EmbedBlock
|
95
|
+
from notionary.blocks.equation.equation_models import (
|
96
|
+
CreateEquationBlock,
|
97
|
+
EquationBlock,
|
98
|
+
)
|
99
|
+
from notionary.blocks.file.file_element_models import CreateFileBlock, FileBlock
|
100
|
+
from notionary.blocks.heading.heading_models import (
|
101
|
+
CreateHeading1Block,
|
102
|
+
CreateHeading2Block,
|
103
|
+
CreateHeading3Block,
|
104
|
+
HeadingBlock,
|
105
|
+
)
|
106
|
+
from notionary.blocks.image_block.image_models import CreateImageBlock
|
107
|
+
from notionary.blocks.numbered_list.numbered_list_models import (
|
108
|
+
CreateNumberedListItemBlock,
|
109
|
+
NumberedListItemBlock,
|
110
|
+
)
|
111
|
+
from notionary.blocks.paragraph.paragraph_models import (
|
112
|
+
CreateParagraphBlock,
|
113
|
+
ParagraphBlock,
|
114
|
+
)
|
115
|
+
from notionary.blocks.pdf.pdf_models import CreatePdfBlock
|
116
|
+
from notionary.blocks.quote.quote_models import CreateQuoteBlock, QuoteBlock
|
117
|
+
from notionary.blocks.table.table_models import TableBlock, TableRowBlock
|
118
|
+
from notionary.blocks.table_of_contents.table_of_contents_models import (
|
119
|
+
CreateTableOfContentsBlock,
|
120
|
+
TableOfContentsBlock,
|
121
|
+
)
|
122
|
+
from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
|
123
|
+
from notionary.blocks.toggle.toggle_models import CreateToggleBlock, ToggleBlock
|
124
|
+
from notionary.blocks.types import BlockType
|
125
|
+
from notionary.blocks.video.video_element_models import CreateVideoBlock
|
126
|
+
|
127
|
+
# Define the Union types that are needed for model rebuilding
|
128
|
+
BlockCreateRequest = Union[
|
129
|
+
CreateBookmarkBlock,
|
130
|
+
CreateBreadcrumbBlock,
|
131
|
+
CreateBulletedListItemBlock,
|
132
|
+
CreateCalloutBlock,
|
133
|
+
CreateChildPageBlock,
|
134
|
+
CreateCodeBlock,
|
135
|
+
CreateColumnListBlock,
|
136
|
+
CreateColumnBlock,
|
137
|
+
CreateDividerBlock,
|
138
|
+
CreateEmbedBlock,
|
139
|
+
CreateEquationBlock,
|
140
|
+
CreateFileBlock,
|
141
|
+
CreateHeading1Block,
|
142
|
+
CreateHeading2Block,
|
143
|
+
CreateHeading3Block,
|
144
|
+
CreateImageBlock,
|
145
|
+
CreateNumberedListItemBlock,
|
146
|
+
CreateParagraphBlock,
|
147
|
+
CreateQuoteBlock,
|
148
|
+
CreateToDoBlock,
|
149
|
+
CreateToggleBlock,
|
150
|
+
CreateVideoBlock,
|
151
|
+
CreateTableOfContentsBlock,
|
152
|
+
CreatePdfBlock,
|
153
|
+
]
|
154
|
+
|
155
|
+
BlockCreateResult = Optional[Union[list[BlockCreateRequest], BlockCreateRequest]]
|
156
|
+
|
157
|
+
# Add all block types to namespace
|
158
|
+
ns.update(
|
159
|
+
{
|
160
|
+
"BlockType": BlockType,
|
161
|
+
"BookmarkBlock": BookmarkBlock,
|
162
|
+
"CreateBookmarkBlock": CreateBookmarkBlock,
|
163
|
+
"BreadcrumbBlock": BreadcrumbBlock,
|
164
|
+
"CreateBreadcrumbBlock": CreateBreadcrumbBlock,
|
165
|
+
"BulletedListItemBlock": BulletedListItemBlock,
|
166
|
+
"CreateBulletedListItemBlock": CreateBulletedListItemBlock,
|
167
|
+
"CalloutBlock": CalloutBlock,
|
168
|
+
"CreateCalloutBlock": CreateCalloutBlock,
|
169
|
+
"ChildPageBlock": ChildPageBlock,
|
170
|
+
"CreateChildPageBlock": CreateChildPageBlock,
|
171
|
+
"CodeBlock": CodeBlock,
|
172
|
+
"CreateCodeBlock": CreateCodeBlock,
|
173
|
+
"ColumnBlock": ColumnBlock,
|
174
|
+
"ColumnListBlock": ColumnListBlock,
|
175
|
+
"CreateColumnBlock": CreateColumnBlock,
|
176
|
+
"CreateColumnListBlock": CreateColumnListBlock,
|
177
|
+
"DividerBlock": DividerBlock,
|
178
|
+
"CreateDividerBlock": CreateDividerBlock,
|
179
|
+
"EmbedBlock": EmbedBlock,
|
180
|
+
"CreateEmbedBlock": CreateEmbedBlock,
|
181
|
+
"EquationBlock": EquationBlock,
|
182
|
+
"CreateEquationBlock": CreateEquationBlock,
|
183
|
+
"FileBlock": FileBlock,
|
184
|
+
"CreateFileBlock": CreateFileBlock,
|
185
|
+
"HeadingBlock": HeadingBlock,
|
186
|
+
"CreateHeading1Block": CreateHeading1Block,
|
187
|
+
"CreateHeading2Block": CreateHeading2Block,
|
188
|
+
"CreateHeading3Block": CreateHeading3Block,
|
189
|
+
"CreateImageBlock": CreateImageBlock,
|
190
|
+
"NumberedListItemBlock": NumberedListItemBlock,
|
191
|
+
"CreateNumberedListItemBlock": CreateNumberedListItemBlock,
|
192
|
+
"ParagraphBlock": ParagraphBlock,
|
193
|
+
"CreateParagraphBlock": CreateParagraphBlock,
|
194
|
+
"QuoteBlock": QuoteBlock,
|
195
|
+
"CreateQuoteBlock": CreateQuoteBlock,
|
196
|
+
"TableBlock": TableBlock,
|
197
|
+
"TableRowBlock": TableRowBlock,
|
198
|
+
"ToDoBlock": ToDoBlock,
|
199
|
+
"CreateToDoBlock": CreateToDoBlock,
|
200
|
+
"ToggleBlock": ToggleBlock,
|
201
|
+
"CreateToggleBlock": CreateToggleBlock,
|
202
|
+
"CreateVideoBlock": CreateVideoBlock,
|
203
|
+
"TableOfContentsBlock": TableOfContentsBlock,
|
204
|
+
"CreateTableOfContentsBlock": CreateTableOfContentsBlock,
|
205
|
+
# Add the Union types
|
206
|
+
"BlockCreateRequest": BlockCreateRequest,
|
207
|
+
"BlockCreateResult": BlockCreateResult,
|
208
|
+
}
|
209
|
+
)
|
210
|
+
|
211
|
+
# Now rebuild with complete namespace
|
212
|
+
models.Block.model_rebuild(_types_namespace=ns)
|
213
|
+
models.BlockChildrenResponse.model_rebuild(_types_namespace=ns)
|
214
|
+
|
215
|
+
# Rebuild all individual block models
|
216
|
+
BookmarkBlock.model_rebuild()
|
217
|
+
BreadcrumbBlock.model_rebuild()
|
218
|
+
BulletedListItemBlock.model_rebuild()
|
219
|
+
CalloutBlock.model_rebuild()
|
220
|
+
ChildPageBlock.model_rebuild()
|
221
|
+
CodeBlock.model_rebuild()
|
222
|
+
ColumnBlock.model_rebuild()
|
223
|
+
ColumnListBlock.model_rebuild()
|
224
|
+
DividerBlock.model_rebuild()
|
225
|
+
EmbedBlock.model_rebuild()
|
226
|
+
EquationBlock.model_rebuild()
|
227
|
+
FileBlock.model_rebuild()
|
228
|
+
HeadingBlock.model_rebuild()
|
229
|
+
NumberedListItemBlock.model_rebuild()
|
230
|
+
ParagraphBlock.model_rebuild()
|
231
|
+
QuoteBlock.model_rebuild()
|
232
|
+
TableBlock.model_rebuild()
|
233
|
+
TableRowBlock.model_rebuild()
|
234
|
+
ToDoBlock.model_rebuild()
|
235
|
+
ToggleBlock.model_rebuild()
|
236
|
+
TableOfContentsBlock.model_rebuild()
|
237
|
+
|
238
|
+
# Rebuild create models
|
239
|
+
CreateBookmarkBlock.model_rebuild()
|
240
|
+
CreateBreadcrumbBlock.model_rebuild()
|
241
|
+
CreateBulletedListItemBlock.model_rebuild()
|
242
|
+
CreateCalloutBlock.model_rebuild()
|
243
|
+
CreateChildPageBlock.model_rebuild()
|
244
|
+
CreateCodeBlock.model_rebuild()
|
245
|
+
CreateColumnListBlock.model_rebuild()
|
246
|
+
CreateColumnBlock.model_rebuild()
|
247
|
+
CreateDividerBlock.model_rebuild()
|
248
|
+
CreateEmbedBlock.model_rebuild()
|
249
|
+
CreateEquationBlock.model_rebuild()
|
250
|
+
CreateFileBlock.model_rebuild()
|
251
|
+
CreateHeading1Block.model_rebuild()
|
252
|
+
CreateHeading2Block.model_rebuild()
|
253
|
+
CreateHeading3Block.model_rebuild()
|
254
|
+
CreateImageBlock.model_rebuild()
|
255
|
+
CreateNumberedListItemBlock.model_rebuild()
|
256
|
+
CreateParagraphBlock.model_rebuild()
|
257
|
+
CreateQuoteBlock.model_rebuild()
|
258
|
+
CreateToDoBlock.model_rebuild()
|
259
|
+
CreateToggleBlock.model_rebuild()
|
260
|
+
CreateVideoBlock.model_rebuild()
|
261
|
+
CreateTableOfContentsBlock.model_rebuild()
|
262
|
+
|
263
|
+
_bootstrapped = True
|
@@ -0,0 +1,13 @@
|
|
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
|
7
|
+
|
8
|
+
__all__ = [
|
9
|
+
"AudioElement",
|
10
|
+
"CreateAudioBlock",
|
11
|
+
"AudioMarkdownNode",
|
12
|
+
"AudioMarkdownBlockParams",
|
13
|
+
]
|
@@ -0,0 +1,90 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import re
|
4
|
+
from typing import Optional
|
5
|
+
|
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.models import Block, BlockCreateResult, BlockType
|
10
|
+
from notionary.blocks.rich_text.rich_text_models import RichTextObject
|
11
|
+
from notionary.blocks.rich_text.text_inline_formatter import TextInlineFormatter
|
12
|
+
|
13
|
+
|
14
|
+
class AudioElement(BaseBlockElement):
|
15
|
+
"""
|
16
|
+
Handles conversion between Markdown audio embeds and Notion audio blocks.
|
17
|
+
|
18
|
+
Markdown audio syntax:
|
19
|
+
- [audio](https://example.com/audio.mp3) - Simple audio embed
|
20
|
+
- [audio](https://example.com/audio.mp3 "Caption text") - Audio with optional caption
|
21
|
+
|
22
|
+
Where:
|
23
|
+
- URL is the required audio file URL
|
24
|
+
- Caption is optional descriptive text (enclosed in quotes)
|
25
|
+
"""
|
26
|
+
|
27
|
+
URL_PATTERN = r"(https?://[^\s\"]+)"
|
28
|
+
CAPTION_PATTERN = r'(?:\s+"([^"]+)")?'
|
29
|
+
PATTERN = re.compile(r"^\[audio\]\(" + URL_PATTERN + CAPTION_PATTERN + r"\)$")
|
30
|
+
|
31
|
+
SUPPORTED_EXTENSIONS = {".mp3", ".wav", ".ogg", ".oga", ".m4a"}
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def match_notion(cls, block: Block) -> bool:
|
35
|
+
"""Check if this element can handle the given Notion block."""
|
36
|
+
return block.type == BlockType.AUDIO
|
37
|
+
|
38
|
+
@classmethod
|
39
|
+
def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
40
|
+
"""Convert markdown audio embed to Notion audio block (or return None if not matching)."""
|
41
|
+
match = cls.PATTERN.match(text.strip())
|
42
|
+
if not match:
|
43
|
+
return None
|
44
|
+
url = match.group(1)
|
45
|
+
|
46
|
+
if not cls._is_likely_audio_url(url):
|
47
|
+
return None
|
48
|
+
caption_text = match.group(2)
|
49
|
+
|
50
|
+
# Create caption rich text objects
|
51
|
+
caption_objects = []
|
52
|
+
if caption_text:
|
53
|
+
caption_rt = RichTextObject.from_plain_text(caption_text)
|
54
|
+
caption_objects = [caption_rt]
|
55
|
+
|
56
|
+
audio_content = FileBlock(
|
57
|
+
type=FileType.EXTERNAL,
|
58
|
+
external=ExternalFile(url=url),
|
59
|
+
caption=caption_objects,
|
60
|
+
)
|
61
|
+
|
62
|
+
return CreateAudioBlock(audio=audio_content)
|
63
|
+
|
64
|
+
@classmethod
|
65
|
+
def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
66
|
+
"""Convert Notion audio block to markdown audio embed."""
|
67
|
+
if block.type != BlockType.AUDIO or block.audio is None:
|
68
|
+
return None
|
69
|
+
|
70
|
+
audio = block.audio
|
71
|
+
|
72
|
+
# Only handle external audio
|
73
|
+
if audio.type != FileType.EXTERNAL or audio.external is None:
|
74
|
+
return None
|
75
|
+
url = audio.external.url
|
76
|
+
if not url:
|
77
|
+
return None
|
78
|
+
|
79
|
+
# Extract caption
|
80
|
+
captions = audio.caption or []
|
81
|
+
if captions:
|
82
|
+
# use TextInlineFormatter instead of manual extraction
|
83
|
+
caption_text = TextInlineFormatter.extract_text_with_formatting(captions)
|
84
|
+
return f'[audio]({url} "{caption_text}")'
|
85
|
+
|
86
|
+
return f"[audio]({url})"
|
87
|
+
|
88
|
+
@classmethod
|
89
|
+
def _is_likely_audio_url(cls, url: str) -> bool:
|
90
|
+
return any(url.lower().endswith(ext) for ext in cls.SUPPORTED_EXTENSIONS)
|
@@ -1,8 +1,10 @@
|
|
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
|
6
8
|
|
7
9
|
|
8
10
|
class AudioMarkdownBlockParams(BaseModel):
|
@@ -0,0 +1,30 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from abc import ABC
|
4
|
+
from typing import Optional
|
5
|
+
|
6
|
+
from notionary.blocks.models import Block, BlockCreateResult
|
7
|
+
|
8
|
+
|
9
|
+
class BaseBlockElement(ABC):
|
10
|
+
"""Base class for elements that can be converted between Markdown and Notion."""
|
11
|
+
|
12
|
+
@classmethod
|
13
|
+
def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
14
|
+
"""
|
15
|
+
Convert markdown to Notion block content.
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
- BlockContent: Single block content (e.g., ToDoBlock, ParagraphBlock)
|
19
|
+
- list[BlockContent]: Multiple block contents
|
20
|
+
- None: Cannot convert this markdown
|
21
|
+
"""
|
22
|
+
|
23
|
+
@classmethod
|
24
|
+
def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
25
|
+
"""Convert Notion block to markdown."""
|
26
|
+
|
27
|
+
@classmethod
|
28
|
+
def match_notion(cls, block: Block) -> bool:
|
29
|
+
"""Check if this element can handle the given Notion block."""
|
30
|
+
return bool(cls.notion_to_markdown(block)) # Now calls the class's version
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from notionary.blocks.bookmark.bookmark_element import BookmarkElement
|
2
|
+
from notionary.blocks.bookmark.bookmark_markdown_node import (
|
3
|
+
BookmarkMarkdownBlockParams,
|
4
|
+
BookmarkMarkdownNode,
|
5
|
+
)
|
6
|
+
from notionary.blocks.bookmark.bookmark_models import BookmarkBlock, CreateBookmarkBlock
|
7
|
+
|
8
|
+
__all__ = [
|
9
|
+
"BookmarkElement",
|
10
|
+
"BookmarkBlock",
|
11
|
+
"CreateBookmarkBlock",
|
12
|
+
"BookmarkMarkdownNode",
|
13
|
+
"BookmarkMarkdownBlockParams",
|
14
|
+
]
|