notionary 0.2.26__py3-none-any.whl → 0.2.28__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 +5 -20
- notionary/blocks/client.py +87 -215
- notionary/blocks/enums.py +167 -0
- notionary/blocks/rich_text/markdown_rich_text_converter.py +266 -0
- notionary/blocks/rich_text/models.py +164 -0
- notionary/blocks/rich_text/name_id_resolver/__init__.py +11 -0
- notionary/blocks/rich_text/name_id_resolver/database.py +31 -0
- notionary/blocks/rich_text/name_id_resolver/page.py +34 -0
- notionary/blocks/rich_text/name_id_resolver/person.py +37 -0
- notionary/blocks/rich_text/name_id_resolver/port.py +11 -0
- notionary/blocks/rich_text/rich_text_markdown_converter.py +132 -0
- notionary/blocks/rich_text/rich_text_patterns.py +39 -0
- notionary/blocks/schemas.py +746 -0
- notionary/comments/client.py +52 -187
- notionary/comments/factory.py +40 -0
- notionary/comments/models.py +5 -127
- notionary/comments/schemas.py +240 -0
- notionary/comments/service.py +34 -0
- notionary/data_source/http/client.py +11 -0
- notionary/data_source/http/data_source_instance_client.py +94 -0
- notionary/data_source/properties/models.py +406 -0
- notionary/data_source/query/builder.py +429 -0
- notionary/data_source/query/resolver.py +114 -0
- notionary/data_source/query/schema.py +304 -0
- notionary/data_source/query/validator.py +73 -0
- notionary/data_source/schemas.py +27 -0
- notionary/data_source/service.py +353 -0
- notionary/database/client.py +30 -135
- notionary/database/database_metadata_update_client.py +19 -0
- notionary/database/schemas.py +29 -0
- notionary/database/service.py +169 -0
- notionary/exceptions/__init__.py +33 -0
- notionary/exceptions/api.py +41 -0
- notionary/exceptions/base.py +2 -0
- notionary/exceptions/block_parsing.py +16 -0
- notionary/exceptions/data_source/__init__.py +6 -0
- notionary/exceptions/data_source/builder.py +182 -0
- notionary/exceptions/data_source/properties.py +34 -0
- notionary/exceptions/properties.py +58 -0
- notionary/exceptions/search.py +33 -0
- notionary/file_upload/client.py +18 -30
- notionary/file_upload/models.py +7 -8
- notionary/file_upload/{notion_file_upload.py → service.py} +29 -64
- notionary/http/client.py +205 -0
- notionary/http/models.py +49 -0
- notionary/page/blocks/client.py +1 -0
- notionary/page/content/factory.py +68 -0
- notionary/page/content/markdown/__init__.py +5 -0
- notionary/page/content/markdown/builder.py +304 -0
- notionary/page/content/markdown/nodes/__init__.py +54 -0
- notionary/page/content/markdown/nodes/audio.py +23 -0
- notionary/page/content/markdown/nodes/base.py +12 -0
- notionary/page/content/markdown/nodes/bookmark.py +25 -0
- notionary/page/content/markdown/nodes/breadcrumb.py +14 -0
- notionary/page/content/markdown/nodes/bulleted_list.py +18 -0
- notionary/page/content/markdown/nodes/callout.py +32 -0
- notionary/page/content/markdown/nodes/code.py +30 -0
- notionary/page/content/markdown/nodes/columns.py +51 -0
- notionary/page/content/markdown/nodes/divider.py +14 -0
- notionary/page/content/markdown/nodes/embed.py +23 -0
- notionary/page/content/markdown/nodes/equation.py +19 -0
- notionary/page/content/markdown/nodes/file.py +23 -0
- notionary/page/content/markdown/nodes/heading.py +16 -0
- notionary/page/content/markdown/nodes/image.py +23 -0
- notionary/page/content/markdown/nodes/mixins/caption.py +12 -0
- notionary/page/content/markdown/nodes/numbered_list.py +15 -0
- notionary/page/content/markdown/nodes/paragraph.py +14 -0
- notionary/page/content/markdown/nodes/pdf.py +23 -0
- notionary/page/content/markdown/nodes/quote.py +15 -0
- notionary/page/content/markdown/nodes/space.py +14 -0
- notionary/page/content/markdown/nodes/table.py +45 -0
- notionary/page/content/markdown/nodes/table_of_contents.py +14 -0
- notionary/page/content/markdown/nodes/todo.py +22 -0
- notionary/page/content/markdown/nodes/toggle.py +28 -0
- notionary/page/content/markdown/nodes/toggleable_heading.py +35 -0
- notionary/page/content/markdown/nodes/video.py +23 -0
- notionary/page/content/parser/context.py +49 -0
- notionary/page/content/parser/factory.py +219 -0
- notionary/page/content/parser/parsers/__init__.py +60 -0
- notionary/page/content/parser/parsers/audio.py +40 -0
- notionary/page/content/parser/parsers/base.py +30 -0
- notionary/page/content/parser/parsers/bookmark.py +33 -0
- notionary/page/content/parser/parsers/breadcrumb.py +33 -0
- notionary/page/content/parser/parsers/bulleted_list.py +41 -0
- notionary/page/content/parser/parsers/callout.py +129 -0
- notionary/page/content/parser/parsers/caption.py +55 -0
- notionary/page/content/parser/parsers/code.py +81 -0
- notionary/page/content/parser/parsers/column.py +117 -0
- notionary/page/content/parser/parsers/column_list.py +81 -0
- notionary/page/content/parser/parsers/divider.py +33 -0
- notionary/page/content/parser/parsers/embed.py +33 -0
- notionary/page/content/parser/parsers/equation.py +65 -0
- notionary/page/content/parser/parsers/file.py +42 -0
- notionary/page/content/parser/parsers/heading.py +58 -0
- notionary/page/content/parser/parsers/image.py +42 -0
- notionary/page/content/parser/parsers/numbered_list.py +45 -0
- notionary/page/content/parser/parsers/paragraph.py +36 -0
- notionary/page/content/parser/parsers/pdf.py +42 -0
- notionary/page/content/parser/parsers/quote.py +65 -0
- notionary/page/content/parser/parsers/space.py +35 -0
- notionary/page/content/parser/parsers/table.py +144 -0
- notionary/page/content/parser/parsers/table_of_contents.py +32 -0
- notionary/page/content/parser/parsers/todo.py +58 -0
- notionary/page/content/parser/parsers/toggle.py +127 -0
- notionary/page/content/parser/parsers/toggleable_heading.py +150 -0
- notionary/page/content/parser/parsers/video.py +42 -0
- notionary/page/content/parser/post_processing/handlers/__init__.py +5 -0
- notionary/page/content/parser/post_processing/handlers/rich_text_length.py +93 -0
- notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +93 -0
- notionary/page/content/parser/post_processing/port.py +9 -0
- notionary/page/content/parser/post_processing/service.py +16 -0
- notionary/page/content/parser/pre_processsing/handlers/__init__.py +9 -0
- notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +80 -0
- notionary/page/content/parser/pre_processsing/handlers/port.py +7 -0
- notionary/page/content/parser/pre_processsing/handlers/whitespace.py +68 -0
- notionary/page/content/parser/pre_processsing/service.py +15 -0
- notionary/page/content/parser/service.py +69 -0
- notionary/page/content/renderer/context.py +48 -0
- notionary/page/content/renderer/factory.py +240 -0
- notionary/page/content/renderer/post_processing/handlers/__init__.py +5 -0
- notionary/page/content/renderer/post_processing/handlers/numbered_list_placeholdere.py +62 -0
- notionary/page/content/renderer/post_processing/port.py +7 -0
- notionary/page/content/renderer/post_processing/service.py +15 -0
- notionary/page/content/renderer/renderers/__init__.py +57 -0
- notionary/page/content/renderer/renderers/audio.py +31 -0
- notionary/page/content/renderer/renderers/base.py +31 -0
- notionary/page/content/renderer/renderers/bookmark.py +25 -0
- notionary/page/content/renderer/renderers/breadcrumb.py +21 -0
- notionary/page/content/renderer/renderers/bulleted_list.py +48 -0
- notionary/page/content/renderer/renderers/callout.py +65 -0
- notionary/page/content/renderer/renderers/captioned_block.py +58 -0
- notionary/page/content/renderer/renderers/code.py +34 -0
- notionary/page/content/renderer/renderers/column.py +44 -0
- notionary/page/content/renderer/renderers/column_list.py +31 -0
- notionary/page/content/renderer/renderers/divider.py +22 -0
- notionary/page/content/renderer/renderers/embed.py +25 -0
- notionary/page/content/renderer/renderers/equation.py +37 -0
- notionary/page/content/renderer/renderers/fallback.py +24 -0
- notionary/page/content/renderer/renderers/file.py +40 -0
- notionary/page/content/renderer/renderers/heading.py +69 -0
- notionary/page/content/renderer/renderers/image.py +31 -0
- notionary/page/content/renderer/renderers/numbered_list.py +41 -0
- notionary/page/content/renderer/renderers/paragraph.py +40 -0
- notionary/page/content/renderer/renderers/pdf.py +31 -0
- notionary/page/content/renderer/renderers/quote.py +49 -0
- notionary/page/content/renderer/renderers/table.py +115 -0
- notionary/page/content/renderer/renderers/table_of_contents.py +26 -0
- notionary/page/content/renderer/renderers/table_row.py +17 -0
- notionary/page/content/renderer/renderers/todo.py +56 -0
- notionary/page/content/renderer/renderers/toggle.py +53 -0
- notionary/page/content/renderer/renderers/toggleable_heading.py +78 -0
- notionary/page/content/renderer/renderers/video.py +31 -0
- notionary/page/content/renderer/service.py +50 -0
- notionary/page/content/service.py +65 -0
- notionary/page/content/syntax/models.py +68 -0
- notionary/page/content/syntax/service.py +453 -0
- notionary/page/page_context.py +7 -16
- notionary/page/page_http_client.py +15 -0
- notionary/page/page_metadata_update_client.py +19 -0
- notionary/page/properties/client.py +144 -0
- notionary/page/properties/factory.py +26 -0
- notionary/page/properties/models.py +307 -0
- notionary/page/properties/service.py +257 -0
- notionary/page/schemas.py +13 -0
- notionary/page/service.py +222 -0
- notionary/shared/entity/client.py +29 -0
- notionary/shared/entity/dto_parsers.py +53 -0
- notionary/shared/entity/entity_metadata_update_client.py +41 -0
- notionary/shared/entity/schemas.py +45 -0
- notionary/shared/entity/service.py +171 -0
- notionary/shared/models/cover.py +20 -0
- notionary/shared/models/file.py +21 -0
- notionary/shared/models/icon.py +28 -0
- notionary/shared/models/parent.py +41 -0
- notionary/shared/properties/type.py +30 -0
- notionary/user/__init__.py +4 -8
- notionary/user/base.py +89 -0
- notionary/user/bot.py +70 -0
- notionary/user/client.py +22 -111
- notionary/user/person.py +41 -0
- notionary/user/schemas.py +67 -0
- notionary/user/service.py +65 -0
- notionary/utils/async_retry.py +39 -0
- notionary/utils/date.py +51 -0
- notionary/utils/fuzzy.py +56 -0
- notionary/{util/logging_mixin.py → utils/mixins/logging.py} +4 -16
- notionary/utils/pagination.py +50 -0
- notionary/utils/singleton.py +13 -0
- notionary/utils/uuid_utils.py +20 -0
- notionary/workspace/__init__.py +3 -0
- notionary/workspace/client.py +62 -0
- notionary/workspace/query/builder.py +60 -0
- notionary/workspace/query/models.py +60 -0
- notionary/workspace/query/service.py +93 -0
- notionary/workspace/schemas.py +21 -0
- notionary/workspace/service.py +116 -0
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/METADATA +54 -49
- notionary-0.2.28.dist-info/RECORD +200 -0
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/WHEEL +1 -1
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info/licenses}/LICENSE +9 -9
- notionary/base_notion_client.py +0 -219
- notionary/blocks/__init__.py +0 -5
- notionary/blocks/_bootstrap.py +0 -271
- notionary/blocks/audio/__init__.py +0 -11
- notionary/blocks/audio/audio_element.py +0 -158
- notionary/blocks/audio/audio_markdown_node.py +0 -24
- notionary/blocks/audio/audio_models.py +0 -10
- notionary/blocks/base_block_element.py +0 -42
- notionary/blocks/bookmark/__init__.py +0 -12
- notionary/blocks/bookmark/bookmark_element.py +0 -83
- notionary/blocks/bookmark/bookmark_markdown_node.py +0 -28
- notionary/blocks/bookmark/bookmark_models.py +0 -15
- notionary/blocks/breadcrumbs/__init__.py +0 -15
- notionary/blocks/breadcrumbs/breadcrumb_element.py +0 -39
- notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +0 -13
- notionary/blocks/breadcrumbs/breadcrumb_models.py +0 -12
- notionary/blocks/bulleted_list/__init__.py +0 -15
- notionary/blocks/bulleted_list/bulleted_list_element.py +0 -74
- notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +0 -20
- notionary/blocks/bulleted_list/bulleted_list_models.py +0 -17
- notionary/blocks/callout/__init__.py +0 -12
- notionary/blocks/callout/callout_element.py +0 -99
- notionary/blocks/callout/callout_markdown_node.py +0 -19
- notionary/blocks/callout/callout_models.py +0 -33
- notionary/blocks/child_database/__init__.py +0 -14
- notionary/blocks/child_database/child_database_element.py +0 -59
- notionary/blocks/child_database/child_database_models.py +0 -12
- notionary/blocks/child_page/__init__.py +0 -9
- notionary/blocks/child_page/child_page_element.py +0 -94
- notionary/blocks/child_page/child_page_models.py +0 -12
- notionary/blocks/code/__init__.py +0 -11
- notionary/blocks/code/code_element.py +0 -149
- notionary/blocks/code/code_markdown_node.py +0 -80
- notionary/blocks/code/code_models.py +0 -94
- notionary/blocks/column/__init__.py +0 -25
- notionary/blocks/column/column_element.py +0 -65
- notionary/blocks/column/column_list_element.py +0 -52
- notionary/blocks/column/column_list_markdown_node.py +0 -34
- notionary/blocks/column/column_markdown_node.py +0 -42
- notionary/blocks/column/column_models.py +0 -26
- notionary/blocks/divider/__init__.py +0 -12
- notionary/blocks/divider/divider_element.py +0 -41
- notionary/blocks/divider/divider_markdown_node.py +0 -11
- notionary/blocks/divider/divider_models.py +0 -12
- notionary/blocks/embed/__init__.py +0 -12
- notionary/blocks/embed/embed_element.py +0 -98
- notionary/blocks/embed/embed_markdown_node.py +0 -19
- notionary/blocks/embed/embed_models.py +0 -14
- notionary/blocks/equation/__init__.py +0 -13
- notionary/blocks/equation/equation_element.py +0 -133
- notionary/blocks/equation/equation_element_markdown_node.py +0 -23
- notionary/blocks/equation/equation_models.py +0 -11
- notionary/blocks/file/__init__.py +0 -23
- notionary/blocks/file/file_element.py +0 -133
- notionary/blocks/file/file_element_markdown_node.py +0 -24
- notionary/blocks/file/file_element_models.py +0 -39
- notionary/blocks/heading/__init__.py +0 -19
- notionary/blocks/heading/heading_element.py +0 -112
- notionary/blocks/heading/heading_markdown_node.py +0 -16
- notionary/blocks/heading/heading_models.py +0 -29
- notionary/blocks/image_block/__init__.py +0 -11
- notionary/blocks/image_block/image_element.py +0 -130
- notionary/blocks/image_block/image_markdown_node.py +0 -25
- notionary/blocks/image_block/image_models.py +0 -10
- notionary/blocks/markdown/markdown_builder.py +0 -525
- notionary/blocks/markdown/markdown_document_model.py +0 -0
- notionary/blocks/markdown/markdown_node.py +0 -25
- notionary/blocks/mixins/captions/__init__.py +0 -4
- notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +0 -31
- notionary/blocks/mixins/captions/caption_mixin.py +0 -92
- notionary/blocks/mixins/file_upload/__init__.py +0 -3
- notionary/blocks/mixins/file_upload/file_upload_mixin.py +0 -320
- notionary/blocks/models.py +0 -174
- notionary/blocks/numbered_list/__init__.py +0 -16
- notionary/blocks/numbered_list/numbered_list_element.py +0 -65
- notionary/blocks/numbered_list/numbered_list_markdown_node.py +0 -17
- notionary/blocks/numbered_list/numbered_list_models.py +0 -17
- notionary/blocks/paragraph/__init__.py +0 -15
- notionary/blocks/paragraph/paragraph_element.py +0 -58
- notionary/blocks/paragraph/paragraph_markdown_node.py +0 -16
- notionary/blocks/paragraph/paragraph_models.py +0 -16
- notionary/blocks/pdf/__init__.py +0 -11
- notionary/blocks/pdf/pdf_element.py +0 -146
- notionary/blocks/pdf/pdf_markdown_node.py +0 -24
- notionary/blocks/pdf/pdf_models.py +0 -11
- notionary/blocks/quote/__init__.py +0 -14
- notionary/blocks/quote/quote_element.py +0 -75
- notionary/blocks/quote/quote_markdown_node.py +0 -16
- notionary/blocks/quote/quote_models.py +0 -18
- notionary/blocks/registry/__init__.py +0 -3
- notionary/blocks/registry/block_registry.py +0 -150
- notionary/blocks/rich_text/__init__.py +0 -33
- notionary/blocks/rich_text/rich_text_models.py +0 -221
- notionary/blocks/rich_text/text_inline_formatter.py +0 -456
- notionary/blocks/syntax_prompt_builder.py +0 -137
- notionary/blocks/table/__init__.py +0 -19
- notionary/blocks/table/table_element.py +0 -225
- notionary/blocks/table/table_markdown_node.py +0 -42
- notionary/blocks/table/table_models.py +0 -28
- notionary/blocks/table_of_contents/__init__.py +0 -17
- notionary/blocks/table_of_contents/table_of_contents_element.py +0 -80
- notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +0 -21
- notionary/blocks/table_of_contents/table_of_contents_models.py +0 -18
- notionary/blocks/todo/__init__.py +0 -12
- notionary/blocks/todo/todo_element.py +0 -81
- notionary/blocks/todo/todo_markdown_node.py +0 -21
- notionary/blocks/todo/todo_models.py +0 -18
- notionary/blocks/toggle/__init__.py +0 -12
- notionary/blocks/toggle/toggle_element.py +0 -112
- notionary/blocks/toggle/toggle_markdown_node.py +0 -31
- notionary/blocks/toggle/toggle_models.py +0 -17
- notionary/blocks/toggleable_heading/__init__.py +0 -11
- notionary/blocks/toggleable_heading/toggleable_heading_element.py +0 -115
- notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +0 -34
- notionary/blocks/types.py +0 -130
- notionary/blocks/video/__init__.py +0 -11
- notionary/blocks/video/video_element.py +0 -187
- notionary/blocks/video/video_element_models.py +0 -10
- notionary/blocks/video/video_markdown_node.py +0 -26
- notionary/comments/__init__.py +0 -26
- notionary/database/__init__.py +0 -4
- notionary/database/database.py +0 -480
- notionary/database/database_filter_builder.py +0 -173
- notionary/database/database_provider.py +0 -227
- notionary/database/exceptions.py +0 -13
- notionary/database/factory.py +0 -0
- notionary/database/models.py +0 -337
- notionary/database/notion_database.py +0 -487
- notionary/file_upload/__init__.py +0 -7
- notionary/page/client.py +0 -124
- notionary/page/markdown_whitespace_processor.py +0 -129
- notionary/page/models.py +0 -322
- notionary/page/notion_page.py +0 -674
- notionary/page/page_content_deleting_service.py +0 -117
- notionary/page/page_content_writer.py +0 -80
- notionary/page/property_formatter.py +0 -99
- notionary/page/reader/handler/__init__.py +0 -19
- notionary/page/reader/handler/base_block_renderer.py +0 -44
- notionary/page/reader/handler/block_processing_context.py +0 -35
- notionary/page/reader/handler/block_rendering_context.py +0 -48
- notionary/page/reader/handler/column_list_renderer.py +0 -51
- notionary/page/reader/handler/column_renderer.py +0 -60
- notionary/page/reader/handler/equation_renderer.py +0 -0
- notionary/page/reader/handler/line_renderer.py +0 -73
- notionary/page/reader/handler/numbered_list_renderer.py +0 -85
- notionary/page/reader/handler/toggle_renderer.py +0 -69
- notionary/page/reader/handler/toggleable_heading_renderer.py +0 -89
- notionary/page/reader/page_content_retriever.py +0 -81
- notionary/page/search_filter_builder.py +0 -132
- notionary/page/utils.py +0 -60
- notionary/page/writer/handler/__init__.py +0 -24
- notionary/page/writer/handler/code_handler.py +0 -72
- notionary/page/writer/handler/column_handler.py +0 -141
- notionary/page/writer/handler/column_list_handler.py +0 -139
- notionary/page/writer/handler/equation_handler.py +0 -74
- notionary/page/writer/handler/line_handler.py +0 -35
- notionary/page/writer/handler/line_processing_context.py +0 -54
- notionary/page/writer/handler/regular_line_handler.py +0 -86
- notionary/page/writer/handler/table_handler.py +0 -66
- notionary/page/writer/handler/toggle_handler.py +0 -159
- notionary/page/writer/handler/toggleable_heading_handler.py +0 -174
- notionary/page/writer/markdown_to_notion_converter.py +0 -139
- notionary/page/writer/markdown_to_notion_converter_context.py +0 -30
- notionary/page/writer/markdown_to_notion_text_length_post_processor.py +0 -0
- notionary/page/writer/notion_text_length_processor.py +0 -150
- notionary/schemas/__init__.py +0 -3
- notionary/schemas/base.py +0 -73
- notionary/shared/__init__.py +0 -3
- notionary/shared/name_to_id_resolver.py +0 -203
- notionary/telemetry/__init__.py +0 -19
- notionary/telemetry/service.py +0 -136
- notionary/telemetry/views.py +0 -73
- notionary/user/base_notion_user.py +0 -53
- notionary/user/models.py +0 -84
- notionary/user/notion_bot_user.py +0 -226
- notionary/user/notion_user.py +0 -255
- notionary/user/notion_user_manager.py +0 -101
- notionary/util/__init__.py +0 -15
- notionary/util/concurrency_limiter.py +0 -0
- notionary/util/factory_decorator.py +0 -0
- notionary/util/factory_only.py +0 -37
- notionary/util/fuzzy.py +0 -75
- notionary/util/page_id_utils.py +0 -27
- notionary/util/singleton.py +0 -18
- notionary/util/singleton_metaclass.py +0 -22
- notionary/workspace.py +0 -105
- notionary-0.2.26.dist-info/RECORD +0 -202
notionary/__init__.py
CHANGED
@@ -1,22 +1,7 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
from .database import DatabaseFilterBuilder, NotionDatabase
|
6
|
-
from .file_upload import NotionFileUpload
|
7
|
-
from .blocks.markdown.markdown_builder import MarkdownBuilder
|
8
|
-
from .page.notion_page import NotionPage
|
9
|
-
from .user import NotionBotUser, NotionUser, NotionUserManager
|
1
|
+
from .data_source.service import NotionDataSource
|
2
|
+
from .database.service import NotionDatabase
|
3
|
+
from .page.content.markdown.builder import MarkdownBuilder
|
4
|
+
from .page.service import NotionPage
|
10
5
|
from .workspace import NotionWorkspace
|
11
6
|
|
12
|
-
__all__ = [
|
13
|
-
"NotionDatabase",
|
14
|
-
"DatabaseFilterBuilder",
|
15
|
-
"NotionPage",
|
16
|
-
"NotionWorkspace",
|
17
|
-
"NotionUser",
|
18
|
-
"NotionUserManager",
|
19
|
-
"NotionBotUser",
|
20
|
-
"NotionFileUpload",
|
21
|
-
"MarkdownBuilder",
|
22
|
-
]
|
7
|
+
__all__ = ["MarkdownBuilder", "NotionDataSource", "NotionDatabase", "NotionPage", "NotionWorkspace", "NotionWorkspace"]
|
notionary/blocks/client.py
CHANGED
@@ -1,65 +1,42 @@
|
|
1
|
-
from typing import Any
|
1
|
+
from typing import Any
|
2
2
|
|
3
|
-
from notionary.
|
4
|
-
from notionary.
|
3
|
+
from notionary.blocks.schemas import Block, BlockChildrenResponse, BlockCreatePayload
|
4
|
+
from notionary.http.client import NotionHttpClient
|
5
|
+
from notionary.utils.pagination import paginate_notion_api
|
5
6
|
|
6
7
|
|
7
|
-
class
|
8
|
-
|
9
|
-
Client for Notion Block API operations.
|
10
|
-
"""
|
11
|
-
|
12
|
-
async def get_block(self, block_id: str) -> Optional[Block]:
|
13
|
-
"""
|
14
|
-
Retrieves a single block by its ID.
|
15
|
-
"""
|
16
|
-
self.logger.debug("Retrieving block: %s", block_id)
|
8
|
+
class NotionBlockHttpClient(NotionHttpClient):
|
9
|
+
BATCH_SIZE = 100
|
17
10
|
|
11
|
+
async def get_block(self, block_id: str) -> Block:
|
18
12
|
response = await self.get(f"blocks/{block_id}")
|
19
|
-
|
20
|
-
try:
|
21
|
-
return Block.model_validate(response)
|
22
|
-
except Exception as e:
|
23
|
-
self.logger.error("Failed to parse block response: %s", str(e))
|
24
|
-
return None
|
25
|
-
return None
|
26
|
-
|
27
|
-
async def get_blocks_by_page_id_recursively(
|
28
|
-
self, page_id: str, parent_id: Optional[str] = None
|
29
|
-
) -> list[Block]:
|
30
|
-
response = (
|
31
|
-
await self.get_block_children(block_id=page_id)
|
32
|
-
if parent_id is None
|
33
|
-
else await self.get_block_children(block_id=parent_id)
|
34
|
-
)
|
13
|
+
return Block.model_validate(response)
|
35
14
|
|
36
|
-
|
37
|
-
|
15
|
+
async def delete_block(self, block_id: str) -> None:
|
16
|
+
self.logger.debug("Deleting block: %s", block_id)
|
17
|
+
await self.delete(f"blocks/{block_id}")
|
38
18
|
|
39
|
-
|
19
|
+
async def get_block_tree(self, parent_block_id: str) -> list[Block]:
|
20
|
+
blocks_at_this_level = await self.get_all_block_children(parent_block_id)
|
40
21
|
|
41
|
-
for block in
|
42
|
-
if
|
43
|
-
|
22
|
+
for block in blocks_at_this_level:
|
23
|
+
if block.has_children:
|
24
|
+
nested_children = await self.get_block_tree(parent_block_id=block.id)
|
25
|
+
block.children = nested_children
|
44
26
|
|
45
|
-
|
46
|
-
if not block_id:
|
47
|
-
continue
|
27
|
+
return blocks_at_this_level
|
48
28
|
|
49
|
-
|
50
|
-
|
51
|
-
)
|
52
|
-
if children:
|
53
|
-
block.children = children
|
29
|
+
async def get_all_block_children(self, parent_block_id: str) -> list[Block]:
|
30
|
+
self.logger.debug("Retrieving all children for block: %s", parent_block_id)
|
54
31
|
|
55
|
-
|
32
|
+
all_blocks = await paginate_notion_api(self.get_block_children, block_id=parent_block_id)
|
33
|
+
|
34
|
+
self.logger.debug("Retrieved %d total children for block %s", len(all_blocks), parent_block_id)
|
35
|
+
return all_blocks
|
56
36
|
|
57
37
|
async def get_block_children(
|
58
|
-
self, block_id: str, start_cursor:
|
59
|
-
) ->
|
60
|
-
"""
|
61
|
-
Retrieves the children of a block with pagination support.
|
62
|
-
"""
|
38
|
+
self, block_id: str, start_cursor: str | None = None, page_size: int = 100
|
39
|
+
) -> BlockChildrenResponse:
|
63
40
|
self.logger.debug("Retrieving children of block: %s", block_id)
|
64
41
|
|
65
42
|
params = {"page_size": min(page_size, 100)}
|
@@ -67,190 +44,85 @@ class NotionBlockClient(BaseNotionClient):
|
|
67
44
|
params["start_cursor"] = start_cursor
|
68
45
|
|
69
46
|
response = await self.get(f"blocks/{block_id}/children", params=params)
|
47
|
+
return BlockChildrenResponse.model_validate(response)
|
70
48
|
|
71
|
-
|
49
|
+
async def append_block_children(
|
50
|
+
self,
|
51
|
+
block_id: str,
|
52
|
+
children: list[BlockCreatePayload],
|
53
|
+
insert_after_block_id: str | None = None,
|
54
|
+
) -> BlockChildrenResponse | None:
|
55
|
+
if not children:
|
56
|
+
self.logger.warning("No children provided to append")
|
72
57
|
return None
|
73
58
|
|
74
|
-
|
75
|
-
return BlockChildrenResponse.model_validate(response)
|
76
|
-
except Exception as e:
|
77
|
-
self.logger.error("Failed to parse block children response: %s", str(e))
|
78
|
-
return None
|
59
|
+
self.logger.debug("Appending %d children to block: %s", len(children), block_id)
|
79
60
|
|
80
|
-
|
81
|
-
"""
|
82
|
-
Retrieves ALL children of a block, handling pagination automatically.
|
83
|
-
"""
|
84
|
-
all_blocks = []
|
85
|
-
cursor = None
|
61
|
+
batches = self._split_into_batches(children)
|
86
62
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
)
|
63
|
+
if len(batches) == 1:
|
64
|
+
children_dicts = self._serialize_blocks(batches[0])
|
65
|
+
return await self._send_append_request(block_id, children_dicts, insert_after_block_id)
|
91
66
|
|
92
|
-
|
93
|
-
break
|
67
|
+
return await self._send_batched_append_requests(block_id, batches, insert_after_block_id)
|
94
68
|
|
95
|
-
|
69
|
+
def _split_into_batches(self, blocks: list[BlockCreatePayload]) -> list[list[BlockCreatePayload]]:
|
70
|
+
batches = []
|
71
|
+
for i in range(0, len(blocks), self.BATCH_SIZE):
|
72
|
+
batch = blocks[i : i + self.BATCH_SIZE]
|
73
|
+
batches.append(batch)
|
74
|
+
return batches
|
96
75
|
|
97
|
-
|
98
|
-
|
76
|
+
def _serialize_blocks(self, blocks: list[BlockCreatePayload]) -> list[dict[str, Any]]:
|
77
|
+
return [block.model_dump(exclude_none=True) for block in blocks]
|
99
78
|
|
100
|
-
|
79
|
+
async def _send_append_request(
|
80
|
+
self, block_id: str, children: list[dict[str, Any]], after_block_id: str | None = None
|
81
|
+
) -> BlockChildrenResponse:
|
82
|
+
payload = {"children": children}
|
83
|
+
if after_block_id:
|
84
|
+
payload["after"] = after_block_id
|
101
85
|
|
102
|
-
self.
|
103
|
-
|
104
|
-
)
|
105
|
-
return all_blocks
|
86
|
+
response = await self.patch(f"blocks/{block_id}/children", payload)
|
87
|
+
return BlockChildrenResponse.model_validate(response)
|
106
88
|
|
107
|
-
async def
|
108
|
-
self,
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
) -> Optional[BlockChildrenResponse]:
|
113
|
-
"""
|
114
|
-
Appends new child blocks to a parent block.
|
115
|
-
Automatically handles batching for more than 100 blocks.
|
116
|
-
"""
|
117
|
-
if not children:
|
118
|
-
self.logger.warning("No children provided to append")
|
119
|
-
return None
|
89
|
+
async def _send_batched_append_requests(
|
90
|
+
self, block_id: str, batches: list[list[BlockCreatePayload]], initial_after_block_id: str | None = None
|
91
|
+
) -> BlockChildrenResponse:
|
92
|
+
total_blocks = sum(len(batch) for batch in batches)
|
93
|
+
self.logger.info("Appending %d blocks in %d batches", total_blocks, len(batches))
|
120
94
|
|
121
|
-
|
95
|
+
all_responses = []
|
96
|
+
after_block_id = initial_after_block_id
|
122
97
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
# If 100 or fewer blocks, use single request
|
127
|
-
if len(children_dicts) <= 100:
|
128
|
-
return await self._append_single_batch(block_id, children_dicts, after)
|
129
|
-
|
130
|
-
# For more than 100 blocks, use batch processing
|
131
|
-
return await self._append_multiple_batches(block_id, children_dicts, after)
|
132
|
-
|
133
|
-
async def _append_single_batch(
|
134
|
-
self, block_id: str, children: list[dict[str, Any]], after: Optional[str] = None
|
135
|
-
) -> Optional[BlockChildrenResponse]:
|
136
|
-
"""
|
137
|
-
Appends a single batch of blocks (≤100).
|
138
|
-
"""
|
139
|
-
data = {"children": children}
|
140
|
-
if after:
|
141
|
-
data["after"] = after
|
142
|
-
|
143
|
-
response = await self.patch(f"blocks/{block_id}/children", data)
|
144
|
-
if response:
|
145
|
-
try:
|
146
|
-
return BlockChildrenResponse.model_validate(response)
|
147
|
-
except Exception as e:
|
148
|
-
self.logger.error("Failed to parse append response: %s", str(e))
|
149
|
-
return None
|
150
|
-
return None
|
151
|
-
|
152
|
-
async def _append_multiple_batches(
|
153
|
-
self, block_id: str, children: list[dict[str, Any]], after: Optional[str] = None
|
154
|
-
) -> Optional[BlockChildrenResponse]:
|
155
|
-
"""
|
156
|
-
Appends multiple batches of blocks, handling pagination.
|
157
|
-
"""
|
158
|
-
all_results = []
|
159
|
-
current_after = after
|
160
|
-
batch_size = 100
|
161
|
-
|
162
|
-
self.logger.info(
|
163
|
-
"Processing %d blocks in batches of %d", len(children), batch_size
|
164
|
-
)
|
98
|
+
for batch_index, batch in enumerate(batches, start=1):
|
99
|
+
self.logger.debug("Processing batch %d/%d (%d blocks)", batch_index, len(batches), len(batch))
|
165
100
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
batch_num = (i // batch_size) + 1
|
170
|
-
total_batches = (len(children) + batch_size - 1) // batch_size
|
171
|
-
|
172
|
-
self.logger.debug(
|
173
|
-
"Processing batch %d/%d (%d blocks)",
|
174
|
-
batch_num,
|
175
|
-
total_batches,
|
176
|
-
len(batch),
|
177
|
-
)
|
178
|
-
|
179
|
-
# Append current batch
|
180
|
-
response = await self._append_single_batch(block_id, batch, current_after)
|
181
|
-
|
182
|
-
if not response:
|
183
|
-
self.logger.error(
|
184
|
-
"Failed to append batch %d/%d", batch_num, total_batches
|
185
|
-
)
|
186
|
-
# Return partial results if we have any
|
187
|
-
if all_results:
|
188
|
-
return self._combine_batch_responses(all_results)
|
189
|
-
return None
|
190
|
-
|
191
|
-
all_results.append(response)
|
192
|
-
|
193
|
-
# Update 'after' to the last block ID from this batch for next iteration
|
194
|
-
if response.results:
|
195
|
-
current_after = response.results[-1].id
|
101
|
+
children_dicts = self._serialize_blocks(batch)
|
102
|
+
response = await self._send_append_request(block_id, children_dicts, after_block_id)
|
103
|
+
all_responses.append(response)
|
196
104
|
|
197
|
-
|
198
|
-
|
199
|
-
)
|
105
|
+
if response.results:
|
106
|
+
after_block_id = response.results[-1].id
|
200
107
|
|
201
|
-
|
202
|
-
"Successfully appended all %d blocks in %d batches",
|
203
|
-
len(children),
|
204
|
-
len(all_results),
|
205
|
-
)
|
108
|
+
self.logger.debug("Completed batch %d/%d", batch_index, len(batches))
|
206
109
|
|
207
|
-
|
208
|
-
return self.
|
110
|
+
self.logger.info("Successfully appended all blocks in %d batches", len(batches))
|
111
|
+
return self._merge_responses(all_responses)
|
209
112
|
|
210
|
-
def
|
211
|
-
self, responses: list[BlockChildrenResponse]
|
212
|
-
) -> BlockChildrenResponse:
|
213
|
-
"""
|
214
|
-
Combines multiple batch responses into a single response.
|
215
|
-
"""
|
113
|
+
def _merge_responses(self, responses: list[BlockChildrenResponse]) -> BlockChildrenResponse:
|
216
114
|
if not responses:
|
217
|
-
|
218
|
-
return BlockChildrenResponse(
|
219
|
-
object="list",
|
220
|
-
results=[],
|
221
|
-
next_cursor=None,
|
222
|
-
has_more=False,
|
223
|
-
type="block",
|
224
|
-
block={},
|
225
|
-
request_id="",
|
226
|
-
)
|
227
|
-
|
228
|
-
# Use the first response as template and combine all results
|
229
|
-
combined = responses[0]
|
230
|
-
all_blocks = []
|
231
|
-
|
232
|
-
for response in responses:
|
233
|
-
all_blocks.extend(response.results)
|
234
|
-
|
235
|
-
# Create new combined response
|
236
|
-
return BlockChildrenResponse(
|
237
|
-
object=combined.object,
|
238
|
-
results=all_blocks,
|
239
|
-
next_cursor=None, # No pagination in combined result
|
240
|
-
has_more=False, # All blocks are included
|
241
|
-
type=combined.type,
|
242
|
-
block=combined.block,
|
243
|
-
request_id=responses[-1].request_id, # Use last request ID
|
244
|
-
)
|
115
|
+
raise ValueError("Cannot merge empty response list - this should never happen")
|
245
116
|
|
246
|
-
|
247
|
-
|
248
|
-
Deletes (archives) a block.
|
249
|
-
"""
|
250
|
-
self.logger.debug("Deleting block: %s", block_id)
|
117
|
+
first_response = responses[0]
|
118
|
+
all_results = [block for response in responses for block in response.results]
|
251
119
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
120
|
+
return BlockChildrenResponse(
|
121
|
+
object=first_response.object,
|
122
|
+
results=all_results,
|
123
|
+
next_cursor=None,
|
124
|
+
has_more=False,
|
125
|
+
type=first_response.type,
|
126
|
+
block=first_response.block,
|
127
|
+
request_id=responses[-1].request_id,
|
128
|
+
)
|
@@ -0,0 +1,167 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from enum import StrEnum
|
4
|
+
from typing import Self
|
5
|
+
|
6
|
+
|
7
|
+
class BlockColor(StrEnum):
|
8
|
+
BLUE = "blue"
|
9
|
+
BLUE_BACKGROUND = "blue_background"
|
10
|
+
BROWN = "brown"
|
11
|
+
BROWN_BACKGROUND = "brown_background"
|
12
|
+
DEFAULT = "default"
|
13
|
+
GRAY = "gray"
|
14
|
+
GRAY_BACKGROUND = "gray_background"
|
15
|
+
GREEN = "green"
|
16
|
+
GREEN_BACKGROUND = "green_background"
|
17
|
+
ORANGE = "orange"
|
18
|
+
ORANGE_BACKGROUND = "orange_background"
|
19
|
+
YELLOW = "yellow"
|
20
|
+
YELLOW_BACKGROUND = "yellow_background"
|
21
|
+
PINK = "pink"
|
22
|
+
PINK_BACKGROUND = "pink_background"
|
23
|
+
PURPLE = "purple"
|
24
|
+
PURPLE_BACKGROUND = "purple_background"
|
25
|
+
RED = "red"
|
26
|
+
RED_BACKGROUND = "red_background"
|
27
|
+
DEFAULT_BACKGROUND = "default_background"
|
28
|
+
|
29
|
+
|
30
|
+
class BlockType(StrEnum):
|
31
|
+
AUDIO = "audio"
|
32
|
+
BOOKMARK = "bookmark"
|
33
|
+
BREADCRUMB = "breadcrumb"
|
34
|
+
BULLETED_LIST_ITEM = "bulleted_list_item"
|
35
|
+
CALLOUT = "callout"
|
36
|
+
CHILD_DATABASE = "child_database"
|
37
|
+
CHILD_PAGE = "child_page"
|
38
|
+
CODE = "code"
|
39
|
+
COLUMN = "column"
|
40
|
+
COLUMN_LIST = "column_list"
|
41
|
+
DIVIDER = "divider"
|
42
|
+
EMBED = "embed"
|
43
|
+
EQUATION = "equation"
|
44
|
+
FILE = "file"
|
45
|
+
HEADING_1 = "heading_1"
|
46
|
+
HEADING_2 = "heading_2"
|
47
|
+
HEADING_3 = "heading_3"
|
48
|
+
IMAGE = "image"
|
49
|
+
LINK_PREVIEW = "link_preview"
|
50
|
+
LINK_TO_PAGE = "link_to_page"
|
51
|
+
NUMBERED_LIST_ITEM = "numbered_list_item"
|
52
|
+
PARAGRAPH = "paragraph"
|
53
|
+
PDF = "pdf"
|
54
|
+
QUOTE = "quote"
|
55
|
+
SYNCED_BLOCK = "synced_block"
|
56
|
+
TABLE = "table"
|
57
|
+
TABLE_OF_CONTENTS = "table_of_contents"
|
58
|
+
TABLE_ROW = "table_row"
|
59
|
+
TO_DO = "to_do"
|
60
|
+
TOGGLE = "toggle"
|
61
|
+
UNSUPPORTED = "unsupported"
|
62
|
+
VIDEO = "video"
|
63
|
+
|
64
|
+
|
65
|
+
class FileType(StrEnum):
|
66
|
+
EXTERNAL = "external"
|
67
|
+
FILE = "file"
|
68
|
+
FILE_UPLOAD = "file_upload"
|
69
|
+
|
70
|
+
|
71
|
+
class CodeLanguage(StrEnum):
|
72
|
+
ABAP = "abap"
|
73
|
+
ARDUINO = "arduino"
|
74
|
+
BASH = "bash"
|
75
|
+
BASIC = "basic"
|
76
|
+
C = "c"
|
77
|
+
CLOJURE = "clojure"
|
78
|
+
COFFEESCRIPT = "coffeescript"
|
79
|
+
CPP = "c++"
|
80
|
+
CSHARP = "c#"
|
81
|
+
CSS = "css"
|
82
|
+
DART = "dart"
|
83
|
+
DIFF = "diff"
|
84
|
+
DOCKER = "docker"
|
85
|
+
ELIXIR = "elixir"
|
86
|
+
ELM = "elm"
|
87
|
+
ERLANG = "erlang"
|
88
|
+
FLOW = "flow"
|
89
|
+
FORTRAN = "fortran"
|
90
|
+
FSHARP = "f#"
|
91
|
+
GHERKIN = "gherkin"
|
92
|
+
GLSL = "glsl"
|
93
|
+
GO = "go"
|
94
|
+
GRAPHQL = "graphql"
|
95
|
+
GROOVY = "groovy"
|
96
|
+
HASKELL = "haskell"
|
97
|
+
HTML = "html"
|
98
|
+
JAVA = "java"
|
99
|
+
JAVASCRIPT = "javascript"
|
100
|
+
JSON = "json"
|
101
|
+
JULIA = "julia"
|
102
|
+
KOTLIN = "kotlin"
|
103
|
+
LATEX = "latex"
|
104
|
+
LESS = "less"
|
105
|
+
LISP = "lisp"
|
106
|
+
LIVESCRIPT = "livescript"
|
107
|
+
LUA = "lua"
|
108
|
+
MAKEFILE = "makefile"
|
109
|
+
MARKDOWN = "markdown"
|
110
|
+
MARKUP = "markup"
|
111
|
+
MATLAB = "matlab"
|
112
|
+
MERMAID = "mermaid"
|
113
|
+
NIX = "nix"
|
114
|
+
OBJECTIVE_C = "objective-c"
|
115
|
+
OCAML = "ocaml"
|
116
|
+
PASCAL = "pascal"
|
117
|
+
PERL = "perl"
|
118
|
+
PHP = "php"
|
119
|
+
PLAIN_TEXT = "plain text"
|
120
|
+
POWERSHELL = "powershell"
|
121
|
+
PROLOG = "prolog"
|
122
|
+
PROTOBUF = "protobuf"
|
123
|
+
PYTHON = "python"
|
124
|
+
R = "r"
|
125
|
+
REASON = "reason"
|
126
|
+
RUBY = "ruby"
|
127
|
+
RUST = "rust"
|
128
|
+
SASS = "sass"
|
129
|
+
SCALA = "scala"
|
130
|
+
SCHEME = "scheme"
|
131
|
+
SCSS = "scss"
|
132
|
+
SHELL = "shell"
|
133
|
+
SQL = "sql"
|
134
|
+
SWIFT = "swift"
|
135
|
+
TYPESCRIPT = "typescript"
|
136
|
+
VB_NET = "vb.net"
|
137
|
+
VERILOG = "verilog"
|
138
|
+
VHDL = "vhdl"
|
139
|
+
VISUAL_BASIC = "visual basic"
|
140
|
+
WEBASSEMBLY = "webassembly"
|
141
|
+
XML = "xml"
|
142
|
+
YAML = "yaml"
|
143
|
+
JAVA_C_CPP_CSHARP = "java/c/c++/c#"
|
144
|
+
|
145
|
+
@classmethod
|
146
|
+
def from_string(cls, lang_str: str | None, default: Self | None = None) -> Self:
|
147
|
+
if not lang_str:
|
148
|
+
return default if default is not None else cls.PLAIN_TEXT
|
149
|
+
|
150
|
+
normalized = lang_str.lower().strip()
|
151
|
+
|
152
|
+
aliases = {
|
153
|
+
"cpp": cls.CPP,
|
154
|
+
"c++": cls.CPP,
|
155
|
+
"js": cls.JAVASCRIPT,
|
156
|
+
"py": cls.PYTHON,
|
157
|
+
"ts": cls.TYPESCRIPT,
|
158
|
+
}
|
159
|
+
|
160
|
+
if normalized in aliases:
|
161
|
+
return aliases[normalized]
|
162
|
+
|
163
|
+
for member in cls:
|
164
|
+
if member.value.lower() == normalized:
|
165
|
+
return member
|
166
|
+
|
167
|
+
return default if default is not None else cls.PLAIN_TEXT
|