notionary 0.4.0__tar.gz → 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {notionary-0.4.0 → notionary-0.4.2}/PKG-INFO +1 -1
- notionary-0.4.2/notionary/__init__.py +62 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/client.py +37 -11
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/markdown_rich_text_converter.py +49 -15
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/models.py +13 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/data_source.py +9 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/person.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/rich_text_markdown_converter.py +10 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/schemas.py +2 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/client.py +19 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/factory.py +10 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/schemas.py +9 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/service.py +12 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/http/data_source_instance_client.py +59 -17
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/properties/schemas.py +30 -10
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/query/builder.py +67 -18
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/query/resolver.py +16 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/query/schema.py +24 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/query/validator.py +18 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/schema/registry.py +31 -12
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/schema/service.py +66 -20
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/service.py +74 -23
- {notionary-0.4.0 → notionary-0.4.2}/notionary/database/client.py +27 -9
- {notionary-0.4.0 → notionary-0.4.2}/notionary/database/database_metadata_update_client.py +12 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/database/service.py +11 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/__init__.py +15 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/block_parsing.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/data_source/builder.py +11 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/data_source/properties.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/file_upload.py +12 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/properties.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/search.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/client.py +5 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/config/config.py +10 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/query/builder.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/schemas.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/service.py +42 -14
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/factory.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/impl/file_name_length.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/models.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/validators/file_extension.py +12 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/http/client.py +27 -8
- notionary-0.4.2/notionary/page/content/__init__.py +9 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/factory.py +21 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/builder.py +85 -23
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/audio.py +8 -4
- notionary-0.4.2/notionary/page/content/markdown/nodes/base.py +12 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/bookmark.py +5 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/breadcrumb.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/bulleted_list.py +5 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/callout.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/code.py +5 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/columns.py +3 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/container.py +9 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/divider.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/embed.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/equation.py +4 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/file.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/heading.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/image.py +8 -4
- notionary-0.4.2/notionary/page/content/markdown/nodes/mixins/caption.py +14 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/numbered_list.py +5 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/paragraph.py +4 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/pdf.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/quote.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/space.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/table.py +8 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/table_of_contents.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/todo.py +15 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/toggle.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/video.py +8 -4
- notionary-0.4.2/notionary/page/content/markdown/structured_output/__init__.py +73 -0
- notionary-0.4.2/notionary/page/content/markdown/structured_output/models.py +391 -0
- notionary-0.4.2/notionary/page/content/markdown/structured_output/service.py +211 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/context.py +1 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/factory.py +23 -8
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/audio.py +7 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/base.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/bookmark.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/breadcrumb.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/bulleted_list.py +19 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/callout.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/caption.py +9 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/code.py +21 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/column.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/column_list.py +19 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/divider.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/embed.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/equation.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/file.py +7 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/file_like_block.py +30 -10
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/heading.py +31 -10
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/image.py +7 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/numbered_list.py +18 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/paragraph.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/pdf.py +7 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/quote.py +28 -9
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/space.py +2 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/table.py +31 -10
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/table_of_contents.py +7 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/todo.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/toggle.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/video.py +7 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/post_processing/handlers/rich_text_length.py +8 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +8 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/post_processing/service.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +21 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/indentation.py +11 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/video_syntax.py +13 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/service.py +4 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/context.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/factory.py +12 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/post_processing/handlers/numbered_list.py +19 -9
- notionary-0.4.2/notionary/page/content/renderer/renderers/audio.py +28 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/base.py +3 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/bookmark.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/bulleted_list.py +11 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/callout.py +19 -7
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/captioned_block.py +11 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/code.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/column.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/column_list.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/embed.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/equation.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/file.py +14 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/file_like_block.py +8 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/heading.py +22 -8
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/image.py +13 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/numbered_list.py +8 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/paragraph.py +12 -4
- notionary-0.4.2/notionary/page/content/renderer/renderers/pdf.py +28 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/quote.py +14 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/table.py +15 -5
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/todo.py +16 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/toggle.py +8 -4
- notionary-0.4.2/notionary/page/content/renderer/renderers/video.py +28 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/service.py +9 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/service.py +21 -7
- notionary-0.4.2/notionary/page/content/syntax/definition/__init__.py +11 -0
- notionary-0.4.2/notionary/page/content/syntax/definition/models.py +57 -0
- notionary-0.4.2/notionary/page/content/syntax/definition/registry.py +371 -0
- notionary-0.4.2/notionary/page/content/syntax/prompts/__init__.py +4 -0
- notionary-0.4.2/notionary/page/content/syntax/prompts/models.py +11 -0
- notionary-0.4.2/notionary/page/content/syntax/prompts/registry.py +703 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/page_metadata_update_client.py +12 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/properties/client.py +45 -15
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/properties/factory.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/properties/service.py +110 -36
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/service.py +20 -6
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/entity/client.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/entity/dto_parsers.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/entity/entity_metadata_update_client.py +9 -3
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/entity/schemas.py +1 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/entity/service.py +53 -22
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/models/file.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/models/icon.py +6 -4
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/base.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/bot.py +10 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/client.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/person.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/schemas.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/service.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/decorators.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/fuzzy.py +6 -2
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/mixins/logging.py +3 -1
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/pagination.py +14 -4
- notionary-0.4.2/notionary/workspace/__init__.py +8 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/query/service.py +59 -16
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/service.py +39 -11
- {notionary-0.4.0 → notionary-0.4.2}/pyproject.toml +76 -72
- notionary-0.4.0/notionary/__init__.py +0 -19
- notionary-0.4.0/notionary/page/blocks/client.py +0 -1
- notionary-0.4.0/notionary/page/content/markdown/nodes/base.py +0 -12
- notionary-0.4.0/notionary/page/content/markdown/nodes/mixins/caption.py +0 -12
- notionary-0.4.0/notionary/page/content/renderer/renderers/audio.py +0 -19
- notionary-0.4.0/notionary/page/content/renderer/renderers/pdf.py +0 -19
- notionary-0.4.0/notionary/page/content/renderer/renderers/video.py +0 -19
- notionary-0.4.0/notionary/page/content/syntax/__init__.py +0 -5
- notionary-0.4.0/notionary/page/content/syntax/models.py +0 -66
- notionary-0.4.0/notionary/page/content/syntax/registry.py +0 -371
- notionary-0.4.0/notionary/workspace/__init__.py +0 -4
- {notionary-0.4.0 → notionary-0.4.2}/.gitignore +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/LICENSE +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/README.md +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/enums.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/database.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/page.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/port.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/rich_text_patterns.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/comments/models.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/http/client.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/query/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/data_source/schemas.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/database/schemas.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/api.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/base.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/exceptions/data_source/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/config/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/config/constants.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/file/reader.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/query/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/query/models.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/port.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/service.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/validators/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/validators/file_exists.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/validators/file_name_length.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/file_upload/validation/validators/upload_limit.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/http/models.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/markdown/nodes/mixins/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/parsers/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/post_processing/handlers/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/post_processing/port.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/port.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/handlers/whitespace.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/parser/pre_processsing/service.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/post_processing/handlers/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/post_processing/port.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/post_processing/service.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/breadcrumb.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/divider.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/fallback.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/table_of_contents.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/content/renderer/renderers/table_row.py +0 -0
- {notionary-0.4.0/notionary/page/content/syntax → notionary-0.4.2/notionary/page/content/syntax/definition}/grammar.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/page_http_client.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/properties/schemas.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/page/schemas.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/models/parent.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/properties/type.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/shared/typings.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/user/factory.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/date.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/utils/uuid_utils.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/client.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/query/__init__.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/query/builder.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/query/models.py +0 -0
- {notionary-0.4.0 → notionary-0.4.2}/notionary/workspace/schemas.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: notionary
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
|
|
5
5
|
Project-URL: Homepage, https://github.com/mathisarends/notionary
|
|
6
6
|
Author-email: Mathis Arends <mathisarends27@gmail.com>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from .data_source.service import NotionDataSource
|
|
2
|
+
from .database.service import NotionDatabase
|
|
3
|
+
from .file_upload import FileUploadQuery, FileUploadQueryBuilder, NotionFileUpload
|
|
4
|
+
from .page.content import SyntaxPromptRegistry
|
|
5
|
+
from .page.content.markdown.builder import MarkdownBuilder
|
|
6
|
+
from .page.content.markdown.structured_output import (
|
|
7
|
+
MarkdownDocumentSchema,
|
|
8
|
+
StructuredOutputMarkdownConverter,
|
|
9
|
+
)
|
|
10
|
+
from .page.service import NotionPage
|
|
11
|
+
from .workspace import (
|
|
12
|
+
NotionWorkspace,
|
|
13
|
+
NotionWorkspaceQueryConfigBuilder,
|
|
14
|
+
WorkspaceQueryConfig,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"AudioSchema",
|
|
19
|
+
"BookmarkSchema",
|
|
20
|
+
"BreadcrumbSchema",
|
|
21
|
+
"BulletedListItemSchema",
|
|
22
|
+
"BulletedListSchema",
|
|
23
|
+
"CalloutSchema",
|
|
24
|
+
"CodeSchema",
|
|
25
|
+
"ColumnSchema",
|
|
26
|
+
"ColumnsSchema",
|
|
27
|
+
"DividerSchema",
|
|
28
|
+
"EmbedSchema",
|
|
29
|
+
"EquationSchema",
|
|
30
|
+
"FileSchema",
|
|
31
|
+
"FileUploadQuery",
|
|
32
|
+
"FileUploadQueryBuilder",
|
|
33
|
+
"Heading1Schema",
|
|
34
|
+
"Heading2Schema",
|
|
35
|
+
"Heading3Schema",
|
|
36
|
+
"ImageSchema",
|
|
37
|
+
"MarkdownBuilder",
|
|
38
|
+
"MarkdownDocumentSchema",
|
|
39
|
+
"MarkdownNodeSchema",
|
|
40
|
+
"MermaidSchema",
|
|
41
|
+
"NotionDataSource",
|
|
42
|
+
"NotionDatabase",
|
|
43
|
+
"NotionFileUpload",
|
|
44
|
+
"NotionPage",
|
|
45
|
+
"NotionWorkspace",
|
|
46
|
+
"NotionWorkspaceQueryConfigBuilder",
|
|
47
|
+
"NumberedListItemSchema",
|
|
48
|
+
"NumberedListSchema",
|
|
49
|
+
"ParagraphSchema",
|
|
50
|
+
"PdfSchema",
|
|
51
|
+
"QuoteSchema",
|
|
52
|
+
"SpaceSchema",
|
|
53
|
+
"StructuredOutputMarkdownConverter",
|
|
54
|
+
"SyntaxPromptRegistry",
|
|
55
|
+
"TableOfContentsSchema",
|
|
56
|
+
"TableSchema",
|
|
57
|
+
"TodoListSchema",
|
|
58
|
+
"TodoSchema",
|
|
59
|
+
"ToggleSchema",
|
|
60
|
+
"VideoSchema",
|
|
61
|
+
"WorkspaceQueryConfig",
|
|
62
|
+
]
|
|
@@ -31,9 +31,13 @@ class NotionBlockHttpClient(NotionHttpClient):
|
|
|
31
31
|
async def get_all_block_children(self, parent_block_id: str) -> list[Block]:
|
|
32
32
|
self.logger.debug("Retrieving all children for block: %s", parent_block_id)
|
|
33
33
|
|
|
34
|
-
all_blocks = await paginate_notion_api(
|
|
34
|
+
all_blocks = await paginate_notion_api(
|
|
35
|
+
self.get_block_children, block_id=parent_block_id
|
|
36
|
+
)
|
|
35
37
|
|
|
36
|
-
self.logger.debug(
|
|
38
|
+
self.logger.debug(
|
|
39
|
+
"Retrieved %d total children for block %s", len(all_blocks), parent_block_id
|
|
40
|
+
)
|
|
37
41
|
return all_blocks
|
|
38
42
|
|
|
39
43
|
async def get_block_children(
|
|
@@ -64,11 +68,17 @@ class NotionBlockHttpClient(NotionHttpClient):
|
|
|
64
68
|
|
|
65
69
|
if len(batches) == 1:
|
|
66
70
|
children_dicts = self._serialize_blocks(batches[0])
|
|
67
|
-
return await self._send_append_request(
|
|
71
|
+
return await self._send_append_request(
|
|
72
|
+
block_id, children_dicts, insert_after_block_id
|
|
73
|
+
)
|
|
68
74
|
|
|
69
|
-
return await self._send_batched_append_requests(
|
|
75
|
+
return await self._send_batched_append_requests(
|
|
76
|
+
block_id, batches, insert_after_block_id
|
|
77
|
+
)
|
|
70
78
|
|
|
71
|
-
def _split_into_batches(
|
|
79
|
+
def _split_into_batches(
|
|
80
|
+
self, blocks: list[BlockCreatePayload]
|
|
81
|
+
) -> list[list[BlockCreatePayload]]:
|
|
72
82
|
batches = []
|
|
73
83
|
for i in range(0, len(blocks), self.BATCH_SIZE):
|
|
74
84
|
batch = blocks[i : i + self.BATCH_SIZE]
|
|
@@ -89,19 +99,31 @@ class NotionBlockHttpClient(NotionHttpClient):
|
|
|
89
99
|
return BlockChildrenResponse.model_validate(response)
|
|
90
100
|
|
|
91
101
|
async def _send_batched_append_requests(
|
|
92
|
-
self,
|
|
102
|
+
self,
|
|
103
|
+
block_id: str,
|
|
104
|
+
batches: list[list[BlockCreatePayload]],
|
|
105
|
+
initial_after_block_id: str | None = None,
|
|
93
106
|
) -> BlockChildrenResponse:
|
|
94
107
|
total_blocks = sum(len(batch) for batch in batches)
|
|
95
|
-
self.logger.info(
|
|
108
|
+
self.logger.info(
|
|
109
|
+
"Appending %d blocks in %d batches", total_blocks, len(batches)
|
|
110
|
+
)
|
|
96
111
|
|
|
97
112
|
all_responses = []
|
|
98
113
|
after_block_id = initial_after_block_id
|
|
99
114
|
|
|
100
115
|
for batch_index, batch in enumerate(batches, start=1):
|
|
101
|
-
self.logger.debug(
|
|
116
|
+
self.logger.debug(
|
|
117
|
+
"Processing batch %d/%d (%d blocks)",
|
|
118
|
+
batch_index,
|
|
119
|
+
len(batches),
|
|
120
|
+
len(batch),
|
|
121
|
+
)
|
|
102
122
|
|
|
103
123
|
children_dicts = self._serialize_blocks(batch)
|
|
104
|
-
response = await self._send_append_request(
|
|
124
|
+
response = await self._send_append_request(
|
|
125
|
+
block_id, children_dicts, after_block_id
|
|
126
|
+
)
|
|
105
127
|
all_responses.append(response)
|
|
106
128
|
|
|
107
129
|
if response.results:
|
|
@@ -112,9 +134,13 @@ class NotionBlockHttpClient(NotionHttpClient):
|
|
|
112
134
|
self.logger.info("Successfully appended all blocks in %d batches", len(batches))
|
|
113
135
|
return self._merge_responses(all_responses)
|
|
114
136
|
|
|
115
|
-
def _merge_responses(
|
|
137
|
+
def _merge_responses(
|
|
138
|
+
self, responses: list[BlockChildrenResponse]
|
|
139
|
+
) -> BlockChildrenResponse:
|
|
116
140
|
if not responses:
|
|
117
|
-
raise ValueError(
|
|
141
|
+
raise ValueError(
|
|
142
|
+
"Cannot merge empty response list - this should never happen"
|
|
143
|
+
)
|
|
118
144
|
|
|
119
145
|
first_response = responses[0]
|
|
120
146
|
all_results = [block for response in responses for block in response.results]
|
{notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/markdown_rich_text_converter.py
RENAMED
|
@@ -4,7 +4,12 @@ from dataclasses import dataclass
|
|
|
4
4
|
from re import Match
|
|
5
5
|
from typing import ClassVar
|
|
6
6
|
|
|
7
|
-
from notionary.blocks.rich_text.models import
|
|
7
|
+
from notionary.blocks.rich_text.models import (
|
|
8
|
+
MentionType,
|
|
9
|
+
RichText,
|
|
10
|
+
RichTextType,
|
|
11
|
+
TextAnnotations,
|
|
12
|
+
)
|
|
8
13
|
from notionary.blocks.rich_text.name_id_resolver import (
|
|
9
14
|
DatabaseNameIdResolver,
|
|
10
15
|
DataSourceNameIdResolver,
|
|
@@ -58,17 +63,32 @@ class MarkdownRichTextConverter:
|
|
|
58
63
|
return [
|
|
59
64
|
PatternHandler(RichTextPatterns.BOLD, self._handle_bold_pattern),
|
|
60
65
|
PatternHandler(RichTextPatterns.ITALIC, self._handle_italic_pattern),
|
|
61
|
-
PatternHandler(
|
|
66
|
+
PatternHandler(
|
|
67
|
+
RichTextPatterns.ITALIC_UNDERSCORE, self._handle_italic_pattern
|
|
68
|
+
),
|
|
62
69
|
PatternHandler(RichTextPatterns.UNDERLINE, self._handle_underline_pattern),
|
|
63
|
-
PatternHandler(
|
|
70
|
+
PatternHandler(
|
|
71
|
+
RichTextPatterns.STRIKETHROUGH, self._handle_strikethrough_pattern
|
|
72
|
+
),
|
|
64
73
|
PatternHandler(RichTextPatterns.CODE, self._handle_code_pattern),
|
|
65
74
|
PatternHandler(RichTextPatterns.LINK, self._handle_link_pattern),
|
|
66
|
-
PatternHandler(
|
|
75
|
+
PatternHandler(
|
|
76
|
+
RichTextPatterns.INLINE_EQUATION, self._handle_equation_pattern
|
|
77
|
+
),
|
|
67
78
|
PatternHandler(RichTextPatterns.COLOR, self._handle_color_pattern),
|
|
68
|
-
PatternHandler(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
PatternHandler(
|
|
79
|
+
PatternHandler(
|
|
80
|
+
RichTextPatterns.PAGE_MENTION, self._handle_page_mention_pattern
|
|
81
|
+
),
|
|
82
|
+
PatternHandler(
|
|
83
|
+
RichTextPatterns.DATABASE_MENTION, self._handle_database_mention_pattern
|
|
84
|
+
),
|
|
85
|
+
PatternHandler(
|
|
86
|
+
RichTextPatterns.DATASOURCE_MENTION,
|
|
87
|
+
self._handle_data_source_mention_pattern,
|
|
88
|
+
),
|
|
89
|
+
PatternHandler(
|
|
90
|
+
RichTextPatterns.USER_MENTION, self._handle_user_mention_pattern
|
|
91
|
+
),
|
|
72
92
|
]
|
|
73
93
|
|
|
74
94
|
async def to_rich_text(self, text: str) -> list[RichText]:
|
|
@@ -106,12 +126,16 @@ class MarkdownRichTextConverter:
|
|
|
106
126
|
for pattern_handler in self.format_handlers:
|
|
107
127
|
match = re.search(pattern_handler.pattern, text)
|
|
108
128
|
if match and match.start() < earliest_position:
|
|
109
|
-
earliest_match = PatternMatch(
|
|
129
|
+
earliest_match = PatternMatch(
|
|
130
|
+
match=match, handler=pattern_handler.handler, position=match.start()
|
|
131
|
+
)
|
|
110
132
|
earliest_position = match.start()
|
|
111
133
|
|
|
112
134
|
return earliest_match
|
|
113
135
|
|
|
114
|
-
async def _process_pattern_match(
|
|
136
|
+
async def _process_pattern_match(
|
|
137
|
+
self, pattern_match: PatternMatch
|
|
138
|
+
) -> RichText | list[RichText]:
|
|
115
139
|
handler_method = pattern_match.handler
|
|
116
140
|
|
|
117
141
|
if self._is_async_handler(handler_method):
|
|
@@ -169,9 +193,13 @@ class MarkdownRichTextConverter:
|
|
|
169
193
|
def _apply_color_to_link_segment(self, segment: RichText, color: str) -> RichText:
|
|
170
194
|
formatting = self._extract_formatting_attributes(segment.annotations)
|
|
171
195
|
|
|
172
|
-
return RichText.for_link(
|
|
196
|
+
return RichText.for_link(
|
|
197
|
+
segment.plain_text, segment.text.link.url, color=color, **formatting
|
|
198
|
+
)
|
|
173
199
|
|
|
174
|
-
def _apply_color_to_plain_text_segment(
|
|
200
|
+
def _apply_color_to_plain_text_segment(
|
|
201
|
+
self, segment: RichText, color: str
|
|
202
|
+
) -> RichText:
|
|
175
203
|
if segment.type != RichTextType.TEXT:
|
|
176
204
|
return segment
|
|
177
205
|
|
|
@@ -179,7 +207,9 @@ class MarkdownRichTextConverter:
|
|
|
179
207
|
|
|
180
208
|
return RichText.from_plain_text(segment.plain_text, color=color, **formatting)
|
|
181
209
|
|
|
182
|
-
def _extract_formatting_attributes(
|
|
210
|
+
def _extract_formatting_attributes(
|
|
211
|
+
self, annotations: TextAnnotations
|
|
212
|
+
) -> dict[str, bool]:
|
|
183
213
|
if not annotations:
|
|
184
214
|
return {
|
|
185
215
|
"bold": False,
|
|
@@ -246,13 +276,17 @@ class MarkdownRichTextConverter:
|
|
|
246
276
|
if resolved_id:
|
|
247
277
|
return create_mention_func(resolved_id)
|
|
248
278
|
else:
|
|
249
|
-
return self._create_unresolved_mention_fallback(
|
|
279
|
+
return self._create_unresolved_mention_fallback(
|
|
280
|
+
identifier, mention_type
|
|
281
|
+
)
|
|
250
282
|
|
|
251
283
|
except Exception:
|
|
252
284
|
# If resolution throws an error, fallback to plain text
|
|
253
285
|
return self._create_unresolved_mention_fallback(identifier, mention_type)
|
|
254
286
|
|
|
255
|
-
def _create_unresolved_mention_fallback(
|
|
287
|
+
def _create_unresolved_mention_fallback(
|
|
288
|
+
self, identifier: str, mention_type: MentionType
|
|
289
|
+
) -> RichText:
|
|
256
290
|
fallback_text = f"@{mention_type.value}[{identifier}]"
|
|
257
291
|
return RichText.for_caption(fallback_text)
|
|
258
292
|
|
|
@@ -140,7 +140,9 @@ class RichText(BaseModel):
|
|
|
140
140
|
def mention_user(cls, user_id: str) -> Self:
|
|
141
141
|
return cls(
|
|
142
142
|
type=RichTextType.MENTION,
|
|
143
|
-
mention=MentionObject(
|
|
143
|
+
mention=MentionObject(
|
|
144
|
+
type=MentionType.USER, user=MentionUserRef(id=user_id)
|
|
145
|
+
),
|
|
144
146
|
annotations=TextAnnotations(),
|
|
145
147
|
)
|
|
146
148
|
|
|
@@ -148,7 +150,9 @@ class RichText(BaseModel):
|
|
|
148
150
|
def mention_page(cls, page_id: str) -> Self:
|
|
149
151
|
return cls(
|
|
150
152
|
type=RichTextType.MENTION,
|
|
151
|
-
mention=MentionObject(
|
|
153
|
+
mention=MentionObject(
|
|
154
|
+
type=MentionType.PAGE, page=MentionPageRef(id=page_id)
|
|
155
|
+
),
|
|
152
156
|
annotations=TextAnnotations(),
|
|
153
157
|
)
|
|
154
158
|
|
|
@@ -156,7 +160,9 @@ class RichText(BaseModel):
|
|
|
156
160
|
def mention_database(cls, database_id: str) -> Self:
|
|
157
161
|
return cls(
|
|
158
162
|
type=RichTextType.MENTION,
|
|
159
|
-
mention=MentionObject(
|
|
163
|
+
mention=MentionObject(
|
|
164
|
+
type=MentionType.DATABASE, database=MentionDatabaseRef(id=database_id)
|
|
165
|
+
),
|
|
160
166
|
annotations=TextAnnotations(),
|
|
161
167
|
)
|
|
162
168
|
|
|
@@ -164,7 +170,10 @@ class RichText(BaseModel):
|
|
|
164
170
|
def mention_data_source(cls, data_source_id: str) -> Self:
|
|
165
171
|
return cls(
|
|
166
172
|
type=RichTextType.MENTION,
|
|
167
|
-
mention=MentionObject(
|
|
173
|
+
mention=MentionObject(
|
|
174
|
+
type=MentionType.DATASOURCE,
|
|
175
|
+
data_source=MentionDataSourceRef(id=data_source_id),
|
|
176
|
+
),
|
|
168
177
|
annotations=TextAnnotations(),
|
|
169
178
|
)
|
|
170
179
|
|
{notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/name_id_resolver/data_source.py
RENAMED
|
@@ -6,8 +6,12 @@ from notionary.workspace.query.service import WorkspaceQueryService
|
|
|
6
6
|
|
|
7
7
|
# !!! in the notion api mentions that reference datasources are not provided yet (it's a limiation of the API as of now)
|
|
8
8
|
class DataSourceNameIdResolver(NameIdResolver):
|
|
9
|
-
def __init__(
|
|
10
|
-
self
|
|
9
|
+
def __init__(
|
|
10
|
+
self, workspace_query_service: WorkspaceQueryService | None = None
|
|
11
|
+
) -> None:
|
|
12
|
+
self._workspace_query_service = (
|
|
13
|
+
workspace_query_service or WorkspaceQueryService()
|
|
14
|
+
)
|
|
11
15
|
|
|
12
16
|
@override
|
|
13
17
|
async def resolve_name_to_id(self, name: str) -> str | None:
|
|
@@ -15,7 +19,9 @@ class DataSourceNameIdResolver(NameIdResolver):
|
|
|
15
19
|
return None
|
|
16
20
|
|
|
17
21
|
cleaned_name = name.strip()
|
|
18
|
-
data_source = await self._workspace_query_service.find_data_source(
|
|
22
|
+
data_source = await self._workspace_query_service.find_data_source(
|
|
23
|
+
query=cleaned_name
|
|
24
|
+
)
|
|
19
25
|
return data_source.id if data_source else None
|
|
20
26
|
|
|
21
27
|
@override
|
|
@@ -6,7 +6,9 @@ from notionary.user.person import PersonUser
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class PersonNameIdResolver(NameIdResolver):
|
|
9
|
-
def __init__(
|
|
9
|
+
def __init__(
|
|
10
|
+
self, person_user_factory=None, http_client: UserHttpClient | None = None
|
|
11
|
+
) -> None:
|
|
10
12
|
if person_user_factory is None:
|
|
11
13
|
person_user_factory = PersonUser
|
|
12
14
|
self.person_user_factory = person_user_factory
|
|
@@ -31,7 +33,9 @@ class PersonNameIdResolver(NameIdResolver):
|
|
|
31
33
|
return None
|
|
32
34
|
|
|
33
35
|
try:
|
|
34
|
-
user = await self.person_user_factory.from_id(
|
|
36
|
+
user = await self.person_user_factory.from_id(
|
|
37
|
+
user_id.strip(), self.http_client
|
|
38
|
+
)
|
|
35
39
|
return user.name if user else None
|
|
36
40
|
except Exception:
|
|
37
41
|
return None
|
{notionary-0.4.0 → notionary-0.4.2}/notionary/blocks/rich_text/rich_text_markdown_converter.py
RENAMED
|
@@ -69,7 +69,9 @@ class RichTextToMarkdownConverter:
|
|
|
69
69
|
return await self._extract_database_mention_markdown(mention.database.id)
|
|
70
70
|
|
|
71
71
|
elif mention.type == MentionType.DATASOURCE and mention.data_source:
|
|
72
|
-
return await self._extract_data_source_mention_markdown(
|
|
72
|
+
return await self._extract_data_source_mention_markdown(
|
|
73
|
+
mention.data_source.id
|
|
74
|
+
)
|
|
73
75
|
|
|
74
76
|
elif mention.type == MentionType.USER and mention.user:
|
|
75
77
|
return await self._extract_user_mention_markdown(mention.user.id)
|
|
@@ -88,7 +90,9 @@ class RichTextToMarkdownConverter:
|
|
|
88
90
|
return f"@database[{database_name or database_id}]"
|
|
89
91
|
|
|
90
92
|
async def _extract_data_source_mention_markdown(self, data_source_id: str) -> str:
|
|
91
|
-
data_source_name = await self.data_source_resolver.resolve_id_to_name(
|
|
93
|
+
data_source_name = await self.data_source_resolver.resolve_id_to_name(
|
|
94
|
+
data_source_id
|
|
95
|
+
)
|
|
92
96
|
return f"@datasource[{data_source_name or data_source_id}]"
|
|
93
97
|
|
|
94
98
|
async def _extract_user_mention_markdown(self, user_id: str) -> str:
|
|
@@ -121,7 +125,10 @@ class RichTextToMarkdownConverter:
|
|
|
121
125
|
if annotations.bold:
|
|
122
126
|
content = f"**{content}**"
|
|
123
127
|
|
|
124
|
-
if
|
|
128
|
+
if (
|
|
129
|
+
annotations.color != BlockColor.DEFAULT
|
|
130
|
+
and annotations.color in self.VALID_COLORS
|
|
131
|
+
):
|
|
125
132
|
content = f"({annotations.color}:{content})"
|
|
126
133
|
|
|
127
134
|
return content
|
|
@@ -34,7 +34,8 @@ class FileUploadFileWithCaption(CaptionMixin, FileUploadFile):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
type FileWithCaption = Annotated[
|
|
37
|
-
ExternalFileWithCaption | NotionHostedFileWithCaption | FileUploadFileWithCaption,
|
|
37
|
+
ExternalFileWithCaption | NotionHostedFileWithCaption | FileUploadFileWithCaption,
|
|
38
|
+
Field(discriminator="type"),
|
|
38
39
|
]
|
|
39
40
|
|
|
40
41
|
|
|
@@ -8,7 +8,10 @@ from notionary.comments.schemas import (
|
|
|
8
8
|
CommentListResponse,
|
|
9
9
|
)
|
|
10
10
|
from notionary.http.client import NotionHttpClient
|
|
11
|
-
from notionary.utils.pagination import
|
|
11
|
+
from notionary.utils.pagination import (
|
|
12
|
+
paginate_notion_api,
|
|
13
|
+
paginate_notion_api_generator,
|
|
14
|
+
)
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class CommentClient(NotionHttpClient):
|
|
@@ -21,16 +24,24 @@ class CommentClient(NotionHttpClient):
|
|
|
21
24
|
total_results_limit: int | None = None,
|
|
22
25
|
) -> AsyncGenerator[CommentDto]:
|
|
23
26
|
async for comment in paginate_notion_api_generator(
|
|
24
|
-
self._list_comments_page,
|
|
27
|
+
self._list_comments_page,
|
|
28
|
+
block_id=block_id,
|
|
29
|
+
total_results_limit=total_results_limit,
|
|
25
30
|
):
|
|
26
31
|
yield comment
|
|
27
32
|
|
|
28
|
-
async def get_all_comments(
|
|
33
|
+
async def get_all_comments(
|
|
34
|
+
self, block_id: str, *, total_results_limit: int | None = None
|
|
35
|
+
) -> list[CommentDto]:
|
|
29
36
|
all_comments = await paginate_notion_api(
|
|
30
|
-
self._list_comments_page,
|
|
37
|
+
self._list_comments_page,
|
|
38
|
+
block_id=block_id,
|
|
39
|
+
total_results_limit=total_results_limit,
|
|
31
40
|
)
|
|
32
41
|
|
|
33
|
-
self.logger.debug(
|
|
42
|
+
self.logger.debug(
|
|
43
|
+
"Retrieved %d total comments for block %s", len(all_comments), block_id
|
|
44
|
+
)
|
|
34
45
|
return all_comments
|
|
35
46
|
|
|
36
47
|
async def _list_comments_page(
|
|
@@ -65,7 +76,9 @@ class CommentClient(NotionHttpClient):
|
|
|
65
76
|
rich_text: list[RichText],
|
|
66
77
|
discussion_id: str,
|
|
67
78
|
) -> CommentDto:
|
|
68
|
-
request = CommentCreateRequest.for_discussion(
|
|
79
|
+
request = CommentCreateRequest.for_discussion(
|
|
80
|
+
discussion_id=discussion_id, rich_text=rich_text
|
|
81
|
+
)
|
|
69
82
|
|
|
70
83
|
body = request.model_dump(exclude_unset=True, exclude_none=True)
|
|
71
84
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
|
|
3
|
-
from notionary.blocks.rich_text.rich_text_markdown_converter import
|
|
3
|
+
from notionary.blocks.rich_text.rich_text_markdown_converter import (
|
|
4
|
+
RichTextToMarkdownConverter,
|
|
5
|
+
)
|
|
4
6
|
from notionary.comments.models import Comment
|
|
5
7
|
from notionary.comments.schemas import CommentDto
|
|
6
8
|
from notionary.user.base import BaseUser
|
|
@@ -20,7 +22,9 @@ class CommentFactory(LoggingMixin):
|
|
|
20
22
|
self.markdown_converter = markdown_converter or RichTextToMarkdownConverter()
|
|
21
23
|
|
|
22
24
|
async def create_from_dto(self, dto: CommentDto) -> Comment:
|
|
23
|
-
author_name, content = await asyncio.gather(
|
|
25
|
+
author_name, content = await asyncio.gather(
|
|
26
|
+
self._resolve_user_name(dto), self._resolve_content(dto)
|
|
27
|
+
)
|
|
24
28
|
|
|
25
29
|
return Comment(author_name=author_name, content=content)
|
|
26
30
|
|
|
@@ -30,7 +34,10 @@ class CommentFactory(LoggingMixin):
|
|
|
30
34
|
try:
|
|
31
35
|
return await BaseUser.from_id_auto(created_by_id, self.http_client)
|
|
32
36
|
except Exception:
|
|
33
|
-
self.logger.warning(
|
|
37
|
+
self.logger.warning(
|
|
38
|
+
f"Failed to resolve user name for user_id: {created_by_id}",
|
|
39
|
+
exc_info=True,
|
|
40
|
+
)
|
|
34
41
|
|
|
35
42
|
return self.UNKNOWN_AUTHOR
|
|
36
43
|
|
|
@@ -61,7 +61,9 @@ class CommentAttachmentFileUploadType(StrEnum):
|
|
|
61
61
|
|
|
62
62
|
class CommentAttachmentInput(BaseModel):
|
|
63
63
|
file_upload_id: str
|
|
64
|
-
type: Literal[CommentAttachmentFileUploadType.FILE_UPLOAD] =
|
|
64
|
+
type: Literal[CommentAttachmentFileUploadType.FILE_UPLOAD] = (
|
|
65
|
+
CommentAttachmentFileUploadType.FILE_UPLOAD
|
|
66
|
+
)
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
# ---------------------------
|
|
@@ -80,7 +82,9 @@ class CustomDisplayName(BaseModel):
|
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
class IntegrationDisplayName(BaseModel):
|
|
83
|
-
type: Literal[CommentDisplayNameType.INTEGRATION] =
|
|
85
|
+
type: Literal[CommentDisplayNameType.INTEGRATION] = (
|
|
86
|
+
CommentDisplayNameType.INTEGRATION
|
|
87
|
+
)
|
|
84
88
|
|
|
85
89
|
|
|
86
90
|
class UserDisplayName(BaseModel):
|
|
@@ -92,7 +96,9 @@ class CustomCommentDisplayName(BaseModel):
|
|
|
92
96
|
custom: CustomDisplayName
|
|
93
97
|
|
|
94
98
|
|
|
95
|
-
type CommentDisplayNameInput =
|
|
99
|
+
type CommentDisplayNameInput = (
|
|
100
|
+
IntegrationDisplayName | UserDisplayName | CustomCommentDisplayName
|
|
101
|
+
)
|
|
96
102
|
|
|
97
103
|
|
|
98
104
|
class CommentDisplayNameDto(BaseModel):
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
|
|
3
|
-
from notionary.blocks.rich_text.markdown_rich_text_converter import
|
|
3
|
+
from notionary.blocks.rich_text.markdown_rich_text_converter import (
|
|
4
|
+
MarkdownRichTextConverter,
|
|
5
|
+
)
|
|
4
6
|
from notionary.comments.client import CommentClient
|
|
5
7
|
from notionary.comments.factory import CommentFactory
|
|
6
8
|
from notionary.comments.models import Comment
|
|
@@ -20,15 +22,21 @@ class CommentService:
|
|
|
20
22
|
async def list_all_comments_for_page(self, page_id: str) -> list[Comment]:
|
|
21
23
|
comment_dtos = [dto async for dto in self.client.iter_comments(page_id)]
|
|
22
24
|
|
|
23
|
-
comments = await asyncio.gather(
|
|
25
|
+
comments = await asyncio.gather(
|
|
26
|
+
*(self.factory.create_from_dto(dto) for dto in comment_dtos)
|
|
27
|
+
)
|
|
24
28
|
return comments
|
|
25
29
|
|
|
26
30
|
async def create_comment_on_page(self, page_id: str, text: str) -> Comment:
|
|
27
31
|
rich_text = await self._converter.to_rich_text(text)
|
|
28
|
-
comment_dto = await self.client.create_comment_for_page(
|
|
32
|
+
comment_dto = await self.client.create_comment_for_page(
|
|
33
|
+
rich_text=rich_text, page_id=page_id
|
|
34
|
+
)
|
|
29
35
|
return await self.factory.create_from_dto(comment_dto)
|
|
30
36
|
|
|
31
37
|
async def reply_to_discussion_by_id(self, discussion_id: str, text: str) -> Comment:
|
|
32
38
|
rich_text = await self._converter.to_rich_text(text)
|
|
33
|
-
comment_dto = await self.client.create_comment_for_discussion(
|
|
39
|
+
comment_dto = await self.client.create_comment_for_discussion(
|
|
40
|
+
rich_text=rich_text, discussion_id=discussion_id
|
|
41
|
+
)
|
|
34
42
|
return await self.factory.create_from_dto(comment_dto)
|