notionary 0.4.0__py3-none-any.whl → 0.4.2__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 +44 -1
- notionary/blocks/client.py +37 -11
- notionary/blocks/rich_text/markdown_rich_text_converter.py +49 -15
- notionary/blocks/rich_text/models.py +13 -4
- notionary/blocks/rich_text/name_id_resolver/data_source.py +9 -3
- notionary/blocks/rich_text/name_id_resolver/person.py +6 -2
- notionary/blocks/rich_text/rich_text_markdown_converter.py +10 -3
- notionary/blocks/schemas.py +2 -1
- notionary/comments/client.py +19 -6
- notionary/comments/factory.py +10 -3
- notionary/comments/schemas.py +9 -3
- notionary/comments/service.py +12 -4
- notionary/data_source/http/data_source_instance_client.py +59 -17
- notionary/data_source/properties/schemas.py +30 -10
- notionary/data_source/query/builder.py +67 -18
- notionary/data_source/query/resolver.py +16 -5
- notionary/data_source/query/schema.py +24 -6
- notionary/data_source/query/validator.py +18 -6
- notionary/data_source/schema/registry.py +31 -12
- notionary/data_source/schema/service.py +66 -20
- notionary/data_source/service.py +74 -23
- notionary/database/client.py +27 -9
- notionary/database/database_metadata_update_client.py +12 -4
- notionary/database/service.py +11 -4
- notionary/exceptions/__init__.py +15 -3
- notionary/exceptions/block_parsing.py +6 -2
- notionary/exceptions/data_source/builder.py +11 -5
- notionary/exceptions/data_source/properties.py +3 -1
- notionary/exceptions/file_upload.py +12 -3
- notionary/exceptions/properties.py +3 -1
- notionary/exceptions/search.py +6 -2
- notionary/file_upload/client.py +5 -1
- notionary/file_upload/config/config.py +10 -3
- notionary/file_upload/query/builder.py +6 -2
- notionary/file_upload/schemas.py +3 -1
- notionary/file_upload/service.py +42 -14
- notionary/file_upload/validation/factory.py +3 -1
- notionary/file_upload/validation/impl/file_name_length.py +3 -1
- notionary/file_upload/validation/models.py +15 -5
- notionary/file_upload/validation/validators/file_extension.py +12 -3
- notionary/http/client.py +27 -8
- notionary/page/content/__init__.py +9 -0
- notionary/page/content/factory.py +21 -7
- notionary/page/content/markdown/builder.py +85 -23
- notionary/page/content/markdown/nodes/audio.py +8 -4
- notionary/page/content/markdown/nodes/base.py +3 -3
- notionary/page/content/markdown/nodes/bookmark.py +5 -3
- notionary/page/content/markdown/nodes/breadcrumb.py +2 -2
- notionary/page/content/markdown/nodes/bulleted_list.py +5 -3
- notionary/page/content/markdown/nodes/callout.py +2 -2
- notionary/page/content/markdown/nodes/code.py +5 -3
- notionary/page/content/markdown/nodes/columns.py +3 -3
- notionary/page/content/markdown/nodes/container.py +9 -5
- notionary/page/content/markdown/nodes/divider.py +2 -2
- notionary/page/content/markdown/nodes/embed.py +8 -4
- notionary/page/content/markdown/nodes/equation.py +4 -2
- notionary/page/content/markdown/nodes/file.py +8 -4
- notionary/page/content/markdown/nodes/heading.py +2 -2
- notionary/page/content/markdown/nodes/image.py +8 -4
- notionary/page/content/markdown/nodes/mixins/caption.py +5 -3
- notionary/page/content/markdown/nodes/numbered_list.py +5 -3
- notionary/page/content/markdown/nodes/paragraph.py +4 -2
- notionary/page/content/markdown/nodes/pdf.py +8 -4
- notionary/page/content/markdown/nodes/quote.py +2 -2
- notionary/page/content/markdown/nodes/space.py +2 -2
- notionary/page/content/markdown/nodes/table.py +8 -5
- notionary/page/content/markdown/nodes/table_of_contents.py +2 -2
- notionary/page/content/markdown/nodes/todo.py +15 -7
- notionary/page/content/markdown/nodes/toggle.py +2 -2
- notionary/page/content/markdown/nodes/video.py +8 -4
- notionary/page/content/markdown/structured_output/__init__.py +73 -0
- notionary/page/content/markdown/structured_output/models.py +391 -0
- notionary/page/content/markdown/structured_output/service.py +211 -0
- notionary/page/content/parser/context.py +1 -1
- notionary/page/content/parser/factory.py +23 -8
- notionary/page/content/parser/parsers/audio.py +7 -2
- notionary/page/content/parser/parsers/base.py +2 -2
- notionary/page/content/parser/parsers/bookmark.py +2 -2
- notionary/page/content/parser/parsers/breadcrumb.py +2 -2
- notionary/page/content/parser/parsers/bulleted_list.py +19 -6
- notionary/page/content/parser/parsers/callout.py +15 -5
- notionary/page/content/parser/parsers/caption.py +9 -3
- notionary/page/content/parser/parsers/code.py +21 -7
- notionary/page/content/parser/parsers/column.py +8 -4
- notionary/page/content/parser/parsers/column_list.py +19 -7
- notionary/page/content/parser/parsers/divider.py +2 -2
- notionary/page/content/parser/parsers/embed.py +2 -2
- notionary/page/content/parser/parsers/equation.py +8 -4
- notionary/page/content/parser/parsers/file.py +7 -2
- notionary/page/content/parser/parsers/file_like_block.py +30 -10
- notionary/page/content/parser/parsers/heading.py +31 -10
- notionary/page/content/parser/parsers/image.py +7 -2
- notionary/page/content/parser/parsers/numbered_list.py +18 -6
- notionary/page/content/parser/parsers/paragraph.py +3 -1
- notionary/page/content/parser/parsers/pdf.py +7 -2
- notionary/page/content/parser/parsers/quote.py +28 -9
- notionary/page/content/parser/parsers/space.py +2 -2
- notionary/page/content/parser/parsers/table.py +31 -10
- notionary/page/content/parser/parsers/table_of_contents.py +7 -3
- notionary/page/content/parser/parsers/todo.py +15 -5
- notionary/page/content/parser/parsers/toggle.py +15 -5
- notionary/page/content/parser/parsers/video.py +7 -2
- notionary/page/content/parser/post_processing/handlers/rich_text_length.py +8 -2
- notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +8 -2
- notionary/page/content/parser/post_processing/service.py +3 -1
- notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +21 -7
- notionary/page/content/parser/pre_processsing/handlers/indentation.py +11 -4
- notionary/page/content/parser/pre_processsing/handlers/video_syntax.py +13 -6
- notionary/page/content/parser/service.py +4 -1
- notionary/page/content/renderer/context.py +15 -5
- notionary/page/content/renderer/factory.py +12 -6
- notionary/page/content/renderer/post_processing/handlers/numbered_list.py +19 -9
- notionary/page/content/renderer/renderers/audio.py +14 -5
- notionary/page/content/renderer/renderers/base.py +3 -3
- notionary/page/content/renderer/renderers/bookmark.py +3 -1
- notionary/page/content/renderer/renderers/bulleted_list.py +11 -5
- notionary/page/content/renderer/renderers/callout.py +19 -7
- notionary/page/content/renderer/renderers/captioned_block.py +11 -5
- notionary/page/content/renderer/renderers/code.py +6 -2
- notionary/page/content/renderer/renderers/column.py +3 -1
- notionary/page/content/renderer/renderers/column_list.py +3 -1
- notionary/page/content/renderer/renderers/embed.py +3 -1
- notionary/page/content/renderer/renderers/equation.py +3 -1
- notionary/page/content/renderer/renderers/file.py +14 -5
- notionary/page/content/renderer/renderers/file_like_block.py +8 -4
- notionary/page/content/renderer/renderers/heading.py +22 -8
- notionary/page/content/renderer/renderers/image.py +13 -4
- notionary/page/content/renderer/renderers/numbered_list.py +8 -3
- notionary/page/content/renderer/renderers/paragraph.py +12 -4
- notionary/page/content/renderer/renderers/pdf.py +14 -5
- notionary/page/content/renderer/renderers/quote.py +14 -6
- notionary/page/content/renderer/renderers/table.py +15 -5
- notionary/page/content/renderer/renderers/todo.py +16 -6
- notionary/page/content/renderer/renderers/toggle.py +8 -4
- notionary/page/content/renderer/renderers/video.py +14 -5
- notionary/page/content/renderer/service.py +9 -3
- notionary/page/content/service.py +21 -7
- notionary/page/content/syntax/definition/__init__.py +11 -0
- notionary/page/content/syntax/definition/models.py +57 -0
- notionary/page/content/syntax/definition/registry.py +371 -0
- notionary/page/content/syntax/prompts/__init__.py +4 -0
- notionary/page/content/syntax/prompts/models.py +11 -0
- notionary/page/content/syntax/prompts/registry.py +703 -0
- notionary/page/page_metadata_update_client.py +12 -4
- notionary/page/properties/client.py +45 -15
- notionary/page/properties/factory.py +6 -2
- notionary/page/properties/service.py +110 -36
- notionary/page/service.py +20 -6
- notionary/shared/entity/client.py +6 -2
- notionary/shared/entity/dto_parsers.py +3 -1
- notionary/shared/entity/entity_metadata_update_client.py +9 -3
- notionary/shared/entity/schemas.py +1 -1
- notionary/shared/entity/service.py +53 -22
- notionary/shared/models/file.py +3 -1
- notionary/shared/models/icon.py +6 -4
- notionary/user/base.py +6 -2
- notionary/user/bot.py +10 -2
- notionary/user/client.py +3 -1
- notionary/user/person.py +3 -1
- notionary/user/schemas.py +3 -1
- notionary/user/service.py +6 -2
- notionary/utils/decorators.py +6 -2
- notionary/utils/fuzzy.py +6 -2
- notionary/utils/mixins/logging.py +3 -1
- notionary/utils/pagination.py +14 -4
- notionary/workspace/__init__.py +5 -1
- notionary/workspace/query/service.py +59 -16
- notionary/workspace/service.py +39 -11
- {notionary-0.4.0.dist-info → notionary-0.4.2.dist-info}/METADATA +1 -1
- notionary-0.4.2.dist-info/RECORD +236 -0
- notionary/page/blocks/client.py +0 -1
- notionary/page/content/syntax/__init__.py +0 -5
- notionary/page/content/syntax/models.py +0 -66
- notionary/page/content/syntax/registry.py +0 -371
- notionary-0.4.0.dist-info/RECORD +0 -230
- /notionary/page/content/syntax/{grammar.py → definition/grammar.py} +0 -0
- {notionary-0.4.0.dist-info → notionary-0.4.2.dist-info}/WHEEL +0 -0
- {notionary-0.4.0.dist-info → notionary-0.4.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,11 +2,11 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.schemas import CreateEmbedBlock, EmbedData
|
|
4
4
|
from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
|
|
5
|
-
from notionary.page.content.syntax import
|
|
5
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class EmbedParser(LineParser):
|
|
9
|
-
def __init__(self, syntax_registry:
|
|
9
|
+
def __init__(self, syntax_registry: SyntaxDefinitionRegistry) -> None:
|
|
10
10
|
super().__init__(syntax_registry)
|
|
11
11
|
self._syntax = syntax_registry.get_embed_syntax()
|
|
12
12
|
|
|
@@ -5,11 +5,11 @@ from notionary.page.content.parser.parsers.base import (
|
|
|
5
5
|
BlockParsingContext,
|
|
6
6
|
LineParser,
|
|
7
7
|
)
|
|
8
|
-
from notionary.page.content.syntax import
|
|
8
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class EquationParser(LineParser):
|
|
12
|
-
def __init__(self, syntax_registry:
|
|
12
|
+
def __init__(self, syntax_registry: SyntaxDefinitionRegistry) -> None:
|
|
13
13
|
super().__init__(syntax_registry)
|
|
14
14
|
self._syntax = syntax_registry.get_equation_syntax()
|
|
15
15
|
|
|
@@ -24,7 +24,9 @@ class EquationParser(LineParser):
|
|
|
24
24
|
equation_content = self._collect_equation_content(context)
|
|
25
25
|
lines_consumed = self._count_lines_consumed(context)
|
|
26
26
|
|
|
27
|
-
block = self._create_equation_block(
|
|
27
|
+
block = self._create_equation_block(
|
|
28
|
+
opening_line=context.line, equation_lines=equation_content
|
|
29
|
+
)
|
|
28
30
|
|
|
29
31
|
if block:
|
|
30
32
|
context.lines_consumed = lines_consumed
|
|
@@ -50,7 +52,9 @@ class EquationParser(LineParser):
|
|
|
50
52
|
|
|
51
53
|
return len(context.get_remaining_lines())
|
|
52
54
|
|
|
53
|
-
def _create_equation_block(
|
|
55
|
+
def _create_equation_block(
|
|
56
|
+
self, opening_line: str, equation_lines: list[str]
|
|
57
|
+
) -> CreateEquationBlock | None:
|
|
54
58
|
if opening_line.strip() != self._syntax.start_delimiter:
|
|
55
59
|
return None
|
|
56
60
|
|
|
@@ -2,12 +2,17 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.schemas import CreateFileBlock, ExternalFileWithCaption
|
|
4
4
|
from notionary.page.content.parser.parsers.file_like_block import FileLikeBlockParser
|
|
5
|
-
from notionary.page.content.syntax import
|
|
5
|
+
from notionary.page.content.syntax.definition import (
|
|
6
|
+
SyntaxDefinition,
|
|
7
|
+
SyntaxDefinitionRegistry,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class FileParser(FileLikeBlockParser[CreateFileBlock]):
|
|
9
12
|
@override
|
|
10
|
-
def _get_syntax(
|
|
13
|
+
def _get_syntax(
|
|
14
|
+
self, syntax_registry: SyntaxDefinitionRegistry
|
|
15
|
+
) -> SyntaxDefinition:
|
|
11
16
|
return syntax_registry.get_file_syntax()
|
|
12
17
|
|
|
13
18
|
@override
|
|
@@ -10,8 +10,8 @@ from notionary.blocks.schemas import (
|
|
|
10
10
|
from notionary.exceptions.file_upload import UploadFailedError, UploadTimeoutError
|
|
11
11
|
from notionary.file_upload.service import NotionFileUpload
|
|
12
12
|
from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
|
|
13
|
-
from notionary.page.content.syntax import
|
|
14
|
-
from notionary.page.content.syntax.models import SyntaxDefinition
|
|
13
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
14
|
+
from notionary.page.content.syntax.definition.models import SyntaxDefinition
|
|
15
15
|
from notionary.shared.models.file import ExternalFileData, FileUploadedFileData
|
|
16
16
|
from notionary.utils.mixins.logging import LoggingMixin
|
|
17
17
|
|
|
@@ -19,13 +19,19 @@ _TBlock = TypeVar("_TBlock")
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class FileLikeBlockParser(LineParser, LoggingMixin, Generic[_TBlock]):
|
|
22
|
-
def __init__(
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
25
|
+
file_upload_service: NotionFileUpload | None = None,
|
|
26
|
+
) -> None:
|
|
23
27
|
super().__init__(syntax_registry)
|
|
24
28
|
self._syntax = self._get_syntax(syntax_registry)
|
|
25
29
|
self._file_upload_service = file_upload_service or NotionFileUpload()
|
|
26
30
|
|
|
27
31
|
@abstractmethod
|
|
28
|
-
def _get_syntax(
|
|
32
|
+
def _get_syntax(
|
|
33
|
+
self, syntax_registry: SyntaxDefinitionRegistry
|
|
34
|
+
) -> SyntaxDefinition:
|
|
29
35
|
pass
|
|
30
36
|
|
|
31
37
|
@abstractmethod
|
|
@@ -46,7 +52,9 @@ class FileLikeBlockParser(LineParser, LoggingMixin, Generic[_TBlock]):
|
|
|
46
52
|
|
|
47
53
|
try:
|
|
48
54
|
if self._is_external_url(path_or_url):
|
|
49
|
-
file_data = ExternalFileWithCaption(
|
|
55
|
+
file_data = ExternalFileWithCaption(
|
|
56
|
+
external=ExternalFileData(url=path_or_url)
|
|
57
|
+
)
|
|
50
58
|
else:
|
|
51
59
|
file_data = await self._upload_local_file(path_or_url)
|
|
52
60
|
|
|
@@ -56,15 +64,27 @@ class FileLikeBlockParser(LineParser, LoggingMixin, Generic[_TBlock]):
|
|
|
56
64
|
except FileNotFoundError:
|
|
57
65
|
self.logger.warning("File not found: '%s' - skipping block", path_or_url)
|
|
58
66
|
except PermissionError:
|
|
59
|
-
self.logger.warning(
|
|
67
|
+
self.logger.warning(
|
|
68
|
+
"No permission to read file: '%s' - skipping block", path_or_url
|
|
69
|
+
)
|
|
60
70
|
except IsADirectoryError:
|
|
61
|
-
self.logger.warning(
|
|
71
|
+
self.logger.warning(
|
|
72
|
+
"Path is a directory, not a file: '%s' - skipping block", path_or_url
|
|
73
|
+
)
|
|
62
74
|
except (UploadFailedError, UploadTimeoutError) as e:
|
|
63
|
-
self.logger.warning(
|
|
75
|
+
self.logger.warning(
|
|
76
|
+
"Upload failed for '%s': %s - skipping block", path_or_url, e
|
|
77
|
+
)
|
|
64
78
|
except OSError as e:
|
|
65
|
-
self.logger.warning(
|
|
79
|
+
self.logger.warning(
|
|
80
|
+
"IO error reading file '%s': %s - skipping block", path_or_url, e
|
|
81
|
+
)
|
|
66
82
|
except Exception as e:
|
|
67
|
-
self.logger.warning(
|
|
83
|
+
self.logger.warning(
|
|
84
|
+
"Unexpected error processing file '%s': %s - skipping block",
|
|
85
|
+
path_or_url,
|
|
86
|
+
e,
|
|
87
|
+
)
|
|
68
88
|
|
|
69
89
|
def _extract_path_or_url(self, line: str) -> str | None:
|
|
70
90
|
match = self._syntax.regex_pattern.search(line)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from typing import override
|
|
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.blocks.schemas import (
|
|
5
7
|
BlockColor,
|
|
6
8
|
BlockCreatePayload,
|
|
@@ -15,14 +17,18 @@ from notionary.page.content.parser.parsers.base import (
|
|
|
15
17
|
BlockParsingContext,
|
|
16
18
|
LineParser,
|
|
17
19
|
)
|
|
18
|
-
from notionary.page.content.syntax import
|
|
20
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
class HeadingParser(LineParser):
|
|
22
24
|
MIN_HEADING_LEVEL = 1
|
|
23
25
|
MAX_HEADING_LEVEL = 3
|
|
24
26
|
|
|
25
|
-
def __init__(
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
30
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
31
|
+
) -> None:
|
|
26
32
|
super().__init__(syntax_registry)
|
|
27
33
|
self._syntax = syntax_registry.get_heading_syntax()
|
|
28
34
|
self._rich_text_converter = rich_text_converter
|
|
@@ -42,7 +48,9 @@ class HeadingParser(LineParser):
|
|
|
42
48
|
await self._process_nested_children(block, context)
|
|
43
49
|
context.result_blocks.append(block)
|
|
44
50
|
|
|
45
|
-
async def _process_nested_children(
|
|
51
|
+
async def _process_nested_children(
|
|
52
|
+
self, block: CreateHeadingBlock, context: BlockParsingContext
|
|
53
|
+
) -> None:
|
|
46
54
|
parent_indent_level = context.get_line_indentation_level()
|
|
47
55
|
child_lines = context.collect_indented_child_lines(parent_indent_level)
|
|
48
56
|
|
|
@@ -64,7 +72,9 @@ class HeadingParser(LineParser):
|
|
|
64
72
|
|
|
65
73
|
context.lines_consumed = len(child_lines)
|
|
66
74
|
|
|
67
|
-
def _set_heading_toggleable(
|
|
75
|
+
def _set_heading_toggleable(
|
|
76
|
+
self, block: CreateHeadingBlock, is_toggleable: bool
|
|
77
|
+
) -> None:
|
|
68
78
|
if block.type == BlockType.HEADING_1:
|
|
69
79
|
block.heading_1.is_toggleable = is_toggleable
|
|
70
80
|
elif block.type == BlockType.HEADING_2:
|
|
@@ -72,7 +82,9 @@ class HeadingParser(LineParser):
|
|
|
72
82
|
elif block.type == BlockType.HEADING_3:
|
|
73
83
|
block.heading_3.is_toggleable = is_toggleable
|
|
74
84
|
|
|
75
|
-
def _set_heading_children(
|
|
85
|
+
def _set_heading_children(
|
|
86
|
+
self, block: CreateHeadingBlock, children: list[BlockCreatePayload]
|
|
87
|
+
) -> None:
|
|
76
88
|
if block.type == BlockType.HEADING_1:
|
|
77
89
|
block.heading_1.children = children
|
|
78
90
|
elif block.type == BlockType.HEADING_2:
|
|
@@ -100,13 +112,22 @@ class HeadingParser(LineParser):
|
|
|
100
112
|
return self._create_heading_block_by_level(level, heading_data)
|
|
101
113
|
|
|
102
114
|
def _is_valid_heading(self, level: int, content: str) -> bool:
|
|
103
|
-
return self.MIN_HEADING_LEVEL <= level <= self.MAX_HEADING_LEVEL and bool(
|
|
115
|
+
return self.MIN_HEADING_LEVEL <= level <= self.MAX_HEADING_LEVEL and bool(
|
|
116
|
+
content
|
|
117
|
+
)
|
|
104
118
|
|
|
105
119
|
async def _build_heading_data(self, content: str) -> CreateHeadingData:
|
|
106
120
|
rich_text = await self._rich_text_converter.to_rich_text(content)
|
|
107
|
-
return CreateHeadingData(
|
|
108
|
-
|
|
109
|
-
|
|
121
|
+
return CreateHeadingData(
|
|
122
|
+
rich_text=rich_text,
|
|
123
|
+
color=BlockColor.DEFAULT,
|
|
124
|
+
is_toggleable=False,
|
|
125
|
+
children=[],
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def _create_heading_block_by_level(
|
|
129
|
+
self, level: int, heading_data: CreateHeadingData
|
|
130
|
+
) -> CreateHeadingBlock:
|
|
110
131
|
if level == 1:
|
|
111
132
|
return CreateHeading1Block(heading_1=heading_data)
|
|
112
133
|
elif level == 2:
|
|
@@ -2,12 +2,17 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.schemas import CreateImageBlock, ExternalFileWithCaption
|
|
4
4
|
from notionary.page.content.parser.parsers.file_like_block import FileLikeBlockParser
|
|
5
|
-
from notionary.page.content.syntax import
|
|
5
|
+
from notionary.page.content.syntax.definition import (
|
|
6
|
+
SyntaxDefinition,
|
|
7
|
+
SyntaxDefinitionRegistry,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class ImageParser(FileLikeBlockParser[CreateImageBlock]):
|
|
9
12
|
@override
|
|
10
|
-
def _get_syntax(
|
|
13
|
+
def _get_syntax(
|
|
14
|
+
self, syntax_registry: SyntaxDefinitionRegistry
|
|
15
|
+
) -> SyntaxDefinition:
|
|
11
16
|
return syntax_registry.get_image_syntax()
|
|
12
17
|
|
|
13
18
|
@override
|
|
@@ -12,11 +12,15 @@ from notionary.page.content.parser.parsers.base import (
|
|
|
12
12
|
BlockParsingContext,
|
|
13
13
|
LineParser,
|
|
14
14
|
)
|
|
15
|
-
from notionary.page.content.syntax import
|
|
15
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class NumberedListParser(LineParser):
|
|
19
|
-
def __init__(
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
22
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
23
|
+
) -> None:
|
|
20
24
|
super().__init__(syntax_registry)
|
|
21
25
|
self._syntax = syntax_registry.get_numbered_list_syntax()
|
|
22
26
|
self._rich_text_converter = rich_text_converter
|
|
@@ -39,7 +43,9 @@ class NumberedListParser(LineParser):
|
|
|
39
43
|
await self._process_nested_children(block, context)
|
|
40
44
|
context.result_blocks.append(block)
|
|
41
45
|
|
|
42
|
-
async def _process_nested_children(
|
|
46
|
+
async def _process_nested_children(
|
|
47
|
+
self, block: CreateNumberedListItemBlock, context: BlockParsingContext
|
|
48
|
+
) -> None:
|
|
43
49
|
child_lines = self._collect_child_lines(context)
|
|
44
50
|
if not child_lines:
|
|
45
51
|
return
|
|
@@ -61,13 +67,17 @@ class NumberedListParser(LineParser):
|
|
|
61
67
|
children_text = self._convert_lines_to_text(stripped_lines)
|
|
62
68
|
return await context.parse_nested_markdown(children_text)
|
|
63
69
|
|
|
64
|
-
def _remove_parent_indentation(
|
|
70
|
+
def _remove_parent_indentation(
|
|
71
|
+
self, lines: list[str], context: BlockParsingContext
|
|
72
|
+
) -> list[str]:
|
|
65
73
|
return context.strip_indentation_level(lines, levels=1)
|
|
66
74
|
|
|
67
75
|
def _convert_lines_to_text(self, lines: list[str]) -> str:
|
|
68
76
|
return "\n".join(lines)
|
|
69
77
|
|
|
70
|
-
async def _create_numbered_list_block(
|
|
78
|
+
async def _create_numbered_list_block(
|
|
79
|
+
self, text: str
|
|
80
|
+
) -> CreateNumberedListItemBlock | None:
|
|
71
81
|
content = self._extract_list_content(text)
|
|
72
82
|
if content is None:
|
|
73
83
|
return None
|
|
@@ -85,5 +95,7 @@ class NumberedListParser(LineParser):
|
|
|
85
95
|
return await self._rich_text_converter.to_rich_text(content)
|
|
86
96
|
|
|
87
97
|
def _build_block(self, rich_text) -> CreateNumberedListItemBlock:
|
|
88
|
-
numbered_list_content = CreateNumberedListItemData(
|
|
98
|
+
numbered_list_content = CreateNumberedListItemData(
|
|
99
|
+
rich_text=rich_text, color=BlockColor.DEFAULT
|
|
100
|
+
)
|
|
89
101
|
return CreateNumberedListItemBlock(numbered_list_item=numbered_list_content)
|
|
@@ -33,5 +33,7 @@ class ParagraphParser(LineParser):
|
|
|
33
33
|
return None
|
|
34
34
|
|
|
35
35
|
rich_text = await self._rich_text_converter.to_rich_text(text)
|
|
36
|
-
paragraph_content = CreateParagraphData(
|
|
36
|
+
paragraph_content = CreateParagraphData(
|
|
37
|
+
rich_text=rich_text, color=BlockColor.DEFAULT
|
|
38
|
+
)
|
|
37
39
|
return CreateParagraphBlock(paragraph=paragraph_content)
|
|
@@ -2,12 +2,17 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.schemas import CreatePdfBlock, ExternalFileWithCaption
|
|
4
4
|
from notionary.page.content.parser.parsers.file_like_block import FileLikeBlockParser
|
|
5
|
-
from notionary.page.content.syntax import
|
|
5
|
+
from notionary.page.content.syntax.definition import (
|
|
6
|
+
SyntaxDefinition,
|
|
7
|
+
SyntaxDefinitionRegistry,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class PdfParser(FileLikeBlockParser[CreatePdfBlock]):
|
|
9
12
|
@override
|
|
10
|
-
def _get_syntax(
|
|
13
|
+
def _get_syntax(
|
|
14
|
+
self, syntax_registry: SyntaxDefinitionRegistry
|
|
15
|
+
) -> SyntaxDefinition:
|
|
11
16
|
return syntax_registry.get_pdf_syntax()
|
|
12
17
|
|
|
13
18
|
@override
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
from typing import override
|
|
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.blocks.schemas import BlockColor, CreateQuoteBlock, CreateQuoteData
|
|
5
7
|
from notionary.page.content.parser.parsers.base import (
|
|
6
8
|
BlockParsingContext,
|
|
7
9
|
LineParser,
|
|
8
10
|
)
|
|
9
|
-
from notionary.page.content.syntax import
|
|
11
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class QuoteParser(LineParser):
|
|
13
|
-
def __init__(
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
18
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
19
|
+
) -> None:
|
|
14
20
|
super().__init__(syntax_registry)
|
|
15
21
|
self._syntax = syntax_registry.get_quote_syntax()
|
|
16
22
|
self._rich_text_converter = rich_text_converter
|
|
@@ -47,11 +53,16 @@ class QuoteParser(LineParser):
|
|
|
47
53
|
return quote_lines
|
|
48
54
|
|
|
49
55
|
async def _process_nested_children(
|
|
50
|
-
self,
|
|
56
|
+
self,
|
|
57
|
+
block: CreateQuoteBlock,
|
|
58
|
+
context: BlockParsingContext,
|
|
59
|
+
quote_lines: list[str],
|
|
51
60
|
) -> None:
|
|
52
61
|
# Calculate indent level after all quote lines
|
|
53
62
|
last_quote_line_index = len(quote_lines) - 1
|
|
54
|
-
child_lines = self._collect_child_lines_after_quote(
|
|
63
|
+
child_lines = self._collect_child_lines_after_quote(
|
|
64
|
+
context, last_quote_line_index
|
|
65
|
+
)
|
|
55
66
|
|
|
56
67
|
if not child_lines:
|
|
57
68
|
return
|
|
@@ -62,7 +73,9 @@ class QuoteParser(LineParser):
|
|
|
62
73
|
|
|
63
74
|
context.lines_consumed += len(child_lines)
|
|
64
75
|
|
|
65
|
-
def _collect_child_lines_after_quote(
|
|
76
|
+
def _collect_child_lines_after_quote(
|
|
77
|
+
self, context: BlockParsingContext, last_quote_index: int
|
|
78
|
+
) -> list[str]:
|
|
66
79
|
"""Collect indented children after the quote block."""
|
|
67
80
|
parent_indent_level = context.get_line_indentation_level()
|
|
68
81
|
remaining_lines = context.get_remaining_lines()
|
|
@@ -86,18 +99,24 @@ class QuoteParser(LineParser):
|
|
|
86
99
|
|
|
87
100
|
return child_lines
|
|
88
101
|
|
|
89
|
-
async def _parse_child_blocks(
|
|
102
|
+
async def _parse_child_blocks(
|
|
103
|
+
self, child_lines: list[str], context: BlockParsingContext
|
|
104
|
+
) -> list[CreateQuoteBlock]:
|
|
90
105
|
stripped_lines = self._remove_parent_indentation(child_lines, context)
|
|
91
106
|
children_text = self._convert_lines_to_text(stripped_lines)
|
|
92
107
|
return await context.parse_nested_markdown(children_text)
|
|
93
108
|
|
|
94
|
-
def _remove_parent_indentation(
|
|
109
|
+
def _remove_parent_indentation(
|
|
110
|
+
self, lines: list[str], context: BlockParsingContext
|
|
111
|
+
) -> list[str]:
|
|
95
112
|
return context.strip_indentation_level(lines, levels=1)
|
|
96
113
|
|
|
97
114
|
def _convert_lines_to_text(self, lines: list[str]) -> str:
|
|
98
115
|
return "\n".join(lines)
|
|
99
116
|
|
|
100
|
-
async def _create_quote_block(
|
|
117
|
+
async def _create_quote_block(
|
|
118
|
+
self, quote_lines: list[str]
|
|
119
|
+
) -> CreateQuoteBlock | None:
|
|
101
120
|
contents = self._extract_quote_contents(quote_lines)
|
|
102
121
|
if not contents:
|
|
103
122
|
return None
|
|
@@ -6,11 +6,11 @@ from notionary.page.content.parser.parsers.base import (
|
|
|
6
6
|
BlockParsingContext,
|
|
7
7
|
LineParser,
|
|
8
8
|
)
|
|
9
|
-
from notionary.page.content.syntax import
|
|
9
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class SpaceParser(LineParser):
|
|
13
|
-
def __init__(self, syntax_registry:
|
|
13
|
+
def __init__(self, syntax_registry: SyntaxDefinitionRegistry) -> None:
|
|
14
14
|
super().__init__(syntax_registry)
|
|
15
15
|
self._syntax = syntax_registry.get_space_syntax()
|
|
16
16
|
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
from typing import override
|
|
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.blocks.rich_text.models import RichText
|
|
5
|
-
from notionary.blocks.schemas import
|
|
7
|
+
from notionary.blocks.schemas import (
|
|
8
|
+
CreateTableBlock,
|
|
9
|
+
CreateTableData,
|
|
10
|
+
CreateTableRowBlock,
|
|
11
|
+
TableRowData,
|
|
12
|
+
)
|
|
6
13
|
from notionary.page.content.parser.parsers import BlockParsingContext, LineParser
|
|
7
|
-
from notionary.page.content.syntax import
|
|
14
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
class TableParser(LineParser):
|
|
11
|
-
def __init__(
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
21
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
22
|
+
) -> None:
|
|
12
23
|
super().__init__(syntax_registry)
|
|
13
24
|
self._syntax = syntax_registry.get_table_syntax()
|
|
14
25
|
self._separator_syntax = syntax_registry.get_table_row_syntax()
|
|
@@ -41,7 +52,9 @@ class TableParser(LineParser):
|
|
|
41
52
|
context.lines_consumed = lines_consumed
|
|
42
53
|
context.result_blocks.append(block)
|
|
43
54
|
|
|
44
|
-
def _collect_table_lines(
|
|
55
|
+
def _collect_table_lines(
|
|
56
|
+
self, table_lines: list[str], remaining_lines: list[str]
|
|
57
|
+
) -> int:
|
|
45
58
|
lines_consumed = 0
|
|
46
59
|
|
|
47
60
|
for index, line in enumerate(remaining_lines):
|
|
@@ -62,9 +75,13 @@ class TableParser(LineParser):
|
|
|
62
75
|
return lines_consumed
|
|
63
76
|
|
|
64
77
|
def _is_table_line(self, line: str) -> bool:
|
|
65
|
-
return self._syntax.regex_pattern.match(
|
|
78
|
+
return self._syntax.regex_pattern.match(
|
|
79
|
+
line
|
|
80
|
+
) or self._separator_syntax.regex_pattern.match(line)
|
|
66
81
|
|
|
67
|
-
async def _create_table_block(
|
|
82
|
+
async def _create_table_block(
|
|
83
|
+
self, table_lines: list[str]
|
|
84
|
+
) -> CreateTableBlock | None:
|
|
68
85
|
if not table_lines:
|
|
69
86
|
return None
|
|
70
87
|
|
|
@@ -93,7 +110,9 @@ class TableParser(LineParser):
|
|
|
93
110
|
return line_stripped
|
|
94
111
|
return None
|
|
95
112
|
|
|
96
|
-
async def _process_table_rows(
|
|
113
|
+
async def _process_table_rows(
|
|
114
|
+
self, table_lines: list[str]
|
|
115
|
+
) -> tuple[list[CreateTableRowBlock], bool]:
|
|
97
116
|
table_rows = []
|
|
98
117
|
has_separator = False
|
|
99
118
|
|
|
@@ -122,7 +141,9 @@ class TableParser(LineParser):
|
|
|
122
141
|
table_row_data = TableRowData(cells=rich_text_cells)
|
|
123
142
|
return CreateTableRowBlock(table_row=table_row_data)
|
|
124
143
|
|
|
125
|
-
async def _convert_cells_to_rich_text(
|
|
144
|
+
async def _convert_cells_to_rich_text(
|
|
145
|
+
self, cells: list[str]
|
|
146
|
+
) -> list[list[RichText]]:
|
|
126
147
|
rich_text_cells = []
|
|
127
148
|
|
|
128
149
|
for cell in cells:
|
|
@@ -132,7 +153,7 @@ class TableParser(LineParser):
|
|
|
132
153
|
return rich_text_cells
|
|
133
154
|
|
|
134
155
|
def _parse_table_row(self, row_text: str) -> list[str]:
|
|
135
|
-
"""Parse a table row by splitting on the table delimiter from
|
|
156
|
+
"""Parse a table row by splitting on the table delimiter from SyntaxDefinitionRegistry."""
|
|
136
157
|
row_content = row_text.strip()
|
|
137
158
|
delimiter = self._syntax.start_delimiter
|
|
138
159
|
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
from typing import override
|
|
2
2
|
|
|
3
|
-
from notionary.blocks.schemas import
|
|
3
|
+
from notionary.blocks.schemas import (
|
|
4
|
+
BlockColor,
|
|
5
|
+
CreateTableOfContentsBlock,
|
|
6
|
+
TableOfContentsData,
|
|
7
|
+
)
|
|
4
8
|
from notionary.page.content.parser.parsers.base import (
|
|
5
9
|
BlockParsingContext,
|
|
6
10
|
LineParser,
|
|
7
11
|
)
|
|
8
|
-
from notionary.page.content.syntax import
|
|
12
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
class TableOfContentsParser(LineParser):
|
|
12
|
-
def __init__(self, syntax_registry:
|
|
16
|
+
def __init__(self, syntax_registry: SyntaxDefinitionRegistry) -> None:
|
|
13
17
|
super().__init__(syntax_registry)
|
|
14
18
|
self._syntax = syntax_registry.get_table_of_contents_syntax()
|
|
15
19
|
|
|
@@ -8,11 +8,15 @@ from notionary.page.content.parser.parsers.base import (
|
|
|
8
8
|
BlockParsingContext,
|
|
9
9
|
LineParser,
|
|
10
10
|
)
|
|
11
|
-
from notionary.page.content.syntax import
|
|
11
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class TodoParser(LineParser):
|
|
15
|
-
def __init__(
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
18
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
19
|
+
) -> None:
|
|
16
20
|
super().__init__(syntax_registry)
|
|
17
21
|
self._syntax = syntax_registry.get_todo_syntax()
|
|
18
22
|
self._syntax_done = syntax_registry.get_todo_done_syntax()
|
|
@@ -39,7 +43,9 @@ class TodoParser(LineParser):
|
|
|
39
43
|
await self._process_nested_children(block, context)
|
|
40
44
|
context.result_blocks.append(block)
|
|
41
45
|
|
|
42
|
-
async def _process_nested_children(
|
|
46
|
+
async def _process_nested_children(
|
|
47
|
+
self, block: CreateToDoBlock, context: BlockParsingContext
|
|
48
|
+
) -> None:
|
|
43
49
|
child_lines = self._collect_child_lines(context)
|
|
44
50
|
if not child_lines:
|
|
45
51
|
return
|
|
@@ -54,12 +60,16 @@ class TodoParser(LineParser):
|
|
|
54
60
|
parent_indent_level = context.get_line_indentation_level()
|
|
55
61
|
return context.collect_indented_child_lines(parent_indent_level)
|
|
56
62
|
|
|
57
|
-
async def _parse_child_blocks(
|
|
63
|
+
async def _parse_child_blocks(
|
|
64
|
+
self, child_lines: list[str], context: BlockParsingContext
|
|
65
|
+
) -> list[CreateToDoBlock]:
|
|
58
66
|
stripped_lines = self._remove_parent_indentation(child_lines, context)
|
|
59
67
|
children_text = self._convert_lines_to_text(stripped_lines)
|
|
60
68
|
return await context.parse_nested_markdown(children_text)
|
|
61
69
|
|
|
62
|
-
def _remove_parent_indentation(
|
|
70
|
+
def _remove_parent_indentation(
|
|
71
|
+
self, lines: list[str], context: BlockParsingContext
|
|
72
|
+
) -> list[str]:
|
|
63
73
|
return context.strip_indentation_level(lines, levels=1)
|
|
64
74
|
|
|
65
75
|
def _convert_lines_to_text(self, lines: list[str]) -> str:
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
from typing import override
|
|
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.blocks.schemas import BlockColor, CreateToggleBlock, CreateToggleData
|
|
5
7
|
from notionary.page.content.parser.parsers import (
|
|
6
8
|
BlockParsingContext,
|
|
7
9
|
LineParser,
|
|
8
10
|
)
|
|
9
|
-
from notionary.page.content.syntax import
|
|
11
|
+
from notionary.page.content.syntax.definition import SyntaxDefinitionRegistry
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class ToggleParser(LineParser):
|
|
13
|
-
def __init__(
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
syntax_registry: SyntaxDefinitionRegistry,
|
|
18
|
+
rich_text_converter: MarkdownRichTextConverter,
|
|
19
|
+
) -> None:
|
|
14
20
|
super().__init__(syntax_registry)
|
|
15
21
|
self._syntax = syntax_registry.get_toggle_syntax()
|
|
16
22
|
self._heading_syntax = syntax_registry.get_toggleable_heading_syntax()
|
|
@@ -51,10 +57,14 @@ class ToggleParser(LineParser):
|
|
|
51
57
|
title = match.group(1).strip()
|
|
52
58
|
rich_text = await self._rich_text_converter.to_rich_text(title)
|
|
53
59
|
|
|
54
|
-
toggle_content = CreateToggleData(
|
|
60
|
+
toggle_content = CreateToggleData(
|
|
61
|
+
rich_text=rich_text, color=BlockColor.DEFAULT, children=[]
|
|
62
|
+
)
|
|
55
63
|
return CreateToggleBlock(toggle=toggle_content)
|
|
56
64
|
|
|
57
|
-
async def _process_nested_children(
|
|
65
|
+
async def _process_nested_children(
|
|
66
|
+
self, block: CreateToggleBlock, context: BlockParsingContext
|
|
67
|
+
) -> None:
|
|
58
68
|
parent_indent_level = context.get_line_indentation_level()
|
|
59
69
|
child_lines = context.collect_indented_child_lines(parent_indent_level)
|
|
60
70
|
|
|
@@ -2,12 +2,17 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.schemas import CreateVideoBlock, ExternalFileWithCaption
|
|
4
4
|
from notionary.page.content.parser.parsers.file_like_block import FileLikeBlockParser
|
|
5
|
-
from notionary.page.content.syntax import
|
|
5
|
+
from notionary.page.content.syntax.definition import (
|
|
6
|
+
SyntaxDefinition,
|
|
7
|
+
SyntaxDefinitionRegistry,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class VideoParser(FileLikeBlockParser[CreateVideoBlock]):
|
|
9
12
|
@override
|
|
10
|
-
def _get_syntax(
|
|
13
|
+
def _get_syntax(
|
|
14
|
+
self, syntax_registry: SyntaxDefinitionRegistry
|
|
15
|
+
) -> SyntaxDefinition:
|
|
11
16
|
return syntax_registry.get_video_syntax()
|
|
12
17
|
|
|
13
18
|
@override
|