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
@@ -0,0 +1,93 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
from collections.abc import AsyncIterator
|
5
|
+
from typing import TYPE_CHECKING, Protocol
|
6
|
+
|
7
|
+
from notionary.exceptions.search import DatabaseNotFound, DataSourceNotFound, PageNotFound
|
8
|
+
from notionary.utils.fuzzy import find_best_match
|
9
|
+
from notionary.workspace.client import WorkspaceClient
|
10
|
+
from notionary.workspace.query.builder import WorkspaceQueryConfigBuilder
|
11
|
+
from notionary.workspace.query.models import WorkspaceQueryConfig
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from notionary import NotionDatabase, NotionDataSource, NotionPage
|
15
|
+
|
16
|
+
|
17
|
+
class SearchableEntity(Protocol):
|
18
|
+
title: str
|
19
|
+
|
20
|
+
|
21
|
+
class WorkspaceQueryService:
|
22
|
+
def __init__(self, client: WorkspaceClient | None = None) -> None:
|
23
|
+
self._client = client or WorkspaceClient()
|
24
|
+
|
25
|
+
async def get_pages_stream(self, search_config: WorkspaceQueryConfig) -> AsyncIterator[NotionPage]:
|
26
|
+
from notionary import NotionPage
|
27
|
+
|
28
|
+
async for page_dto in self._client.query_pages_stream(search_config):
|
29
|
+
yield await NotionPage.from_id(page_dto.id)
|
30
|
+
|
31
|
+
async def get_pages(self, search_config: WorkspaceQueryConfig) -> list[NotionPage]:
|
32
|
+
from notionary import NotionPage
|
33
|
+
|
34
|
+
page_dtos = [dto async for dto in self._client.query_pages_stream(search_config)]
|
35
|
+
page_tasks = [NotionPage.from_id(dto.id) for dto in page_dtos]
|
36
|
+
return await asyncio.gather(*page_tasks)
|
37
|
+
|
38
|
+
async def get_data_sources_stream(self, search_config: WorkspaceQueryConfig) -> AsyncIterator[NotionDataSource]:
|
39
|
+
from notionary import NotionDataSource
|
40
|
+
|
41
|
+
async for data_source_dto in self._client.query_data_sources_stream(search_config):
|
42
|
+
yield await NotionDataSource.from_id(data_source_dto.id)
|
43
|
+
|
44
|
+
async def get_data_sources(self, search_config: WorkspaceQueryConfig) -> list[NotionDataSource]:
|
45
|
+
from notionary import NotionDataSource
|
46
|
+
|
47
|
+
data_source_dtos = [dto async for dto in self._client.query_data_sources_stream(search_config)]
|
48
|
+
data_source_tasks = [NotionDataSource.from_id(dto.id) for dto in data_source_dtos]
|
49
|
+
return await asyncio.gather(*data_source_tasks)
|
50
|
+
|
51
|
+
async def find_data_source(self, query: str, min_similarity: float = 0.6) -> NotionDataSource:
|
52
|
+
config = WorkspaceQueryConfigBuilder().with_query(query).with_data_sources_only().with_page_size(5).build()
|
53
|
+
data_sources = await self.get_data_sources(config)
|
54
|
+
|
55
|
+
return self._get_best_match(
|
56
|
+
data_sources, query, exception_class=DataSourceNotFound, min_similarity=min_similarity
|
57
|
+
)
|
58
|
+
|
59
|
+
async def find_page(self, query: str, min_similarity: float = 0.6) -> NotionPage:
|
60
|
+
config = WorkspaceQueryConfigBuilder().with_query(query).with_pages_only().with_page_size(5).build()
|
61
|
+
pages = await self.get_pages(config)
|
62
|
+
|
63
|
+
return self._get_best_match(pages, query, exception_class=PageNotFound, min_similarity=min_similarity)
|
64
|
+
|
65
|
+
async def find_database(self, query: str = "") -> NotionDatabase:
|
66
|
+
config = WorkspaceQueryConfigBuilder().with_query(query).with_data_sources_only().with_page_size(100).build()
|
67
|
+
data_sources = await self.get_data_sources(config)
|
68
|
+
|
69
|
+
parent_database_tasks = [data_source.get_parent_database() for data_source in data_sources]
|
70
|
+
parent_databases = await asyncio.gather(*parent_database_tasks)
|
71
|
+
potential_databases = [database for database in parent_databases if database is not None]
|
72
|
+
|
73
|
+
return self._get_best_match(potential_databases, query, exception_class=DatabaseNotFound)
|
74
|
+
|
75
|
+
def _get_best_match(
|
76
|
+
self,
|
77
|
+
search_results: list[SearchableEntity],
|
78
|
+
query: str,
|
79
|
+
exception_class: type[Exception],
|
80
|
+
min_similarity: float | None = None,
|
81
|
+
) -> SearchableEntity:
|
82
|
+
best_match = find_best_match(
|
83
|
+
query=query,
|
84
|
+
items=search_results,
|
85
|
+
text_extractor=lambda searchable_entity: searchable_entity.title,
|
86
|
+
min_similarity=min_similarity,
|
87
|
+
)
|
88
|
+
|
89
|
+
if not best_match:
|
90
|
+
available_titles = [result.title for result in search_results[:5]]
|
91
|
+
raise exception_class(query, available_titles)
|
92
|
+
|
93
|
+
return best_match
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from typing import Generic, Literal, TypeVar
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
from notionary.data_source.schemas import DataSourceDto
|
6
|
+
from notionary.page.schemas import NotionPageDto
|
7
|
+
|
8
|
+
T = TypeVar("T", bound=BaseModel)
|
9
|
+
|
10
|
+
PageOrDataSource = DataSourceDto | NotionPageDto
|
11
|
+
|
12
|
+
|
13
|
+
class SearchResponse(BaseModel, Generic[T]):
|
14
|
+
results: list[T]
|
15
|
+
next_cursor: str | None = None
|
16
|
+
has_more: bool
|
17
|
+
type: Literal["page_or_data_source"]
|
18
|
+
|
19
|
+
|
20
|
+
PageSearchResponse = SearchResponse[NotionPageDto]
|
21
|
+
DataSourceSearchResponse = SearchResponse[DataSourceDto]
|
@@ -0,0 +1,116 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections.abc import AsyncIterator, Callable
|
4
|
+
from typing import TYPE_CHECKING, Self
|
5
|
+
|
6
|
+
from notionary.user.service import UserService
|
7
|
+
from notionary.workspace.query.builder import WorkspaceQueryConfigBuilder
|
8
|
+
from notionary.workspace.query.models import WorkspaceQueryConfig, WorkspaceQueryObjectType
|
9
|
+
from notionary.workspace.query.service import WorkspaceQueryService
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from notionary.data_source.service import NotionDataSource
|
13
|
+
from notionary.page.service import NotionPage
|
14
|
+
from notionary.user import BotUser, PersonUser
|
15
|
+
|
16
|
+
type _QueryConfigInput = WorkspaceQueryConfig | Callable[[WorkspaceQueryConfigBuilder], WorkspaceQueryConfigBuilder]
|
17
|
+
|
18
|
+
|
19
|
+
class NotionWorkspace:
|
20
|
+
def __init__(
|
21
|
+
self,
|
22
|
+
name: str | None = None,
|
23
|
+
query_service: WorkspaceQueryService | None = None,
|
24
|
+
user_service: UserService | None = None,
|
25
|
+
) -> None:
|
26
|
+
self._name = name
|
27
|
+
self._query_service = query_service or WorkspaceQueryService()
|
28
|
+
self._user_service = user_service or UserService()
|
29
|
+
|
30
|
+
@classmethod
|
31
|
+
async def from_current_integration(cls) -> Self:
|
32
|
+
from notionary.user import BotUser
|
33
|
+
|
34
|
+
bot_user = await BotUser.from_current_integration()
|
35
|
+
|
36
|
+
return cls(name=bot_user.workspace_name)
|
37
|
+
|
38
|
+
@property
|
39
|
+
def name(self) -> str:
|
40
|
+
return self._name
|
41
|
+
|
42
|
+
async def get_pages(
|
43
|
+
self,
|
44
|
+
config: _QueryConfigInput | None = None,
|
45
|
+
) -> list[NotionPage]:
|
46
|
+
query_config = self._resolve_config(config, default_object_type_to_query=WorkspaceQueryObjectType.PAGE)
|
47
|
+
return await self._query_service.get_pages(query_config)
|
48
|
+
|
49
|
+
async def get_pages_stream(
|
50
|
+
self,
|
51
|
+
config: _QueryConfigInput | None = None,
|
52
|
+
) -> AsyncIterator[NotionPage]:
|
53
|
+
query_config = self._resolve_config(config, default_object_type_to_query=WorkspaceQueryObjectType.PAGE)
|
54
|
+
async for page in self._query_service.get_pages_stream(query_config):
|
55
|
+
yield page
|
56
|
+
|
57
|
+
async def get_data_sources(
|
58
|
+
self,
|
59
|
+
config: _QueryConfigInput | None = None,
|
60
|
+
) -> list[NotionDataSource]:
|
61
|
+
query_config = self._resolve_config(config, default_object_type_to_query=WorkspaceQueryObjectType.DATA_SOURCE)
|
62
|
+
return await self._query_service.get_data_sources(query_config)
|
63
|
+
|
64
|
+
async def get_data_sources_stream(
|
65
|
+
self,
|
66
|
+
config: _QueryConfigInput | None = None,
|
67
|
+
) -> AsyncIterator[NotionDataSource]:
|
68
|
+
query_config = self._resolve_config(config, default_object_type_to_query=WorkspaceQueryObjectType.DATA_SOURCE)
|
69
|
+
async for data_source in self._query_service.get_data_sources_stream(query_config):
|
70
|
+
yield data_source
|
71
|
+
|
72
|
+
def _resolve_config(
|
73
|
+
self,
|
74
|
+
config: _QueryConfigInput | None,
|
75
|
+
default_object_type_to_query: WorkspaceQueryObjectType,
|
76
|
+
) -> WorkspaceQueryConfig:
|
77
|
+
if isinstance(config, WorkspaceQueryConfig):
|
78
|
+
return config
|
79
|
+
|
80
|
+
builder = self._create_builder_with_defaults(default_object_type_to_query)
|
81
|
+
|
82
|
+
if callable(config):
|
83
|
+
config(builder)
|
84
|
+
|
85
|
+
return builder.build()
|
86
|
+
|
87
|
+
def _create_builder_with_defaults(self, object_type: WorkspaceQueryObjectType) -> WorkspaceQueryConfigBuilder:
|
88
|
+
builder = WorkspaceQueryConfigBuilder()
|
89
|
+
|
90
|
+
if object_type == WorkspaceQueryObjectType.PAGE:
|
91
|
+
builder.with_pages_only()
|
92
|
+
else:
|
93
|
+
builder.with_data_sources_only()
|
94
|
+
|
95
|
+
return builder
|
96
|
+
|
97
|
+
async def get_users(self) -> list[PersonUser]:
|
98
|
+
return [user async for user in self._user_service.list_users_stream()]
|
99
|
+
|
100
|
+
async def get_users_stream(self) -> AsyncIterator[PersonUser]:
|
101
|
+
async for user in self._user_service.list_users_stream():
|
102
|
+
yield user
|
103
|
+
|
104
|
+
async def get_bot_users(self) -> list[BotUser]:
|
105
|
+
return [user async for user in self._user_service.list_bot_users_stream()]
|
106
|
+
|
107
|
+
async def get_bot_users_stream(self) -> AsyncIterator[BotUser]:
|
108
|
+
async for user in self._user_service.list_bot_users_stream():
|
109
|
+
yield user
|
110
|
+
|
111
|
+
async def search_users(self, query: str) -> list[PersonUser]:
|
112
|
+
return [user async for user in self._user_service.search_users_stream(query)]
|
113
|
+
|
114
|
+
async def search_users_stream(self, query: str) -> AsyncIterator[PersonUser]:
|
115
|
+
async for user in self._user_service.search_users_stream(query):
|
116
|
+
yield user
|
@@ -1,24 +1,16 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: notionary
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.28
|
4
4
|
Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
|
5
|
-
License: MIT
|
6
|
-
Author: Mathis Arends
|
7
|
-
Author-email: mathisarends27@gmail.com
|
8
|
-
Requires-Python: >=3.9
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
16
|
-
Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
|
17
|
-
Requires-Dist: httpx (>=0.28.0)
|
18
|
-
Requires-Dist: posthog (>=6.3.1,<7.0.0)
|
19
|
-
Requires-Dist: pydantic (>=2.11.4)
|
20
|
-
Requires-Dist: python-dotenv (>=1.1.0)
|
21
5
|
Project-URL: Homepage, https://github.com/mathisarends/notionary
|
6
|
+
Author-email: Mathis Arends <mathisarends27@gmail.com>
|
7
|
+
License: MIT
|
8
|
+
License-File: LICENSE
|
9
|
+
Requires-Python: >=3.11
|
10
|
+
Requires-Dist: aiofiles<25.0.0,>=24.1.0
|
11
|
+
Requires-Dist: httpx>=0.28.0
|
12
|
+
Requires-Dist: pydantic>=2.11.4
|
13
|
+
Requires-Dist: python-dotenv<2.0.0,>=1.0.1
|
22
14
|
Description-Content-Type: text/markdown
|
23
15
|
|
24
16
|
<picture>
|
@@ -35,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
35
27
|
[](LICENSE)
|
36
28
|
[](https://mathisarends.github.io/notionary/)
|
37
29
|
|
38
|
-
**Transform complex Notion API interactions into simple, Pythonic code.**
|
30
|
+
**Transform complex Notion API interactions into simple, Pythonic code.**
|
39
31
|
Perfect for developers building AI agents, automation workflows, and dynamic content systems.
|
40
32
|
|
41
33
|
</div>
|
@@ -73,13 +65,13 @@ export NOTION_SECRET=your_integration_key
|
|
73
65
|
|
74
66
|
https://github.com/user-attachments/assets/da8b4691-bee4-4b0f-801e-dccacb630398
|
75
67
|
|
76
|
-
|
68
|
+
_Create styled project pages with properties, content, and rich formatting_
|
77
69
|
|
78
70
|
### Local File Uploads (Videos & Images)
|
79
71
|
|
80
72
|
https://github.com/user-attachments/assets/a079ec01-bb56-4c65-8260-7b1fca42ac68
|
81
73
|
|
82
|
-
|
74
|
+
_Upload videos and images using simple markdown syntax - files are automatically uploaded to Notion_
|
83
75
|
|
84
76
|
---
|
85
77
|
|
@@ -93,33 +85,33 @@ from notionary import NotionPage, NotionDatabase
|
|
93
85
|
|
94
86
|
async def main():
|
95
87
|
# Find pages by name - fuzzy matching included!
|
96
|
-
page = await NotionPage.
|
97
|
-
|
88
|
+
page = await NotionPage.from_title("Meeting Notes")
|
89
|
+
|
98
90
|
# Option 1: Direct Extended Markdown
|
99
91
|
await page.append_markdown("""
|
100
92
|
## Action Items
|
101
93
|
- [x] Review project proposal
|
102
|
-
- [ ] Schedule team meeting
|
94
|
+
- [ ] Schedule team meeting
|
103
95
|
- [ ] Update documentation
|
104
96
|
|
105
97
|
[callout](Meeting decisions require follow-up "💡")
|
106
|
-
|
98
|
+
|
107
99
|
+++ Details
|
108
100
|
Additional context and next steps...
|
109
101
|
+++
|
110
102
|
""")
|
111
|
-
|
103
|
+
|
112
104
|
# Option 2: Type-Safe Builder (maps to same markdown internally)
|
113
105
|
await page.append_markdown(lambda builder: (
|
114
106
|
builder
|
115
|
-
.h2("Project Status")
|
107
|
+
.h2("Project Status")
|
116
108
|
.callout("Milestone reached!", "🎉")
|
117
109
|
.columns(
|
118
110
|
lambda col: col.h3("Completed").bulleted_list([
|
119
111
|
"API design", "Database setup", "Authentication"
|
120
112
|
]),
|
121
113
|
lambda col: col.h3("In Progress").bulleted_list([
|
122
|
-
"Frontend UI", "Testing", "Documentation"
|
114
|
+
"Frontend UI", "Testing", "Documentation"
|
123
115
|
]),
|
124
116
|
width_ratios=[0.6, 0.4]
|
125
117
|
)
|
@@ -138,33 +130,36 @@ asyncio.run(main())
|
|
138
130
|
|
139
131
|
Every Notion block type with extended syntax:
|
140
132
|
|
141
|
-
| Block Type
|
142
|
-
|
143
|
-
| **Callouts**
|
144
|
-
| **Toggles**
|
145
|
-
| **Columns**
|
146
|
-
| **Tables**
|
147
|
-
| **Media**
|
148
|
-
| **Code**
|
149
|
-
| **Equations** | `$LaTeX$`
|
150
|
-
| **TOC**
|
133
|
+
| Block Type | Markdown Syntax | Use Case |
|
134
|
+
| ------------- | -------------------------------------------- | ---------------------------- |
|
135
|
+
| **Callouts** | `[callout](Text "🔥")` | Highlighting key information |
|
136
|
+
| **Toggles** | `+++ Title\nContent\n+++` | Collapsible sections |
|
137
|
+
| **Columns** | `::: columns\n::: column\nContent\n:::\n:::` | Side-by-side layouts |
|
138
|
+
| **Tables** | Standard markdown tables | Structured data |
|
139
|
+
| **Media** | `[video](./file.mp4)(caption:Description)` | Auto-uploading files |
|
140
|
+
| **Code** | Standard code fences with captions | Code snippets |
|
141
|
+
| **Equations** | `$LaTeX$` | Mathematical expressions |
|
142
|
+
| **TOC** | `[toc](blue_background)` | Auto-generated navigation |
|
151
143
|
|
152
144
|
---
|
153
145
|
|
154
146
|
## What You Can Build 💡
|
155
147
|
|
156
148
|
### **AI Content Systems**
|
149
|
+
|
157
150
|
- **Report Generation**: AI agents that create structured reports, documentation, and analysis
|
158
151
|
- **Content Pipelines**: Automated workflows that process data and generate Notion pages
|
159
152
|
- **Knowledge Management**: AI-powered documentation systems with smart categorization
|
160
153
|
|
161
|
-
### **Workflow Automation**
|
154
|
+
### **Workflow Automation**
|
155
|
+
|
162
156
|
- **Project Management**: Sync project status, update timelines, generate progress reports
|
163
157
|
- **Data Integration**: Connect external APIs and databases to Notion workspaces
|
164
158
|
- **Template Systems**: Dynamic page generation from templates and data sources
|
165
159
|
|
166
160
|
### **Content Management**
|
167
|
-
|
161
|
+
|
162
|
+
- **Bulk Operations**: Mass page updates, content migration, and database management
|
168
163
|
- **Media Handling**: Automated image/video uploads with proper organization
|
169
164
|
- **Cross-Platform**: Sync content between Notion and other platforms
|
170
165
|
|
@@ -177,34 +172,40 @@ Every Notion block type with extended syntax:
|
|
177
172
|
<td width="50%">
|
178
173
|
|
179
174
|
### Smart Discovery
|
175
|
+
|
180
176
|
- Find pages/databases by name
|
181
|
-
- Fuzzy matching for approximate searches
|
177
|
+
- Fuzzy matching for approximate searches
|
182
178
|
- No more hunting for IDs or URLs
|
183
179
|
|
184
180
|
### Extended Markdown
|
181
|
+
|
185
182
|
- Rich syntax beyond standard markdown
|
186
183
|
- Callouts, toggles, columns, media uploads
|
187
184
|
- Schema provided for AI agent integration
|
188
185
|
|
189
|
-
### Modern Python
|
186
|
+
### Modern Python
|
187
|
+
|
190
188
|
- Full async/await support
|
191
|
-
- Type hints throughout
|
189
|
+
- Type hints throughout
|
192
190
|
- High-performance batch operations
|
193
191
|
|
194
192
|
</td>
|
195
193
|
<td width="50%">
|
196
194
|
|
197
195
|
### Round-Trip Editing
|
196
|
+
|
198
197
|
- Read existing content as markdown
|
199
198
|
- Edit and modify preserving formatting
|
200
199
|
- Write back to Notion seamlessly
|
201
200
|
|
202
201
|
### AI-Ready Architecture
|
202
|
+
|
203
203
|
- Schema-driven syntax for LLM prompts
|
204
204
|
- Perfect for AI content generation
|
205
205
|
- Handles complex nested structures
|
206
206
|
|
207
207
|
### Complete Coverage
|
208
|
+
|
208
209
|
- Every Notion block type supported
|
209
210
|
- File uploads with automatic handling
|
210
211
|
- Database operations and properties
|
@@ -218,24 +219,28 @@ Every Notion block type with extended syntax:
|
|
218
219
|
## Examples & Documentation
|
219
220
|
|
220
221
|
### Full Documentation
|
222
|
+
|
221
223
|
[**mathisarends.github.io/notionary**](https://mathisarends.github.io/notionary/) - Complete API reference, guides, and tutorials
|
222
224
|
|
223
225
|
### Quick Links
|
226
|
+
|
224
227
|
- [**Getting Started**](https://mathisarends.github.io/notionary/get-started/) - Setup and first steps
|
225
|
-
- [**Page Management**](https://mathisarends.github.io/notionary/page/) - Content and properties
|
228
|
+
- [**Page Management**](https://mathisarends.github.io/notionary/page/) - Content and properties
|
226
229
|
- [**Database Operations**](https://mathisarends.github.io/notionary/database/) - Queries and management
|
227
230
|
- [**Block Types Reference**](https://mathisarends.github.io/notionary/blocks/) - Complete syntax guide
|
228
231
|
|
229
232
|
### Hands-On Examples
|
230
233
|
|
231
234
|
**Core Functionality:**
|
235
|
+
|
232
236
|
- [Page Management](examples/page_example.py) - Create, update, and manage pages
|
233
|
-
- [Database Operations](examples/database.py) - Connect and query databases
|
237
|
+
- [Database Operations](examples/database.py) - Connect and query databases
|
234
238
|
- [Workspace Discovery](examples/workspace_discovery.py) - Explore your workspace
|
235
239
|
|
236
240
|
**Extended Markdown:**
|
241
|
+
|
237
242
|
- [Basic Formatting](examples/markdown/basic.py) - Text, lists, and links
|
238
|
-
- [Callouts & Highlights](examples/markdown/callout.py) - Information boxes
|
243
|
+
- [Callouts & Highlights](examples/markdown/callout.py) - Information boxes
|
239
244
|
- [Toggle Sections](examples/markdown/toggle.py) - Collapsible content
|
240
245
|
- [Multi-Column Layouts](examples/markdown/columns.py) - Side-by-side design
|
241
246
|
- [Tables & Data](examples/markdown/table.py) - Structured presentations
|
@@ -245,8 +250,9 @@ Every Notion block type with extended syntax:
|
|
245
250
|
## Contributing
|
246
251
|
|
247
252
|
We welcome contributions from the community! Whether you're:
|
253
|
+
|
248
254
|
- **Fixing bugs** - Help improve stability and reliability
|
249
|
-
- **Adding features** - Extend functionality for new use cases
|
255
|
+
- **Adding features** - Extend functionality for new use cases
|
250
256
|
- **Improving docs** - Make the library more accessible
|
251
257
|
- **Sharing examples** - Show creative applications and patterns
|
252
258
|
|
@@ -260,11 +266,10 @@ Check our [**Contributing Guide**](https://mathisarends.github.io/notionary/cont
|
|
260
266
|
|
261
267
|
[📖 **Read the Docs**](https://mathisarends.github.io/notionary/) • [🚀 **Getting Started**](https://mathisarends.github.io/notionary/get-started/) • [💻 **Browse Examples**](examples/)
|
262
268
|
|
263
|
-
|
269
|
+
_Built with ❤️ for Python developers and AI agents_
|
264
270
|
|
265
271
|
---
|
266
272
|
|
267
273
|
**Transform complex Notion API interactions into simple, powerful code.**
|
268
274
|
|
269
275
|
</div>
|
270
|
-
|