notionary 0.3.1__py3-none-any.whl → 0.4.1__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 +49 -1
- notionary/blocks/client.py +37 -11
- notionary/blocks/enums.py +0 -6
- 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 +33 -78
- notionary/comments/client.py +19 -6
- notionary/comments/factory.py +10 -3
- notionary/comments/schemas.py +10 -31
- notionary/comments/service.py +12 -4
- notionary/data_source/http/data_source_instance_client.py +59 -17
- notionary/data_source/properties/schemas.py +156 -115
- 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/schemas.py +2 -2
- notionary/data_source/service.py +103 -43
- notionary/database/client.py +27 -9
- notionary/database/database_metadata_update_client.py +12 -4
- notionary/database/schemas.py +2 -2
- notionary/database/service.py +14 -9
- notionary/exceptions/__init__.py +20 -4
- notionary/exceptions/api.py +2 -2
- notionary/exceptions/base.py +1 -1
- notionary/exceptions/block_parsing.py +9 -5
- notionary/exceptions/data_source/builder.py +13 -7
- notionary/exceptions/data_source/properties.py +6 -4
- notionary/exceptions/file_upload.py +76 -0
- notionary/exceptions/properties.py +7 -5
- notionary/exceptions/search.py +10 -6
- notionary/file_upload/__init__.py +4 -0
- notionary/file_upload/client.py +128 -210
- notionary/file_upload/config/__init__.py +17 -0
- notionary/file_upload/config/config.py +39 -0
- notionary/file_upload/config/constants.py +16 -0
- notionary/file_upload/file/reader.py +28 -0
- notionary/file_upload/query/__init__.py +7 -0
- notionary/file_upload/query/builder.py +58 -0
- notionary/file_upload/query/models.py +37 -0
- notionary/file_upload/schemas.py +80 -0
- notionary/file_upload/service.py +182 -291
- notionary/file_upload/validation/factory.py +66 -0
- notionary/file_upload/validation/impl/file_name_length.py +25 -0
- notionary/file_upload/validation/models.py +134 -0
- notionary/file_upload/validation/port.py +7 -0
- notionary/file_upload/validation/service.py +17 -0
- notionary/file_upload/validation/validators/__init__.py +11 -0
- notionary/file_upload/validation/validators/file_exists.py +15 -0
- notionary/file_upload/validation/validators/file_extension.py +131 -0
- notionary/file_upload/validation/validators/file_name_length.py +21 -0
- notionary/file_upload/validation/validators/upload_limit.py +31 -0
- notionary/http/client.py +33 -30
- 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 +26 -8
- notionary/page/content/parser/parsers/audio.py +12 -32
- 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 -4
- notionary/page/content/parser/parsers/equation.py +8 -4
- notionary/page/content/parser/parsers/file.py +12 -34
- notionary/page/content/parser/parsers/file_like_block.py +109 -0
- notionary/page/content/parser/parsers/heading.py +31 -10
- notionary/page/content/parser/parsers/image.py +12 -34
- 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 +12 -34
- 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 +12 -34
- 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 +20 -23
- 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 +20 -23
- notionary/page/content/renderer/renderers/file_like_block.py +47 -0
- notionary/page/content/renderer/renderers/heading.py +22 -8
- notionary/page/content/renderer/renderers/image.py +20 -23
- 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 +20 -23
- 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 +20 -23
- 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 +46 -16
- notionary/page/properties/factory.py +6 -2
- notionary/page/properties/{models.py → schemas.py} +93 -107
- notionary/page/properties/service.py +111 -37
- notionary/page/schemas.py +3 -3
- notionary/page/service.py +21 -7
- notionary/shared/entity/client.py +6 -2
- notionary/shared/entity/dto_parsers.py +4 -37
- notionary/shared/entity/entity_metadata_update_client.py +25 -5
- notionary/shared/entity/schemas.py +6 -6
- notionary/shared/entity/service.py +89 -35
- notionary/shared/models/file.py +36 -6
- notionary/shared/models/icon.py +5 -12
- notionary/user/base.py +6 -2
- notionary/user/bot.py +22 -14
- 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 +13 -9
- notionary/utils/fuzzy.py +6 -2
- notionary/utils/mixins/logging.py +3 -1
- notionary/utils/pagination.py +14 -4
- notionary/workspace/__init__.py +6 -2
- notionary/workspace/query/__init__.py +2 -1
- notionary/workspace/query/service.py +42 -13
- notionary/workspace/service.py +74 -46
- {notionary-0.3.1.dist-info → notionary-0.4.1.dist-info}/METADATA +1 -1
- notionary-0.4.1.dist-info/RECORD +236 -0
- notionary/file_upload/models.py +0 -69
- notionary/page/blocks/client.py +0 -1
- notionary/page/content/syntax/__init__.py +0 -4
- notionary/page/content/syntax/models.py +0 -66
- notionary/page/content/syntax/registry.py +0 -393
- notionary/page/page_context.py +0 -50
- notionary/shared/models/cover.py +0 -20
- notionary-0.3.1.dist-info/RECORD +0 -211
- /notionary/page/content/syntax/{grammar.py → definition/grammar.py} +0 -0
- {notionary-0.3.1.dist-info → notionary-0.4.1.dist-info}/WHEEL +0 -0
- {notionary-0.3.1.dist-info → notionary-0.4.1.dist-info}/licenses/LICENSE +0 -0
notionary/database/client.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from notionary.blocks.rich_text.rich_text_markdown_converter import
|
|
1
|
+
from notionary.blocks.rich_text.rich_text_markdown_converter import (
|
|
2
|
+
RichTextToMarkdownConverter,
|
|
3
|
+
)
|
|
2
4
|
from notionary.database.schemas import (
|
|
3
5
|
NotionDatabaseDto,
|
|
4
6
|
NotionDatabaseUpdateDto,
|
|
@@ -15,14 +17,20 @@ class NotionDatabaseHttpClient(NotionHttpClient):
|
|
|
15
17
|
response = await self.get(f"databases/{self._database_id}")
|
|
16
18
|
return NotionDatabaseDto.model_validate(response)
|
|
17
19
|
|
|
18
|
-
async def patch_database(
|
|
20
|
+
async def patch_database(
|
|
21
|
+
self, update_database_dto: NotionDatabaseUpdateDto
|
|
22
|
+
) -> NotionDatabaseDto:
|
|
19
23
|
update_database_dto_dict = update_database_dto.model_dump(exclude_none=True)
|
|
20
24
|
|
|
21
|
-
response = await self.patch(
|
|
25
|
+
response = await self.patch(
|
|
26
|
+
f"databases/{self._database_id}", data=update_database_dto_dict
|
|
27
|
+
)
|
|
22
28
|
return NotionDatabaseDto.model_validate(response)
|
|
23
29
|
|
|
24
30
|
async def update_database_title(self, title: str) -> NotionDatabaseDto:
|
|
25
|
-
from notionary.blocks.rich_text.markdown_rich_text_converter import
|
|
31
|
+
from notionary.blocks.rich_text.markdown_rich_text_converter import (
|
|
32
|
+
MarkdownRichTextConverter,
|
|
33
|
+
)
|
|
26
34
|
|
|
27
35
|
markdown_rich_text_formatter = MarkdownRichTextConverter()
|
|
28
36
|
database_rich_text = await markdown_rich_text_formatter.to_rich_text(title)
|
|
@@ -31,13 +39,23 @@ class NotionDatabaseHttpClient(NotionHttpClient):
|
|
|
31
39
|
return await self.patch_database(database_title_update_dto)
|
|
32
40
|
|
|
33
41
|
async def update_database_description(self, description: str) -> str:
|
|
34
|
-
from notionary.blocks.rich_text.markdown_rich_text_converter import
|
|
42
|
+
from notionary.blocks.rich_text.markdown_rich_text_converter import (
|
|
43
|
+
MarkdownRichTextConverter,
|
|
44
|
+
)
|
|
35
45
|
|
|
36
46
|
markdown_to_rich_text_converter = MarkdownRichTextConverter()
|
|
37
|
-
rich_text_description = await markdown_to_rich_text_converter.to_rich_text(
|
|
47
|
+
rich_text_description = await markdown_to_rich_text_converter.to_rich_text(
|
|
48
|
+
description
|
|
49
|
+
)
|
|
38
50
|
|
|
39
|
-
database_description_update_dto = NotionDatabaseUpdateDto(
|
|
40
|
-
|
|
51
|
+
database_description_update_dto = NotionDatabaseUpdateDto(
|
|
52
|
+
description=rich_text_description
|
|
53
|
+
)
|
|
54
|
+
update_database_response = await self.patch_database(
|
|
55
|
+
database_description_update_dto
|
|
56
|
+
)
|
|
41
57
|
|
|
42
58
|
rich_text_to_markdown_converter = RichTextToMarkdownConverter()
|
|
43
|
-
return await rich_text_to_markdown_converter.to_markdown(
|
|
59
|
+
return await rich_text_to_markdown_converter.to_markdown(
|
|
60
|
+
update_database_response.description
|
|
61
|
+
)
|
|
@@ -2,7 +2,9 @@ from typing import override
|
|
|
2
2
|
|
|
3
3
|
from notionary.database.schemas import NotionDatabaseDto
|
|
4
4
|
from notionary.http.client import NotionHttpClient
|
|
5
|
-
from notionary.shared.entity.entity_metadata_update_client import
|
|
5
|
+
from notionary.shared.entity.entity_metadata_update_client import (
|
|
6
|
+
EntityMetadataUpdateClient,
|
|
7
|
+
)
|
|
6
8
|
from notionary.shared.entity.schemas import NotionEntityUpdateDto
|
|
7
9
|
|
|
8
10
|
|
|
@@ -12,8 +14,14 @@ class DatabaseMetadataUpdateClient(NotionHttpClient, EntityMetadataUpdateClient)
|
|
|
12
14
|
self._database_id = database_id
|
|
13
15
|
|
|
14
16
|
@override
|
|
15
|
-
async def patch_metadata(
|
|
16
|
-
|
|
17
|
+
async def patch_metadata(
|
|
18
|
+
self, updated_data: NotionEntityUpdateDto
|
|
19
|
+
) -> NotionDatabaseDto:
|
|
20
|
+
updated_data_dict = updated_data.model_dump(
|
|
21
|
+
exclude_unset=True, exclude_none=True
|
|
22
|
+
)
|
|
17
23
|
|
|
18
|
-
response_dict = await self.patch(
|
|
24
|
+
response_dict = await self.patch(
|
|
25
|
+
f"databases/{self._database_id}", data=updated_data_dict
|
|
26
|
+
)
|
|
19
27
|
return NotionDatabaseDto.model_validate(response_dict)
|
notionary/database/schemas.py
CHANGED
|
@@ -2,7 +2,7 @@ from pydantic import BaseModel, Field
|
|
|
2
2
|
|
|
3
3
|
from notionary.blocks.rich_text.models import RichText
|
|
4
4
|
from notionary.shared.entity.schemas import EntityResponseDto
|
|
5
|
-
from notionary.shared.models.
|
|
5
|
+
from notionary.shared.models.file import File
|
|
6
6
|
from notionary.shared.models.icon import Icon
|
|
7
7
|
|
|
8
8
|
|
|
@@ -24,6 +24,6 @@ class NotionDatabaseDto(EntityResponseDto):
|
|
|
24
24
|
class NotionDatabaseUpdateDto(BaseModel):
|
|
25
25
|
title: list[RichText] | None = None
|
|
26
26
|
icon: Icon | None = None
|
|
27
|
-
cover:
|
|
27
|
+
cover: File | None = None
|
|
28
28
|
archived: bool | None = None
|
|
29
29
|
description: list[RichText] | None = None
|
notionary/database/service.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
1
|
import asyncio
|
|
4
2
|
from collections.abc import Awaitable, Callable
|
|
5
3
|
from typing import Self
|
|
6
4
|
|
|
7
|
-
from notionary.blocks.rich_text.rich_text_markdown_converter import
|
|
5
|
+
from notionary.blocks.rich_text.rich_text_markdown_converter import (
|
|
6
|
+
RichTextToMarkdownConverter,
|
|
7
|
+
)
|
|
8
8
|
from notionary.data_source.service import NotionDataSource
|
|
9
9
|
from notionary.database.client import NotionDatabaseHttpClient
|
|
10
|
-
from notionary.database.database_metadata_update_client import
|
|
10
|
+
from notionary.database.database_metadata_update_client import (
|
|
11
|
+
DatabaseMetadataUpdateClient,
|
|
12
|
+
)
|
|
11
13
|
from notionary.database.schemas import NotionDatabaseDto
|
|
12
14
|
from notionary.shared.entity.dto_parsers import (
|
|
13
15
|
extract_description,
|
|
@@ -16,7 +18,7 @@ from notionary.shared.entity.dto_parsers import (
|
|
|
16
18
|
from notionary.shared.entity.service import Entity
|
|
17
19
|
from notionary.workspace.query.service import WorkspaceQueryService
|
|
18
20
|
|
|
19
|
-
type
|
|
21
|
+
type _DataSourceFactory = Callable[[str], Awaitable[NotionDataSource]]
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
class NotionDatabase(Entity):
|
|
@@ -73,7 +75,8 @@ class NotionDatabase(Entity):
|
|
|
73
75
|
client: NotionDatabaseHttpClient,
|
|
74
76
|
) -> Self:
|
|
75
77
|
title, description = await asyncio.gather(
|
|
76
|
-
extract_title(dto, rich_text_converter),
|
|
78
|
+
extract_title(dto, rich_text_converter),
|
|
79
|
+
extract_description(dto, rich_text_converter),
|
|
77
80
|
)
|
|
78
81
|
|
|
79
82
|
metadata_update_client = DatabaseMetadataUpdateClient(database_id=dto.id)
|
|
@@ -104,7 +107,7 @@ class NotionDatabase(Entity):
|
|
|
104
107
|
|
|
105
108
|
async def get_data_sources(
|
|
106
109
|
self,
|
|
107
|
-
data_source_factory:
|
|
110
|
+
data_source_factory: _DataSourceFactory = NotionDataSource.from_id,
|
|
108
111
|
) -> list[NotionDataSource]:
|
|
109
112
|
if self._data_sources is None:
|
|
110
113
|
self._data_sources = await self._load_data_sources(data_source_factory)
|
|
@@ -112,7 +115,7 @@ class NotionDatabase(Entity):
|
|
|
112
115
|
|
|
113
116
|
async def _load_data_sources(
|
|
114
117
|
self,
|
|
115
|
-
data_source_factory:
|
|
118
|
+
data_source_factory: _DataSourceFactory,
|
|
116
119
|
) -> list[NotionDataSource]:
|
|
117
120
|
tasks = [data_source_factory(ds_id) for ds_id in self._data_source_ids]
|
|
118
121
|
return list(await asyncio.gather(*tasks))
|
|
@@ -122,5 +125,7 @@ class NotionDatabase(Entity):
|
|
|
122
125
|
self._title = result.title[0].plain_text if result.title else ""
|
|
123
126
|
|
|
124
127
|
async def set_description(self, description: str) -> None:
|
|
125
|
-
updated_description = await self.client.update_database_description(
|
|
128
|
+
updated_description = await self.client.update_database_description(
|
|
129
|
+
description=description
|
|
130
|
+
)
|
|
126
131
|
self._description = updated_description
|
notionary/exceptions/__init__.py
CHANGED
|
@@ -7,10 +7,23 @@ from .api import (
|
|
|
7
7
|
NotionServerError,
|
|
8
8
|
NotionValidationError,
|
|
9
9
|
)
|
|
10
|
-
from .base import
|
|
11
|
-
from .block_parsing import
|
|
10
|
+
from .base import NotionaryException
|
|
11
|
+
from .block_parsing import (
|
|
12
|
+
InsufficientColumnsError,
|
|
13
|
+
InvalidColumnRatioSumError,
|
|
14
|
+
UnsupportedVideoFormatError,
|
|
15
|
+
)
|
|
12
16
|
from .data_source import DataSourcePropertyNotFound, DataSourcePropertyTypeError
|
|
13
|
-
from .
|
|
17
|
+
from .file_upload import (
|
|
18
|
+
FileSizeException,
|
|
19
|
+
NoFileExtensionException,
|
|
20
|
+
UnsupportedFileTypeException,
|
|
21
|
+
)
|
|
22
|
+
from .properties import (
|
|
23
|
+
AccessPagePropertyWithoutDataSourceError,
|
|
24
|
+
PagePropertyNotFoundError,
|
|
25
|
+
PagePropertyTypeError,
|
|
26
|
+
)
|
|
14
27
|
from .search import DatabaseNotFound, DataSourceNotFound, EntityNotFound, PageNotFound
|
|
15
28
|
|
|
16
29
|
__all__ = [
|
|
@@ -20,8 +33,10 @@ __all__ = [
|
|
|
20
33
|
"DataSourcePropertyTypeError",
|
|
21
34
|
"DatabaseNotFound",
|
|
22
35
|
"EntityNotFound",
|
|
36
|
+
"FileSizeException",
|
|
23
37
|
"InsufficientColumnsError",
|
|
24
38
|
"InvalidColumnRatioSumError",
|
|
39
|
+
"NoFileExtensionException",
|
|
25
40
|
"NotionApiError",
|
|
26
41
|
"NotionAuthenticationError",
|
|
27
42
|
"NotionConnectionError",
|
|
@@ -29,9 +44,10 @@ __all__ = [
|
|
|
29
44
|
"NotionResourceNotFoundError",
|
|
30
45
|
"NotionServerError",
|
|
31
46
|
"NotionValidationError",
|
|
32
|
-
"
|
|
47
|
+
"NotionaryException",
|
|
33
48
|
"PageNotFound",
|
|
34
49
|
"PagePropertyNotFoundError",
|
|
35
50
|
"PagePropertyTypeError",
|
|
51
|
+
"UnsupportedFileTypeException",
|
|
36
52
|
"UnsupportedVideoFormatError",
|
|
37
53
|
]
|
notionary/exceptions/api.py
CHANGED
notionary/exceptions/base.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class
|
|
1
|
+
class NotionaryException(Exception):
|
|
2
2
|
pass
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
from notionary.exceptions.base import
|
|
1
|
+
from notionary.exceptions.base import NotionaryException
|
|
2
2
|
|
|
3
3
|
RATIO_TOLERANCE = 0.0001
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class InsufficientColumnsError(
|
|
6
|
+
class InsufficientColumnsError(NotionaryException):
|
|
7
7
|
def __init__(self, column_count: int) -> None:
|
|
8
8
|
self.column_count = column_count
|
|
9
|
-
super().__init__(
|
|
9
|
+
super().__init__(
|
|
10
|
+
f"Columns container must contain at least 2 column blocks, but only {column_count} found"
|
|
11
|
+
)
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
class InvalidColumnRatioSumError(
|
|
14
|
+
class InvalidColumnRatioSumError(NotionaryException):
|
|
13
15
|
def __init__(self, total: float, tolerance: float = RATIO_TOLERANCE) -> None:
|
|
14
16
|
self.total = total
|
|
15
17
|
self.tolerance = tolerance
|
|
16
|
-
super().__init__(
|
|
18
|
+
super().__init__(
|
|
19
|
+
f"Width ratios must sum to 1.0 (±{tolerance}), but sum is {total}"
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
class UnsupportedVideoFormatError(ValueError):
|
|
@@ -8,11 +8,11 @@ from notionary.data_source.query.schema import (
|
|
|
8
8
|
Operator,
|
|
9
9
|
StringOperator,
|
|
10
10
|
)
|
|
11
|
-
from notionary.exceptions.base import
|
|
11
|
+
from notionary.exceptions.base import NotionaryException
|
|
12
12
|
from notionary.shared.properties.type import PropertyType
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class QueryBuilderError(
|
|
15
|
+
class QueryBuilderError(NotionaryException):
|
|
16
16
|
def __init__(self, message: str, property_name: str | None = None) -> None:
|
|
17
17
|
self.property_name = property_name
|
|
18
18
|
super().__init__(message)
|
|
@@ -67,7 +67,11 @@ class MissingRequiredValue(QueryBuilderError):
|
|
|
67
67
|
def __init__(
|
|
68
68
|
self,
|
|
69
69
|
property_name: str,
|
|
70
|
-
operator: StringOperator
|
|
70
|
+
operator: StringOperator
|
|
71
|
+
| NumberOperator
|
|
72
|
+
| BooleanOperator
|
|
73
|
+
| DateOperator
|
|
74
|
+
| ArrayOperator,
|
|
71
75
|
) -> None:
|
|
72
76
|
self.operator = operator
|
|
73
77
|
|
|
@@ -79,7 +83,11 @@ class ValueNotAllowedForOperator(QueryBuilderError):
|
|
|
79
83
|
def __init__(
|
|
80
84
|
self,
|
|
81
85
|
property_name: str,
|
|
82
|
-
operator: StringOperator
|
|
86
|
+
operator: StringOperator
|
|
87
|
+
| NumberOperator
|
|
88
|
+
| BooleanOperator
|
|
89
|
+
| DateOperator
|
|
90
|
+
| ArrayOperator,
|
|
83
91
|
) -> None:
|
|
84
92
|
self.operator = operator
|
|
85
93
|
|
|
@@ -144,9 +152,7 @@ class NoPropertySelected(QueryBuilderError):
|
|
|
144
152
|
|
|
145
153
|
class EmptyOrGroupError(QueryBuilderError):
|
|
146
154
|
def __init__(self) -> None:
|
|
147
|
-
message = (
|
|
148
|
-
"Cannot create an OR group with no conditions. Add at least one filter condition before using .or_where()"
|
|
149
|
-
)
|
|
155
|
+
message = "Cannot create an OR group with no conditions. Add at least one filter condition before using .or_where()"
|
|
150
156
|
super().__init__(message)
|
|
151
157
|
|
|
152
158
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import difflib
|
|
2
2
|
|
|
3
|
-
from notionary.exceptions.base import
|
|
3
|
+
from notionary.exceptions.base import NotionaryException
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class DataSourcePropertyNotFound(
|
|
6
|
+
class DataSourcePropertyNotFound(NotionaryException):
|
|
7
7
|
def __init__(
|
|
8
8
|
self,
|
|
9
9
|
property_name: str,
|
|
@@ -28,7 +28,9 @@ class DataSourcePropertyNotFound(NotionaryError):
|
|
|
28
28
|
super().__init__(message)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class DataSourcePropertyTypeError(
|
|
32
|
-
def __init__(
|
|
31
|
+
class DataSourcePropertyTypeError(NotionaryException):
|
|
32
|
+
def __init__(
|
|
33
|
+
self, property_name: str, expected_type: str, actual_type: str
|
|
34
|
+
) -> None:
|
|
33
35
|
message = f"Property '{property_name}' has the wrong type. Expected: '{expected_type}', found: '{actual_type}'."
|
|
34
36
|
super().__init__(message)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from notionary.exceptions.base import NotionaryException
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class UnsupportedFileTypeException(NotionaryException):
|
|
5
|
+
def __init__(
|
|
6
|
+
self,
|
|
7
|
+
extension: str,
|
|
8
|
+
filename: str,
|
|
9
|
+
supported_extensions_by_category: dict[str, list[str]],
|
|
10
|
+
):
|
|
11
|
+
supported_exts = []
|
|
12
|
+
for category, extensions in supported_extensions_by_category.items():
|
|
13
|
+
supported_exts.append(f"{category}: {', '.join(extensions[:5])}...")
|
|
14
|
+
|
|
15
|
+
supported_info = "\n ".join(supported_exts)
|
|
16
|
+
super().__init__(
|
|
17
|
+
f"File '{filename}' has unsupported extension '{extension}'.\n"
|
|
18
|
+
f"Supported file types by category:\n {supported_info}"
|
|
19
|
+
)
|
|
20
|
+
self.extension = extension
|
|
21
|
+
self.filename = filename
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class NoFileExtensionException(NotionaryException):
|
|
25
|
+
def __init__(self, filename: str):
|
|
26
|
+
super().__init__(
|
|
27
|
+
f"File '{filename}' has no extension. Files must have a valid extension to determine their type."
|
|
28
|
+
)
|
|
29
|
+
self.filename = filename
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class FileSizeException(NotionaryException):
|
|
33
|
+
def __init__(self, filename: str, file_size_bytes: int, max_size_bytes: int):
|
|
34
|
+
file_size_mb = file_size_bytes / (1024 * 1024)
|
|
35
|
+
max_size_mb = max_size_bytes / (1024 * 1024)
|
|
36
|
+
super().__init__(
|
|
37
|
+
f"File '{filename}' is too large ({file_size_mb:.2f} MB). Maximum allowed size is {max_size_mb:.2f} MB."
|
|
38
|
+
)
|
|
39
|
+
self.filename = filename
|
|
40
|
+
self.file_size_bytes = file_size_bytes
|
|
41
|
+
self.max_size_bytes = max_size_bytes
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class FileNotFoundError(NotionaryException):
|
|
45
|
+
def __init__(self, file_path: str):
|
|
46
|
+
super().__init__(f"File does not exist: {file_path}")
|
|
47
|
+
self.file_path = file_path
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class FilenameTooLongError(NotionaryException):
|
|
51
|
+
def __init__(self, filename: str, filename_bytes: int, max_filename_bytes: int):
|
|
52
|
+
super().__init__(
|
|
53
|
+
f"Filename too long: {filename_bytes} bytes (max {max_filename_bytes}). Filename: {filename}"
|
|
54
|
+
)
|
|
55
|
+
self.filename = filename
|
|
56
|
+
self.filename_bytes = filename_bytes
|
|
57
|
+
self.max_filename_bytes = max_filename_bytes
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class UploadFailedError(NotionaryException):
|
|
61
|
+
def __init__(self, file_upload_id: str, reason: str | None = None):
|
|
62
|
+
message = f"Upload failed for file_upload_id: {file_upload_id}"
|
|
63
|
+
if reason:
|
|
64
|
+
message += f". Reason: {reason}"
|
|
65
|
+
super().__init__(message)
|
|
66
|
+
self.file_upload_id = file_upload_id
|
|
67
|
+
self.reason = reason
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class UploadTimeoutError(NotionaryException):
|
|
71
|
+
def __init__(self, file_upload_id: str, timeout_seconds: int):
|
|
72
|
+
super().__init__(
|
|
73
|
+
f"Upload timeout after {timeout_seconds}s for file_upload_id: {file_upload_id}"
|
|
74
|
+
)
|
|
75
|
+
self.file_upload_id = file_upload_id
|
|
76
|
+
self.timeout_seconds = timeout_seconds
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import difflib
|
|
2
2
|
from typing import ClassVar
|
|
3
3
|
|
|
4
|
-
from notionary.exceptions.base import
|
|
4
|
+
from notionary.exceptions.base import NotionaryException
|
|
5
5
|
from notionary.shared.models.parent import ParentType
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class PagePropertyNotFoundError(
|
|
8
|
+
class PagePropertyNotFoundError(NotionaryException):
|
|
9
9
|
def __init__(
|
|
10
10
|
self,
|
|
11
11
|
page_url: str,
|
|
@@ -31,7 +31,7 @@ class PagePropertyNotFoundError(NotionaryError):
|
|
|
31
31
|
super().__init__(message)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
class PagePropertyTypeError(
|
|
34
|
+
class PagePropertyTypeError(NotionaryException):
|
|
35
35
|
def __init__(
|
|
36
36
|
self,
|
|
37
37
|
property_name: str,
|
|
@@ -41,7 +41,7 @@ class PagePropertyTypeError(NotionaryError):
|
|
|
41
41
|
super().__init__(message)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
class AccessPagePropertyWithoutDataSourceError(
|
|
44
|
+
class AccessPagePropertyWithoutDataSourceError(NotionaryException):
|
|
45
45
|
_PARENT_DESCRIPTIONS: ClassVar[dict[ParentType, str]] = {
|
|
46
46
|
ParentType.WORKSPACE: "the workspace itself",
|
|
47
47
|
ParentType.PAGE_ID: "another page",
|
|
@@ -50,7 +50,9 @@ class AccessPagePropertyWithoutDataSourceError(NotionaryError):
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
def __init__(self, parent_type: ParentType) -> None:
|
|
53
|
-
parent_desc = self._PARENT_DESCRIPTIONS.get(
|
|
53
|
+
parent_desc = self._PARENT_DESCRIPTIONS.get(
|
|
54
|
+
parent_type, f"its parent type is '{parent_type}'"
|
|
55
|
+
)
|
|
54
56
|
message = (
|
|
55
57
|
f"Cannot access properties other than title because this page's parent is {parent_desc}. "
|
|
56
58
|
"To use operations like property reading/writing, you need to use a page whose parent is a data source."
|
notionary/exceptions/search.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
from notionary.exceptions.base import
|
|
1
|
+
from notionary.exceptions.base import NotionaryException
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class EntityNotFound(
|
|
5
|
-
def __init__(
|
|
4
|
+
class EntityNotFound(NotionaryException):
|
|
5
|
+
def __init__(
|
|
6
|
+
self, entity_type: str, query: str, available_titles: list[str] | None = None
|
|
7
|
+
) -> None:
|
|
6
8
|
self.entity_type = entity_type
|
|
7
9
|
self.query = query
|
|
8
10
|
self.available_titles = available_titles or []
|
|
@@ -33,15 +35,17 @@ class DatabaseNotFound(EntityNotFound):
|
|
|
33
35
|
super().__init__("database", query, available_titles)
|
|
34
36
|
|
|
35
37
|
|
|
36
|
-
class NoUsersInWorkspace(
|
|
38
|
+
class NoUsersInWorkspace(NotionaryException):
|
|
37
39
|
def __init__(self, user_type: str) -> None:
|
|
38
40
|
self.user_type = user_type
|
|
39
41
|
message = f"No '{user_type}' users found in the workspace."
|
|
40
42
|
super().__init__(message)
|
|
41
43
|
|
|
42
44
|
|
|
43
|
-
class UserNotFound(
|
|
44
|
-
def __init__(
|
|
45
|
+
class UserNotFound(NotionaryException):
|
|
46
|
+
def __init__(
|
|
47
|
+
self, user_type: str, query: str, available_names: list[str] | None = None
|
|
48
|
+
) -> None:
|
|
45
49
|
self.user_type = user_type
|
|
46
50
|
self.query = query
|
|
47
51
|
self.available_names = available_names or []
|