notionary 0.2.27__py3-none-any.whl → 0.3.0__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/__init__.py +4 -4
- notionary/blocks/client.py +90 -216
- notionary/blocks/enums.py +167 -0
- notionary/blocks/rich_text/markdown_rich_text_converter.py +280 -0
- notionary/blocks/rich_text/models.py +178 -0
- notionary/blocks/rich_text/name_id_resolver/__init__.py +13 -0
- notionary/blocks/rich_text/name_id_resolver/data_source.py +32 -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 +144 -0
- notionary/blocks/rich_text/rich_text_patterns.py +42 -0
- notionary/blocks/schemas.py +778 -0
- notionary/comments/__init__.py +1 -22
- notionary/comments/client.py +52 -187
- notionary/comments/factory.py +38 -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 +104 -0
- notionary/data_source/properties/schemas.py +402 -0
- notionary/data_source/query/builder.py +448 -0
- notionary/data_source/query/resolver.py +114 -0
- notionary/data_source/query/schema.py +302 -0
- notionary/data_source/query/validator.py +73 -0
- notionary/data_source/schema/registry.py +104 -0
- notionary/data_source/schema/service.py +136 -0
- notionary/data_source/schemas.py +27 -0
- notionary/data_source/service.py +377 -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 +168 -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 +57 -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 +204 -0
- notionary/http/models.py +50 -0
- notionary/page/blocks/client.py +1 -0
- notionary/page/content/factory.py +73 -0
- notionary/page/content/markdown/__init__.py +5 -0
- notionary/page/content/markdown/builder.py +226 -0
- notionary/page/content/markdown/nodes/__init__.py +52 -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 +41 -0
- notionary/page/content/markdown/nodes/callout.py +34 -0
- notionary/page/content/markdown/nodes/code.py +28 -0
- notionary/page/content/markdown/nodes/columns.py +69 -0
- notionary/page/content/markdown/nodes/container.py +64 -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 +36 -0
- notionary/page/content/markdown/nodes/image.py +23 -0
- notionary/page/content/markdown/nodes/mixins/__init__.py +5 -0
- notionary/page/content/markdown/nodes/mixins/caption.py +12 -0
- notionary/page/content/markdown/nodes/numbered_list.py +38 -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 +27 -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 +38 -0
- notionary/page/content/markdown/nodes/toggle.py +27 -0
- notionary/page/content/markdown/nodes/video.py +23 -0
- notionary/page/content/parser/context.py +126 -0
- notionary/page/content/parser/factory.py +210 -0
- notionary/page/content/parser/parsers/__init__.py +58 -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 +85 -0
- notionary/page/content/parser/parsers/callout.py +100 -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 +76 -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 +115 -0
- notionary/page/content/parser/parsers/image.py +42 -0
- notionary/page/content/parser/parsers/numbered_list.py +89 -0
- notionary/page/content/parser/parsers/paragraph.py +37 -0
- notionary/page/content/parser/parsers/pdf.py +42 -0
- notionary/page/content/parser/parsers/quote.py +125 -0
- notionary/page/content/parser/parsers/space.py +41 -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 +96 -0
- notionary/page/content/parser/parsers/toggle.py +70 -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 +95 -0
- notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +114 -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 +11 -0
- notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +130 -0
- notionary/page/content/parser/pre_processsing/handlers/indentation.py +84 -0
- notionary/page/content/parser/pre_processsing/handlers/port.py +7 -0
- notionary/page/content/parser/pre_processsing/handlers/whitespace.py +73 -0
- notionary/page/content/parser/pre_processsing/service.py +15 -0
- notionary/page/content/parser/service.py +78 -0
- notionary/page/content/renderer/context.py +51 -0
- notionary/page/content/renderer/factory.py +231 -0
- notionary/page/content/renderer/post_processing/handlers/__init__.py +5 -0
- notionary/page/content/renderer/post_processing/handlers/numbered_list.py +156 -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 +55 -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 +50 -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 +53 -0
- notionary/page/content/renderer/renderers/column_list.py +44 -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 +95 -0
- notionary/page/content/renderer/renderers/image.py +31 -0
- notionary/page/content/renderer/renderers/numbered_list.py +42 -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 +52 -0
- notionary/page/content/renderer/renderers/video.py +31 -0
- notionary/page/content/renderer/service.py +50 -0
- notionary/page/content/service.py +68 -0
- notionary/page/content/syntax/__init__.py +4 -0
- notionary/page/content/syntax/grammar.py +10 -0
- notionary/page/content/syntax/models.py +66 -0
- notionary/page/content/syntax/registry.py +393 -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 +308 -0
- notionary/page/properties/service.py +261 -0
- notionary/page/schemas.py +13 -0
- notionary/page/service.py +225 -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/shared/typings.py +3 -0
- notionary/user/__init__.py +4 -8
- notionary/user/base.py +138 -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/date.py +51 -0
- notionary/utils/decorators.py +122 -0
- notionary/utils/fuzzy.py +68 -0
- notionary/utils/mixins/logging.py +58 -0
- notionary/utils/pagination.py +100 -0
- notionary/utils/uuid_utils.py +20 -0
- notionary/workspace/__init__.py +4 -0
- notionary/workspace/client.py +62 -0
- notionary/workspace/query/__init__.py +3 -0
- notionary/workspace/query/builder.py +60 -0
- notionary/workspace/query/models.py +61 -0
- notionary/workspace/query/service.py +100 -0
- notionary/workspace/schemas.py +21 -0
- notionary/workspace/service.py +116 -0
- notionary-0.3.0.dist-info/METADATA +201 -0
- notionary-0.3.0.dist-info/RECORD +209 -0
- {notionary-0.2.27.dist-info → notionary-0.3.0.dist-info}/WHEEL +1 -1
- {notionary-0.2.27.dist-info → notionary-0.3.0.dist-info/licenses}/LICENSE +9 -9
- notionary/base_notion_client.py +0 -219
- 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/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/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 -712
- 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/logging_mixin.py +0 -59
- 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.27.dist-info/METADATA +0 -270
- notionary-0.2.27.dist-info/RECORD +0 -202
- /notionary/{database → user}/factory.py +0 -0
notionary/util/fuzzy.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import difflib
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from typing import Any, Callable, List, Optional, TypeVar
|
|
6
|
-
|
|
7
|
-
T = TypeVar("T")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class MatchResult:
|
|
12
|
-
"""Result of a fuzzy match operation."""
|
|
13
|
-
|
|
14
|
-
item: Any
|
|
15
|
-
similarity: float
|
|
16
|
-
matched_text: str
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def calculate_similarity(query: str, target: str) -> float:
|
|
20
|
-
"""Calculate similarity between two strings using difflib."""
|
|
21
|
-
return difflib.SequenceMatcher(
|
|
22
|
-
None, query.lower().strip(), target.lower().strip()
|
|
23
|
-
).ratio()
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def find_best_matches(
|
|
27
|
-
query: str,
|
|
28
|
-
items: List[T],
|
|
29
|
-
text_extractor: Callable[[T], str],
|
|
30
|
-
min_similarity: float = 0.0,
|
|
31
|
-
limit: Optional[int] = None,
|
|
32
|
-
) -> List[MatchResult[T]]:
|
|
33
|
-
"""
|
|
34
|
-
Find best fuzzy matches from a list of items.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
query: The search query
|
|
38
|
-
items: List of items to search through
|
|
39
|
-
text_extractor: Function to extract text from each item
|
|
40
|
-
min_similarity: Minimum similarity threshold (0.0 to 1.0)
|
|
41
|
-
limit: Maximum number of results to return
|
|
42
|
-
|
|
43
|
-
Returns:
|
|
44
|
-
List of MatchResult objects sorted by similarity (highest first)
|
|
45
|
-
"""
|
|
46
|
-
results = []
|
|
47
|
-
|
|
48
|
-
for item in items:
|
|
49
|
-
text = text_extractor(item)
|
|
50
|
-
similarity = calculate_similarity(query, text)
|
|
51
|
-
|
|
52
|
-
if similarity >= min_similarity:
|
|
53
|
-
results.append(
|
|
54
|
-
MatchResult(item=item, similarity=similarity, matched_text=text)
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
# Sort by similarity (highest first)
|
|
58
|
-
results.sort(key=lambda x: x.similarity, reverse=True)
|
|
59
|
-
|
|
60
|
-
# Apply limit if specified
|
|
61
|
-
if limit:
|
|
62
|
-
results = results[:limit]
|
|
63
|
-
|
|
64
|
-
return results
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def find_best_match(
|
|
68
|
-
query: str,
|
|
69
|
-
items: List[T],
|
|
70
|
-
text_extractor: Callable[[T], str],
|
|
71
|
-
min_similarity: float = 0.0,
|
|
72
|
-
) -> Optional[MatchResult[T]]:
|
|
73
|
-
"""Find the single best fuzzy match."""
|
|
74
|
-
matches = find_best_matches(query, items, text_extractor, min_similarity, limit=1)
|
|
75
|
-
return matches[0] if matches else None
|
notionary/util/logging_mixin.py
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
from typing import ClassVar, Optional
|
|
4
|
-
|
|
5
|
-
from dotenv import load_dotenv
|
|
6
|
-
|
|
7
|
-
load_dotenv()
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def setup_logging():
|
|
11
|
-
"""
|
|
12
|
-
Sets up logging configuration for the application.
|
|
13
|
-
"""
|
|
14
|
-
log_level = os.getenv("LOG_LEVEL", "WARNING").upper()
|
|
15
|
-
logging.basicConfig(
|
|
16
|
-
level=getattr(logging, log_level),
|
|
17
|
-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
setup_logging()
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class LoggingMixin:
|
|
27
|
-
# Class attribute with proper typing
|
|
28
|
-
logger: ClassVar[logging.Logger] = None
|
|
29
|
-
|
|
30
|
-
def __init_subclass__(cls, **kwargs):
|
|
31
|
-
"""
|
|
32
|
-
This method is called when a class inherits from LoggingMixin.
|
|
33
|
-
It automatically sets up the logger as a class attribute.
|
|
34
|
-
"""
|
|
35
|
-
super().__init_subclass__(**kwargs)
|
|
36
|
-
cls.logger = logging.getLogger(cls.__name__)
|
|
37
|
-
|
|
38
|
-
@property
|
|
39
|
-
def instance_logger(self) -> logging.Logger:
|
|
40
|
-
"""Instance logger - for instance methods"""
|
|
41
|
-
if not hasattr(self, "_logger"):
|
|
42
|
-
self._logger = logging.getLogger(self.__class__.__name__)
|
|
43
|
-
return self._logger
|
|
44
|
-
|
|
45
|
-
@staticmethod
|
|
46
|
-
def _get_class_name_from_frame(frame) -> Optional[str]:
|
|
47
|
-
local_vars = frame.f_locals
|
|
48
|
-
if "self" in local_vars:
|
|
49
|
-
return local_vars["self"].__class__.__name__
|
|
50
|
-
|
|
51
|
-
if "cls" in local_vars:
|
|
52
|
-
return local_vars["cls"].__name__
|
|
53
|
-
|
|
54
|
-
if "__qualname__" in frame.f_code.co_names:
|
|
55
|
-
qualname = frame.f_code.co_qualname
|
|
56
|
-
if "." in qualname:
|
|
57
|
-
return qualname.split(".")[0]
|
|
58
|
-
|
|
59
|
-
return None
|
notionary/util/page_id_utils.py
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
UUID_PATTERN = r"^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$"
|
|
5
|
-
UUID_RAW_PATTERN = r"([a-f0-9]{32})"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def extract_uuid(source: str) -> Optional[str]:
|
|
9
|
-
if is_valid_uuid(source):
|
|
10
|
-
return source
|
|
11
|
-
|
|
12
|
-
match = re.search(UUID_RAW_PATTERN, source.lower())
|
|
13
|
-
if not match:
|
|
14
|
-
return None
|
|
15
|
-
|
|
16
|
-
uuid_raw = match.group(1)
|
|
17
|
-
return f"{uuid_raw[0:8]}-{uuid_raw[8:12]}-{uuid_raw[12:16]}-{uuid_raw[16:20]}-{uuid_raw[20:32]}"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def is_valid_uuid(uuid: str) -> bool:
|
|
21
|
-
return bool(re.match(UUID_PATTERN, uuid.lower()))
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def format_uuid(value: str) -> Optional[str]:
|
|
25
|
-
if is_valid_uuid(value):
|
|
26
|
-
return value
|
|
27
|
-
return extract_uuid(value)
|
notionary/util/singleton.py
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
def singleton(cls):
|
|
2
|
-
"""
|
|
3
|
-
Simple singleton decorator that ensures only one instance of a class exists.
|
|
4
|
-
|
|
5
|
-
Usage:
|
|
6
|
-
@singleton
|
|
7
|
-
class MyClass:
|
|
8
|
-
pass
|
|
9
|
-
"""
|
|
10
|
-
instances = {}
|
|
11
|
-
|
|
12
|
-
def __new__(cls, *args, **kwargs):
|
|
13
|
-
if cls not in instances:
|
|
14
|
-
instances[cls] = super(cls, cls).__new__(cls)
|
|
15
|
-
return instances[cls]
|
|
16
|
-
|
|
17
|
-
cls.__new__ = __new__
|
|
18
|
-
return cls
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from typing import Any, Dict, Type, TypeVar, cast
|
|
2
|
-
|
|
3
|
-
T = TypeVar("T")
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class SingletonMetaClass(type):
|
|
7
|
-
"""
|
|
8
|
-
A metaclass that ensures a class has only a single instance.
|
|
9
|
-
Provides a get_instance() method with proper type hinting.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
_instances: Dict[Type, Any] = {}
|
|
13
|
-
|
|
14
|
-
def __call__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
|
15
|
-
"""Called when the class is instantiated (e.g., MyClass())."""
|
|
16
|
-
if cls not in cls._instances:
|
|
17
|
-
cls._instances[cls] = super().__call__(*args, **kwargs)
|
|
18
|
-
return cast(T, cls._instances[cls])
|
|
19
|
-
|
|
20
|
-
def get_instance(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
|
21
|
-
"""Explicit method to retrieve the singleton instance with correct return type."""
|
|
22
|
-
return cls(*args, **kwargs) # Triggers __call__
|
notionary/workspace.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from notionary import NotionDatabase, NotionPage
|
|
5
|
-
from notionary.database.client import NotionDatabaseClient
|
|
6
|
-
from notionary.page.client import NotionPageClient
|
|
7
|
-
from notionary.user import NotionUser, NotionUserManager
|
|
8
|
-
from notionary.util import LoggingMixin
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class NotionWorkspace(LoggingMixin):
|
|
12
|
-
"""
|
|
13
|
-
Represents a Notion workspace, providing methods to interact with databases, pages, and limited user operations.
|
|
14
|
-
|
|
15
|
-
Note: Due to Notion API limitations, bulk user operations (listing all users) are not supported.
|
|
16
|
-
Only individual user queries and bot user information are available.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, token: Optional[str] = None):
|
|
20
|
-
"""
|
|
21
|
-
Initialize the workspace with Notion clients.
|
|
22
|
-
"""
|
|
23
|
-
self.database_client = NotionDatabaseClient(token=token)
|
|
24
|
-
self.page_client = NotionPageClient(token=token)
|
|
25
|
-
self.user_manager = NotionUserManager(token=token)
|
|
26
|
-
|
|
27
|
-
async def search_pages(self, query: str, limit=100) -> list[NotionPage]:
|
|
28
|
-
"""
|
|
29
|
-
Search for pages globally across Notion workspace.
|
|
30
|
-
"""
|
|
31
|
-
response = await self.page_client.search_pages(query, limit=limit)
|
|
32
|
-
return await asyncio.gather(
|
|
33
|
-
*(NotionPage.from_page_id(page.id) for page in response.results)
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
async def search_databases(
|
|
37
|
-
self, query: str, limit: int = 100
|
|
38
|
-
) -> list[NotionDatabase]:
|
|
39
|
-
"""
|
|
40
|
-
Search for databases globally across the Notion workspace.
|
|
41
|
-
"""
|
|
42
|
-
response = await self.database_client.search_databases(query=query, limit=limit)
|
|
43
|
-
return await asyncio.gather(
|
|
44
|
-
*(
|
|
45
|
-
NotionDatabase.from_database_id(database.id)
|
|
46
|
-
for database in response.results
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
async def get_database_by_name(
|
|
51
|
-
self, database_name: str
|
|
52
|
-
) -> Optional[NotionDatabase]:
|
|
53
|
-
"""
|
|
54
|
-
Get a Notion database by its name.
|
|
55
|
-
Uses Notion's search API and returns the first matching database.
|
|
56
|
-
"""
|
|
57
|
-
databases = await self.search_databases(query=database_name, limit=1)
|
|
58
|
-
|
|
59
|
-
return databases[0] if databases else None
|
|
60
|
-
|
|
61
|
-
async def list_all_databases(self, limit: int = 100) -> list[NotionDatabase]:
|
|
62
|
-
"""
|
|
63
|
-
List all databases in the workspace.
|
|
64
|
-
Returns a list of NotionDatabase instances.
|
|
65
|
-
"""
|
|
66
|
-
database_results = await self.database_client.search_databases(
|
|
67
|
-
query="", limit=limit
|
|
68
|
-
)
|
|
69
|
-
return [
|
|
70
|
-
await NotionDatabase.from_database_id(database.id)
|
|
71
|
-
for database in database_results.results
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
# User-related methods (limited due to API constraints)
|
|
75
|
-
async def get_current_bot_user(self) -> Optional[NotionUser]:
|
|
76
|
-
"""
|
|
77
|
-
Get the current bot user from the API token.
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
Optional[NotionUser]: Current bot user or None if failed
|
|
81
|
-
"""
|
|
82
|
-
return await self.user_manager.get_current_bot_user()
|
|
83
|
-
|
|
84
|
-
async def get_user_by_id(self, user_id: str) -> Optional[NotionUser]:
|
|
85
|
-
"""
|
|
86
|
-
Get a specific user by their ID.
|
|
87
|
-
|
|
88
|
-
Args:
|
|
89
|
-
user_id: The ID of the user to retrieve
|
|
90
|
-
|
|
91
|
-
Returns:
|
|
92
|
-
Optional[NotionUser]: The user or None if not found/failed
|
|
93
|
-
"""
|
|
94
|
-
return await self.user_manager.get_user_by_id(user_id)
|
|
95
|
-
|
|
96
|
-
async def get_workspace_info(self) -> Optional[dict]:
|
|
97
|
-
"""
|
|
98
|
-
Get available workspace information including bot details.
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
Optional[dict]: Workspace information or None if failed to get bot user
|
|
102
|
-
"""
|
|
103
|
-
return await self.user_manager.get_workspace_info()
|
|
104
|
-
|
|
105
|
-
# TODO: Create database would be nice here
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: notionary
|
|
3
|
-
Version: 0.2.27
|
|
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
|
-
Project-URL: Homepage, https://github.com/mathisarends/notionary
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
|
24
|
-
<picture>
|
|
25
|
-
<source media="(prefers-color-scheme: dark)" srcset="./static/notionary-dark.png">
|
|
26
|
-
<source media="(prefers-color-scheme: light)" srcset="./static/notionary-light.png">
|
|
27
|
-
<img alt="Notionary logo: dark mode shows a white logo, light mode shows a black logo." src="./static/browser-use.png" width="full">
|
|
28
|
-
</picture>
|
|
29
|
-
|
|
30
|
-
<h1 align="center">The Modern Notion API for Python & AI Agents</h1>
|
|
31
|
-
|
|
32
|
-
<div align="center">
|
|
33
|
-
|
|
34
|
-
[](https://www.python.org/downloads/)
|
|
35
|
-
[](LICENSE)
|
|
36
|
-
[](https://mathisarends.github.io/notionary/)
|
|
37
|
-
|
|
38
|
-
**Transform complex Notion API interactions into simple, Pythonic code.**
|
|
39
|
-
Perfect for developers building AI agents, automation workflows, and dynamic content systems.
|
|
40
|
-
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Why Notionary?
|
|
46
|
-
|
|
47
|
-
- **AI-Native Design** - Built specifically for AI agents with schema-driven markdown syntax
|
|
48
|
-
- **Smart Discovery** - Find pages and databases by name with fuzzy matching—no more hunting for IDs
|
|
49
|
-
- **Extended Markdown** - Rich syntax for toggles, columns, callouts, and media uploads
|
|
50
|
-
- **Async-First** - Modern Python with full async/await support and high performance
|
|
51
|
-
- **Round-Trip** - Read existing content, modify it, and write it back while preserving formatting
|
|
52
|
-
- **Complete Coverage** - Every Notion block type supported with type safety
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## Installation
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
pip install notionary
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Set up your [Notion integration](https://www.notion.so/profile/integrations) and configure your token:
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
export NOTION_SECRET=your_integration_key
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## See It in Action
|
|
71
|
-
|
|
72
|
-
### Creating Rich Database Entries
|
|
73
|
-
|
|
74
|
-
https://github.com/user-attachments/assets/da8b4691-bee4-4b0f-801e-dccacb630398
|
|
75
|
-
|
|
76
|
-
*Create styled project pages with properties, content, and rich formatting*
|
|
77
|
-
|
|
78
|
-
### Local File Uploads (Videos & Images)
|
|
79
|
-
|
|
80
|
-
https://github.com/user-attachments/assets/a079ec01-bb56-4c65-8260-7b1fca42ac68
|
|
81
|
-
|
|
82
|
-
*Upload videos and images using simple markdown syntax - files are automatically uploaded to Notion*
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Quick Start
|
|
87
|
-
|
|
88
|
-
### Find → Create → Update Flow
|
|
89
|
-
|
|
90
|
-
```python
|
|
91
|
-
import asyncio
|
|
92
|
-
from notionary import NotionPage, NotionDatabase
|
|
93
|
-
|
|
94
|
-
async def main():
|
|
95
|
-
# Find pages by name - fuzzy matching included!
|
|
96
|
-
page = await NotionPage.from_page_name("Meeting Notes")
|
|
97
|
-
|
|
98
|
-
# Option 1: Direct Extended Markdown
|
|
99
|
-
await page.append_markdown("""
|
|
100
|
-
## Action Items
|
|
101
|
-
- [x] Review project proposal
|
|
102
|
-
- [ ] Schedule team meeting
|
|
103
|
-
- [ ] Update documentation
|
|
104
|
-
|
|
105
|
-
[callout](Meeting decisions require follow-up "💡")
|
|
106
|
-
|
|
107
|
-
+++ Details
|
|
108
|
-
Additional context and next steps...
|
|
109
|
-
+++
|
|
110
|
-
""")
|
|
111
|
-
|
|
112
|
-
# Option 2: Type-Safe Builder (maps to same markdown internally)
|
|
113
|
-
await page.append_markdown(lambda builder: (
|
|
114
|
-
builder
|
|
115
|
-
.h2("Project Status")
|
|
116
|
-
.callout("Milestone reached!", "🎉")
|
|
117
|
-
.columns(
|
|
118
|
-
lambda col: col.h3("Completed").bulleted_list([
|
|
119
|
-
"API design", "Database setup", "Authentication"
|
|
120
|
-
]),
|
|
121
|
-
lambda col: col.h3("In Progress").bulleted_list([
|
|
122
|
-
"Frontend UI", "Testing", "Documentation"
|
|
123
|
-
]),
|
|
124
|
-
width_ratios=[0.6, 0.4]
|
|
125
|
-
)
|
|
126
|
-
.toggle("Budget Details", lambda t: t
|
|
127
|
-
.table(["Item", "Cost", "Status"], [
|
|
128
|
-
["Development", "$15,000", "Paid"],
|
|
129
|
-
["Design", "$8,000", "Pending"]
|
|
130
|
-
])
|
|
131
|
-
)
|
|
132
|
-
))
|
|
133
|
-
|
|
134
|
-
asyncio.run(main())
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Complete Block Support
|
|
138
|
-
|
|
139
|
-
Every Notion block type with extended syntax:
|
|
140
|
-
|
|
141
|
-
| Block Type | Markdown Syntax | Use Case |
|
|
142
|
-
|------------|-----------------|----------|
|
|
143
|
-
| **Callouts** | `[callout](Text "🔥")` | Highlighting key information |
|
|
144
|
-
| **Toggles** | `+++ Title\nContent\n+++` | Collapsible sections |
|
|
145
|
-
| **Columns** | `::: columns\n::: column\nContent\n:::\n:::` | Side-by-side layouts |
|
|
146
|
-
| **Tables** | Standard markdown tables | Structured data |
|
|
147
|
-
| **Media** | `[video](./file.mp4)(caption:Description)` | Auto-uploading files |
|
|
148
|
-
| **Code** | Standard code fences with captions | Code snippets |
|
|
149
|
-
| **Equations** | `$LaTeX$` | Mathematical expressions |
|
|
150
|
-
| **TOC** | `[toc](blue_background)` | Auto-generated navigation |
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## What You Can Build 💡
|
|
155
|
-
|
|
156
|
-
### **AI Content Systems**
|
|
157
|
-
- **Report Generation**: AI agents that create structured reports, documentation, and analysis
|
|
158
|
-
- **Content Pipelines**: Automated workflows that process data and generate Notion pages
|
|
159
|
-
- **Knowledge Management**: AI-powered documentation systems with smart categorization
|
|
160
|
-
|
|
161
|
-
### **Workflow Automation**
|
|
162
|
-
- **Project Management**: Sync project status, update timelines, generate progress reports
|
|
163
|
-
- **Data Integration**: Connect external APIs and databases to Notion workspaces
|
|
164
|
-
- **Template Systems**: Dynamic page generation from templates and data sources
|
|
165
|
-
|
|
166
|
-
### **Content Management**
|
|
167
|
-
- **Bulk Operations**: Mass page updates, content migration, and database management
|
|
168
|
-
- **Media Handling**: Automated image/video uploads with proper organization
|
|
169
|
-
- **Cross-Platform**: Sync content between Notion and other platforms
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## Key Features
|
|
174
|
-
|
|
175
|
-
<table>
|
|
176
|
-
<tr>
|
|
177
|
-
<td width="50%">
|
|
178
|
-
|
|
179
|
-
### Smart Discovery
|
|
180
|
-
- Find pages/databases by name
|
|
181
|
-
- Fuzzy matching for approximate searches
|
|
182
|
-
- No more hunting for IDs or URLs
|
|
183
|
-
|
|
184
|
-
### Extended Markdown
|
|
185
|
-
- Rich syntax beyond standard markdown
|
|
186
|
-
- Callouts, toggles, columns, media uploads
|
|
187
|
-
- Schema provided for AI agent integration
|
|
188
|
-
|
|
189
|
-
### Modern Python
|
|
190
|
-
- Full async/await support
|
|
191
|
-
- Type hints throughout
|
|
192
|
-
- High-performance batch operations
|
|
193
|
-
|
|
194
|
-
</td>
|
|
195
|
-
<td width="50%">
|
|
196
|
-
|
|
197
|
-
### Round-Trip Editing
|
|
198
|
-
- Read existing content as markdown
|
|
199
|
-
- Edit and modify preserving formatting
|
|
200
|
-
- Write back to Notion seamlessly
|
|
201
|
-
|
|
202
|
-
### AI-Ready Architecture
|
|
203
|
-
- Schema-driven syntax for LLM prompts
|
|
204
|
-
- Perfect for AI content generation
|
|
205
|
-
- Handles complex nested structures
|
|
206
|
-
|
|
207
|
-
### Complete Coverage
|
|
208
|
-
- Every Notion block type supported
|
|
209
|
-
- File uploads with automatic handling
|
|
210
|
-
- Database operations and properties
|
|
211
|
-
|
|
212
|
-
</td>
|
|
213
|
-
</tr>
|
|
214
|
-
</table>
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Examples & Documentation
|
|
219
|
-
|
|
220
|
-
### Full Documentation
|
|
221
|
-
[**mathisarends.github.io/notionary**](https://mathisarends.github.io/notionary/) - Complete API reference, guides, and tutorials
|
|
222
|
-
|
|
223
|
-
### Quick Links
|
|
224
|
-
- [**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
|
|
226
|
-
- [**Database Operations**](https://mathisarends.github.io/notionary/database/) - Queries and management
|
|
227
|
-
- [**Block Types Reference**](https://mathisarends.github.io/notionary/blocks/) - Complete syntax guide
|
|
228
|
-
|
|
229
|
-
### Hands-On Examples
|
|
230
|
-
|
|
231
|
-
**Core Functionality:**
|
|
232
|
-
- [Page Management](examples/page_example.py) - Create, update, and manage pages
|
|
233
|
-
- [Database Operations](examples/database.py) - Connect and query databases
|
|
234
|
-
- [Workspace Discovery](examples/workspace_discovery.py) - Explore your workspace
|
|
235
|
-
|
|
236
|
-
**Extended Markdown:**
|
|
237
|
-
- [Basic Formatting](examples/markdown/basic.py) - Text, lists, and links
|
|
238
|
-
- [Callouts & Highlights](examples/markdown/callout.py) - Information boxes
|
|
239
|
-
- [Toggle Sections](examples/markdown/toggle.py) - Collapsible content
|
|
240
|
-
- [Multi-Column Layouts](examples/markdown/columns.py) - Side-by-side design
|
|
241
|
-
- [Tables & Data](examples/markdown/table.py) - Structured presentations
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## Contributing
|
|
246
|
-
|
|
247
|
-
We welcome contributions from the community! Whether you're:
|
|
248
|
-
- **Fixing bugs** - Help improve stability and reliability
|
|
249
|
-
- **Adding features** - Extend functionality for new use cases
|
|
250
|
-
- **Improving docs** - Make the library more accessible
|
|
251
|
-
- **Sharing examples** - Show creative applications and patterns
|
|
252
|
-
|
|
253
|
-
Check our [**Contributing Guide**](https://mathisarends.github.io/notionary/contributing/) to get started.
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
<div align="center">
|
|
258
|
-
|
|
259
|
-
**Ready to revolutionize your Notion workflows?**
|
|
260
|
-
|
|
261
|
-
[📖 **Read the Docs**](https://mathisarends.github.io/notionary/) • [🚀 **Getting Started**](https://mathisarends.github.io/notionary/get-started/) • [💻 **Browse Examples**](examples/)
|
|
262
|
-
|
|
263
|
-
*Built with ❤️ for Python developers and AI agents*
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
**Transform complex Notion API interactions into simple, powerful code.**
|
|
268
|
-
|
|
269
|
-
</div>
|
|
270
|
-
|