notionary 0.1.5__py3-none-any.whl → 0.1.7__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/core/database/notion_database_manager.py +146 -232
- notionary/core/database/notion_database_manager_factory.py +9 -52
- notionary/core/database/notion_database_schema.py +1 -314
- notionary/core/notion_client.py +2 -10
- notionary/core/page/{page_content_manager.py → content/page_content_manager.py} +0 -1
- notionary/core/page/metadata/metadata_editor.py +109 -0
- notionary/core/page/metadata/notion_icon_manager.py +46 -0
- notionary/core/page/metadata/notion_page_cover_manager.py +48 -0
- notionary/core/page/notion_page_manager.py +230 -49
- notionary/core/page/properites/database_property_service.py +330 -0
- notionary/core/page/properites/page_property_manager.py +146 -0
- notionary/core/page/{property_formatter.py → properites/property_formatter.py} +19 -20
- notionary/core/page/properites/property_operation_result.py +103 -0
- notionary/core/page/properites/property_value_extractor.py +46 -0
- notionary/core/page/relations/notion_page_relation_manager.py +364 -0
- notionary/core/page/relations/notion_page_title_resolver.py +43 -0
- notionary/core/page/relations/page_database_relation.py +70 -0
- notionary/core/page/relations/relation_operation_result.py +135 -0
- notionary/util/{uuid_utils.py → page_id_utils.py} +15 -0
- {notionary-0.1.5.dist-info → notionary-0.1.7.dist-info}/METADATA +1 -1
- {notionary-0.1.5.dist-info → notionary-0.1.7.dist-info}/RECORD +24 -18
- notionary/core/database/database_query_service.py +0 -73
- notionary/core/database/database_schema_service.py +0 -57
- notionary/core/database/notion_database_writer.py +0 -390
- notionary/core/database/page_service.py +0 -161
- notionary/core/page/meta_data/metadata_editor.py +0 -37
- {notionary-0.1.5.dist-info → notionary-0.1.7.dist-info}/WHEEL +0 -0
- {notionary-0.1.5.dist-info → notionary-0.1.7.dist-info}/licenses/LICENSE +0 -0
- {notionary-0.1.5.dist-info → notionary-0.1.7.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
notionary/__init__.py,sha256=5T16clJlSHFsopcPUnkGrEo8spNDUQ0i-O00UEF7nR8,320
|
2
|
-
notionary/core/notion_client.py,sha256=
|
2
|
+
notionary/core/notion_client.py,sha256=9o9-Ki1homkSbM1C51nsaAzVPMt2d4r8cPzoX3NK_HQ,4495
|
3
3
|
notionary/core/converters/__init__.py,sha256=GOUehJbe4BKHtec1MqL1YGu3AX8zFtkwSZfhYkY5-P0,1798
|
4
4
|
notionary/core/converters/markdown_to_notion_converter.py,sha256=PGtg4v5lUvkXXl1Y8E6a3Mf8hEfxfhBrslPs_H_Lq_E,16564
|
5
5
|
notionary/core/converters/notion_to_markdown_converter.py,sha256=c8GyWX8-UrNfRDk7OOBKbSEb5qOwljUCwI6g5risO2c,1287
|
@@ -22,25 +22,31 @@ notionary/core/converters/elements/video_element.py,sha256=xrBLY3e_SgKNamItZkfPN
|
|
22
22
|
notionary/core/converters/registry/block_element_registry.py,sha256=0dpRFMM67UVmXRMP4-Ubc_uCZCVVmRKgxPpueCeknjw,8619
|
23
23
|
notionary/core/converters/registry/block_element_registry_builder.py,sha256=yTV1GPKAN7o65r9jHIqPeBCw0ICdaUZnRC5JKNwpRq4,9227
|
24
24
|
notionary/core/database/database_info_service.py,sha256=58k7om0UXP8w0jCJHewccG5UbOvELMBAbQvXOm7F1OM,1341
|
25
|
-
notionary/core/database/
|
26
|
-
notionary/core/database/
|
27
|
-
notionary/core/database/
|
28
|
-
notionary/core/database/notion_database_manager_factory.py,sha256=jYQeoWV4VKyfCkbxCMVf0aeShfXDvE2EVTs3Jr--Ro8,8285
|
29
|
-
notionary/core/database/notion_database_schema.py,sha256=OtAsKzga7eiWzUa4AasNO2MBOTlQERQ_9Gk22Kc6f64,12599
|
30
|
-
notionary/core/database/notion_database_writer.py,sha256=qpKOSDLI89GWL1kDnzLKSY5GVIzQHVYAWUl12_n-nwU,13651
|
31
|
-
notionary/core/database/page_service.py,sha256=NzKCU2G-mnmqOitNWCJ6jOr0HSv1vPi1-ScSruvFdqg,5190
|
25
|
+
notionary/core/database/notion_database_manager.py,sha256=cEQHf8bTcgA3hLMgsbMGSXhCmccmxWLQ6oOJiINR3ac,8257
|
26
|
+
notionary/core/database/notion_database_manager_factory.py,sha256=SoWUiM5zdajmR1ppYHTdPgHrdZbwuTMdoXW3_tBffyU,6831
|
27
|
+
notionary/core/database/notion_database_schema.py,sha256=WUIjG7I5kusk4GOOdmVSHIKc2Z8SeOgJ1FuGpTn4avQ,3304
|
32
28
|
notionary/core/database/models/page_result.py,sha256=Vmm5_oYpYAkIIJVoTd1ZZGloeC3cmFLMYP255mAmtaw,233
|
33
|
-
notionary/core/page/notion_page_manager.py,sha256=
|
34
|
-
notionary/core/page/page_content_manager.py,sha256=
|
35
|
-
notionary/core/page/
|
36
|
-
notionary/core/page/
|
29
|
+
notionary/core/page/notion_page_manager.py,sha256=NH4mNZ9jgRxmc3gay1ymG0Qcc5k_YX9eSkCMUnB9ghw,13247
|
30
|
+
notionary/core/page/content/page_content_manager.py,sha256=CZGb8vXWADxwo_xBrZ7mmKEW_HSFhlVNjOgWMfYgGJc,3142
|
31
|
+
notionary/core/page/metadata/metadata_editor.py,sha256=U3Ff9GRk28dqT9M1xsl6Q3Cj47-hB1n2pNJzeDXy4ks,4938
|
32
|
+
notionary/core/page/metadata/notion_icon_manager.py,sha256=v9pUG61TOT8x9UzDqBtQW6S5XQzWostq7IwrURnWvF4,1499
|
33
|
+
notionary/core/page/metadata/notion_page_cover_manager.py,sha256=nDWXeEztKyPscq5dRxIZ6d6IqV7E3vR-Qg1N8KzP_fo,1831
|
34
|
+
notionary/core/page/properites/database_property_service.py,sha256=z_HTt_HdB75ffYW5XNwfthZrjLEBXYqKrrK-iGHblek,12073
|
35
|
+
notionary/core/page/properites/page_property_manager.py,sha256=jMiSt9uzr9bKXYhZMg60LVLewp03OFYCeD_qQhKmFT0,6806
|
36
|
+
notionary/core/page/properites/property_formatter.py,sha256=N7GGf-ecUuMLvgt5T_KxabjmvUN7uJrMYFCL7438AZo,3665
|
37
|
+
notionary/core/page/properites/property_operation_result.py,sha256=BVje4SnWf2EdWQYH8sv_6rGd2dL0Owsixfn9SuJY0bk,3961
|
38
|
+
notionary/core/page/properites/property_value_extractor.py,sha256=IG8hKon83CZJ0zYJ-EtgHd2wbjoKOHdA3jB2vmR50Mw,2035
|
39
|
+
notionary/core/page/relations/notion_page_relation_manager.py,sha256=EHavK75Semzh8d7edI1ubh0SJyD8E0loNWVIsfxGAY4,12685
|
40
|
+
notionary/core/page/relations/notion_page_title_resolver.py,sha256=bV0ecP2dikr3vbTEXXsx_4jEtQtpQAHvG-wulASqj3o,1679
|
41
|
+
notionary/core/page/relations/page_database_relation.py,sha256=2WO1HFyIMQwgYoxvxBDUa_iTnJu-Y3Wkzy4JGJ4loME,2420
|
42
|
+
notionary/core/page/relations/relation_operation_result.py,sha256=XkO4rK0ha_FRsfq_Vlwp4a2cE-dGVPBrVxCXOlWqfwk,5258
|
37
43
|
notionary/exceptions/database_exceptions.py,sha256=I-Tx6bYRLpi5pjGPtbT-Mqxvz3BFgYTiuZxknJeLxtI,2638
|
38
44
|
notionary/exceptions/page_creation_exception.py,sha256=4v7IuZD6GsQLrqhDLriGjuG3ML638gAO53zDCrLePuU,281
|
39
45
|
notionary/util/logging_mixin.py,sha256=fKsx9t90bwvL74ZX3dU-sXdC4TZCQyO6qU9I8txkw_U,1369
|
46
|
+
notionary/util/page_id_utils.py,sha256=vgCEp6BdsSJuEtLZVjrRAU9p6moLW-vymM7va8fhErI,1220
|
40
47
|
notionary/util/singleton_decorator.py,sha256=GTNMfIlVNRUVMw_c88xqd12-DcqZJjmyidN54yqiNVw,472
|
41
|
-
notionary/
|
42
|
-
notionary-0.1.
|
43
|
-
notionary-0.1.
|
44
|
-
notionary-0.1.
|
45
|
-
notionary-0.1.
|
46
|
-
notionary-0.1.5.dist-info/RECORD,,
|
48
|
+
notionary-0.1.7.dist-info/licenses/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
|
49
|
+
notionary-0.1.7.dist-info/METADATA,sha256=l0WogkR1uSHB6R6ZMCQPIlE4ajYyQ9HfnUDbccNYYfg,6153
|
50
|
+
notionary-0.1.7.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
51
|
+
notionary-0.1.7.dist-info/top_level.txt,sha256=fhONa6BMHQXqthx5PanWGbPL0b8rdFqhrJKVLf_adSs,10
|
52
|
+
notionary-0.1.7.dist-info/RECORD,,
|
@@ -1,73 +0,0 @@
|
|
1
|
-
from typing import Any, AsyncGenerator, Dict, List, Optional
|
2
|
-
from notionary.core.database.notion_database_schema import NotionDatabaseSchema
|
3
|
-
from notionary.core.page.notion_page_manager import NotionPageManager
|
4
|
-
|
5
|
-
|
6
|
-
class DatabaseQueryService:
|
7
|
-
"""Service für Datenbankabfragen und Iterations"""
|
8
|
-
|
9
|
-
def __init__(self, schema: NotionDatabaseSchema):
|
10
|
-
self._schema = schema
|
11
|
-
|
12
|
-
async def get_pages(
|
13
|
-
self,
|
14
|
-
database_id: str,
|
15
|
-
limit: int = 100,
|
16
|
-
filter_conditions: Optional[Dict[str, Any]] = None,
|
17
|
-
sorts: Optional[List[Dict[str, Any]]] = None,
|
18
|
-
) -> List[NotionPageManager]:
|
19
|
-
"""
|
20
|
-
Get all pages from the database.
|
21
|
-
|
22
|
-
Args:
|
23
|
-
database_id: The database ID to query
|
24
|
-
limit: Maximum number of pages to retrieve
|
25
|
-
filter_conditions: Optional filter to apply to the database query
|
26
|
-
sorts: Optional sort instructions for the database query
|
27
|
-
|
28
|
-
Returns:
|
29
|
-
List of NotionPageManager instances for each page
|
30
|
-
"""
|
31
|
-
pages: List[NotionPageManager] = []
|
32
|
-
count = 0
|
33
|
-
|
34
|
-
async for page in self.iter_pages(
|
35
|
-
database_id,
|
36
|
-
page_size=min(limit, 100),
|
37
|
-
filter_conditions=filter_conditions,
|
38
|
-
sorts=sorts,
|
39
|
-
):
|
40
|
-
pages.append(page)
|
41
|
-
count += 1
|
42
|
-
|
43
|
-
if count >= limit:
|
44
|
-
break
|
45
|
-
|
46
|
-
return pages
|
47
|
-
|
48
|
-
async def iter_pages(
|
49
|
-
self,
|
50
|
-
database_id: str,
|
51
|
-
page_size: int = 100,
|
52
|
-
filter_conditions: Optional[Dict[str, Any]] = None,
|
53
|
-
sorts: Optional[List[Dict[str, Any]]] = None,
|
54
|
-
) -> AsyncGenerator[NotionPageManager, None]:
|
55
|
-
"""
|
56
|
-
Asynchronous generator that yields pages from the database.
|
57
|
-
|
58
|
-
Args:
|
59
|
-
database_id: The database ID to query
|
60
|
-
page_size: Number of pages to fetch per request
|
61
|
-
filter_conditions: Optional filter to apply to the database query
|
62
|
-
sorts: Optional sort instructions for the database query
|
63
|
-
|
64
|
-
Yields:
|
65
|
-
NotionPageManager instances for each page
|
66
|
-
"""
|
67
|
-
async for page_manager in self._schema.iter_database_pages(
|
68
|
-
database_id=database_id,
|
69
|
-
page_size=page_size,
|
70
|
-
filter_conditions=filter_conditions,
|
71
|
-
sorts=sorts,
|
72
|
-
):
|
73
|
-
yield page_manager
|
@@ -1,57 +0,0 @@
|
|
1
|
-
from typing import Dict, List
|
2
|
-
from notionary.core.database.notion_database_schema import NotionDatabaseSchema
|
3
|
-
|
4
|
-
|
5
|
-
class DatabaseSchemaService:
|
6
|
-
"""Service für den Zugriff auf Datenbankschema-Informationen"""
|
7
|
-
|
8
|
-
def __init__(self, schema: NotionDatabaseSchema):
|
9
|
-
self._schema = schema
|
10
|
-
|
11
|
-
async def get_property_types(self) -> Dict[str, str]:
|
12
|
-
"""
|
13
|
-
Get all property types for the database.
|
14
|
-
|
15
|
-
Returns:
|
16
|
-
Dictionary mapping property names to their types
|
17
|
-
"""
|
18
|
-
return await self._schema.get_property_types()
|
19
|
-
|
20
|
-
async def get_select_options(self, property_name: str) -> List[Dict[str, str]]:
|
21
|
-
"""
|
22
|
-
Get options for a select, multi-select, or status property.
|
23
|
-
|
24
|
-
Args:
|
25
|
-
property_name: Name of the property
|
26
|
-
|
27
|
-
Returns:
|
28
|
-
List of select options with name, id, and color (if available)
|
29
|
-
"""
|
30
|
-
options = await self._schema.get_select_options(property_name)
|
31
|
-
return [
|
32
|
-
{
|
33
|
-
"name": option.get("name", ""),
|
34
|
-
"id": option.get("id", ""),
|
35
|
-
"color": option.get("color", ""),
|
36
|
-
}
|
37
|
-
for option in options
|
38
|
-
]
|
39
|
-
|
40
|
-
async def get_relation_options(
|
41
|
-
self, property_name: str, limit: int = 100
|
42
|
-
) -> List[Dict[str, str]]:
|
43
|
-
"""
|
44
|
-
Get available options for a relation property.
|
45
|
-
|
46
|
-
Args:
|
47
|
-
property_name: Name of the relation property
|
48
|
-
limit: Maximum number of options to retrieve
|
49
|
-
|
50
|
-
Returns:
|
51
|
-
List of relation options with id and title
|
52
|
-
"""
|
53
|
-
options = await self._schema.get_relation_options(property_name, limit)
|
54
|
-
return [
|
55
|
-
{"id": option.get("id", ""), "title": option.get("title", "")}
|
56
|
-
for option in options
|
57
|
-
]
|
@@ -1,390 +0,0 @@
|
|
1
|
-
from typing import Any, Dict, List, Optional, Union, TypedDict, cast
|
2
|
-
from notionary.core.database.notion_database_schema import NotionDatabaseSchema
|
3
|
-
from notionary.core.notion_client import NotionClient
|
4
|
-
from notionary.core.page.property_formatter import NotionPropertyFormatter
|
5
|
-
from notionary.util.logging_mixin import LoggingMixin
|
6
|
-
|
7
|
-
|
8
|
-
class NotionRelationItem(TypedDict):
|
9
|
-
id: str
|
10
|
-
|
11
|
-
|
12
|
-
class NotionRelationProperty(TypedDict):
|
13
|
-
relation: List[NotionRelationItem]
|
14
|
-
|
15
|
-
|
16
|
-
class NotionFormattedValue(TypedDict, total=False):
|
17
|
-
title: List[Dict[str, Any]]
|
18
|
-
rich_text: List[Dict[str, Any]]
|
19
|
-
select: Dict[str, str]
|
20
|
-
multi_select: List[Dict[str, str]]
|
21
|
-
relation: List[NotionRelationItem]
|
22
|
-
number: Union[int, float]
|
23
|
-
date: Dict[str, str]
|
24
|
-
checkbox: bool
|
25
|
-
url: str
|
26
|
-
email: str
|
27
|
-
phone_number: str
|
28
|
-
|
29
|
-
|
30
|
-
class PageCreationResponse(TypedDict):
|
31
|
-
id: str
|
32
|
-
parent: Dict[str, str]
|
33
|
-
properties: Dict[str, Any]
|
34
|
-
|
35
|
-
|
36
|
-
class NotionRelationHandler(LoggingMixin):
|
37
|
-
"""
|
38
|
-
Handler for managing relations in Notion databases.
|
39
|
-
Provides a unified interface for working with relations.
|
40
|
-
"""
|
41
|
-
|
42
|
-
def __init__(self, client: NotionClient, db_schema: NotionDatabaseSchema) -> None:
|
43
|
-
self._client = client
|
44
|
-
self._db_schema = db_schema
|
45
|
-
self._formatter = NotionPropertyFormatter()
|
46
|
-
|
47
|
-
async def find_relation_by_title(
|
48
|
-
self, database_id: str, relation_prop_name: str, title: str
|
49
|
-
) -> Optional[str]:
|
50
|
-
"""
|
51
|
-
Finds a relation ID based on the title of the entry in the target database.
|
52
|
-
"""
|
53
|
-
target_db_id = await self._db_schema.get_relation_database_id(
|
54
|
-
relation_prop_name
|
55
|
-
)
|
56
|
-
if not target_db_id:
|
57
|
-
self.logger.error(
|
58
|
-
"No target database found for relation '%s' in database %s",
|
59
|
-
relation_prop_name,
|
60
|
-
database_id,
|
61
|
-
)
|
62
|
-
return None
|
63
|
-
|
64
|
-
options = await self._db_schema.get_relation_options(relation_prop_name)
|
65
|
-
|
66
|
-
for option in options:
|
67
|
-
if option["title"].lower() == title.lower():
|
68
|
-
self.logger.debug("Relation entry '%s' found: %s", title, option["id"])
|
69
|
-
return option["id"]
|
70
|
-
|
71
|
-
self.logger.warning("Relation entry '%s' not found", title)
|
72
|
-
return None
|
73
|
-
|
74
|
-
async def _get_title_properties(
|
75
|
-
self, database_id: str, title: str
|
76
|
-
) -> Optional[Dict[str, NotionFormattedValue]]:
|
77
|
-
"""
|
78
|
-
Determines the title property for a database and formats the value.
|
79
|
-
"""
|
80
|
-
if not await self._db_schema.load():
|
81
|
-
self.logger.error("Could not load database schema for %s", database_id)
|
82
|
-
return None
|
83
|
-
|
84
|
-
property_types = await self._db_schema.get_property_types()
|
85
|
-
|
86
|
-
title_prop_name: Optional[str] = None
|
87
|
-
for name, prop_type in property_types.items():
|
88
|
-
if prop_type == "title":
|
89
|
-
title_prop_name = name
|
90
|
-
break
|
91
|
-
|
92
|
-
if not title_prop_name:
|
93
|
-
self.logger.error("No title property found in database %s", database_id)
|
94
|
-
return None
|
95
|
-
|
96
|
-
formatted_title = self._formatter.format_value("title", title)
|
97
|
-
if not formatted_title:
|
98
|
-
self.logger.error("Could not format title '%s'", title)
|
99
|
-
return None
|
100
|
-
|
101
|
-
return {title_prop_name: cast(NotionFormattedValue, formatted_title)}
|
102
|
-
|
103
|
-
|
104
|
-
class DatabaseWritter(LoggingMixin):
|
105
|
-
"""
|
106
|
-
Enhanced class for creating and updating pages in Notion databases.
|
107
|
-
Supports both simple properties and relations.
|
108
|
-
"""
|
109
|
-
|
110
|
-
def __init__(
|
111
|
-
self, client: NotionClient, db_schema: Optional[NotionDatabaseSchema] = None
|
112
|
-
) -> None:
|
113
|
-
"""
|
114
|
-
Initialize with a NotionClient and optionally a NotionDatabaseSchema.
|
115
|
-
|
116
|
-
Args:
|
117
|
-
client: The Notion API client
|
118
|
-
db_schema: Optional database schema instance
|
119
|
-
"""
|
120
|
-
self._client = client
|
121
|
-
self._formatter = NotionPropertyFormatter()
|
122
|
-
|
123
|
-
self._active_schema: Optional[NotionDatabaseSchema] = db_schema
|
124
|
-
self._relation_handler: Optional[NotionRelationHandler] = None
|
125
|
-
|
126
|
-
if db_schema:
|
127
|
-
self._relation_handler = NotionRelationHandler(client, db_schema)
|
128
|
-
|
129
|
-
async def _ensure_schema_for_database(self, database_id: str) -> bool:
|
130
|
-
"""
|
131
|
-
Stellt sicher, dass ein Schema für die angegebene Datenbank geladen ist.
|
132
|
-
|
133
|
-
Args:
|
134
|
-
database_id: ID der Datenbank
|
135
|
-
|
136
|
-
Returns:
|
137
|
-
True, wenn das Schema erfolgreich geladen wurde
|
138
|
-
"""
|
139
|
-
if self._active_schema and self._active_schema.database_id == database_id:
|
140
|
-
return True
|
141
|
-
|
142
|
-
self._active_schema = NotionDatabaseSchema(database_id, self._client)
|
143
|
-
self._relation_handler = NotionRelationHandler(
|
144
|
-
self._client, self._active_schema
|
145
|
-
)
|
146
|
-
|
147
|
-
return await self._active_schema.load()
|
148
|
-
|
149
|
-
async def create_page(
|
150
|
-
self,
|
151
|
-
database_id: str,
|
152
|
-
properties: Dict[str, Any],
|
153
|
-
relations: Optional[Dict[str, Union[str, List[str]]]] = None,
|
154
|
-
) -> Optional[PageCreationResponse]:
|
155
|
-
"""
|
156
|
-
Creates a new page in a database with support for relations.
|
157
|
-
"""
|
158
|
-
# Stelle sicher, dass wir ein Schema für diese Datenbank haben
|
159
|
-
if not await self._ensure_schema_for_database(database_id):
|
160
|
-
self.logger.error("Could not load schema for database %s", database_id)
|
161
|
-
return None
|
162
|
-
|
163
|
-
formatted_props = await self._format_properties(database_id, properties)
|
164
|
-
if not formatted_props:
|
165
|
-
return None
|
166
|
-
|
167
|
-
if relations:
|
168
|
-
relation_props = await self._process_relations(database_id, relations)
|
169
|
-
if relation_props:
|
170
|
-
formatted_props.update(relation_props)
|
171
|
-
|
172
|
-
data: Dict[str, Any] = {
|
173
|
-
"parent": {"database_id": database_id},
|
174
|
-
"properties": formatted_props,
|
175
|
-
}
|
176
|
-
|
177
|
-
result = await self._client.post("pages", data)
|
178
|
-
if not result:
|
179
|
-
self.logger.error("Error creating page in database %s", database_id)
|
180
|
-
return None
|
181
|
-
|
182
|
-
self.logger.info("Page successfully created in database %s", database_id)
|
183
|
-
return cast(PageCreationResponse, result)
|
184
|
-
|
185
|
-
async def update_page(
|
186
|
-
self,
|
187
|
-
page_id: str,
|
188
|
-
properties: Optional[Dict[str, Any]] = None,
|
189
|
-
relations: Optional[Dict[str, Union[str, List[str]]]] = None,
|
190
|
-
) -> Optional[Dict[str, Any]]:
|
191
|
-
"""
|
192
|
-
Updates a page with support for relations.
|
193
|
-
"""
|
194
|
-
page_data = await self._client.get(f"pages/{page_id}")
|
195
|
-
if (
|
196
|
-
not page_data
|
197
|
-
or "parent" not in page_data
|
198
|
-
or "database_id" not in page_data["parent"]
|
199
|
-
):
|
200
|
-
self.logger.error("Could not determine database ID for page %s", page_id)
|
201
|
-
return None
|
202
|
-
|
203
|
-
database_id = page_data["parent"]["database_id"]
|
204
|
-
|
205
|
-
# Stelle sicher, dass wir ein Schema für diese Datenbank haben
|
206
|
-
if not await self._ensure_schema_for_database(database_id):
|
207
|
-
self.logger.error("Could not load schema for database %s", database_id)
|
208
|
-
return None
|
209
|
-
|
210
|
-
if not properties and not relations:
|
211
|
-
self.logger.warning("No properties or relations specified for update")
|
212
|
-
return page_data
|
213
|
-
|
214
|
-
update_props: Dict[str, NotionFormattedValue] = {}
|
215
|
-
|
216
|
-
if properties:
|
217
|
-
formatted_props = await self._format_properties(database_id, properties)
|
218
|
-
if formatted_props:
|
219
|
-
update_props.update(formatted_props)
|
220
|
-
|
221
|
-
if relations:
|
222
|
-
relation_props = await self._process_relations(database_id, relations)
|
223
|
-
if relation_props:
|
224
|
-
update_props.update(relation_props)
|
225
|
-
|
226
|
-
if not update_props:
|
227
|
-
self.logger.warning("No valid properties to update for page %s", page_id)
|
228
|
-
return None
|
229
|
-
|
230
|
-
data = {"properties": update_props}
|
231
|
-
|
232
|
-
result = await self._client.patch(f"pages/{page_id}", data)
|
233
|
-
if not result:
|
234
|
-
self.logger.error("Error updating page %s", page_id)
|
235
|
-
return None
|
236
|
-
|
237
|
-
self.logger.info("Page %s successfully updated", page_id)
|
238
|
-
return result
|
239
|
-
|
240
|
-
async def delete_page(self, page_id: str) -> bool:
|
241
|
-
"""
|
242
|
-
Deletes a page (archives it in Notion).
|
243
|
-
"""
|
244
|
-
data = {"archived": True}
|
245
|
-
|
246
|
-
result = await self._client.patch(f"pages/{page_id}", data)
|
247
|
-
if not result:
|
248
|
-
self.logger.error("Error deleting page %s", page_id)
|
249
|
-
return False
|
250
|
-
|
251
|
-
self.logger.info("Page %s successfully deleted (archived)", page_id)
|
252
|
-
return True
|
253
|
-
|
254
|
-
async def _format_properties(
|
255
|
-
self, database_id: str, properties: Dict[str, Any]
|
256
|
-
) -> Optional[Dict[str, NotionFormattedValue]]:
|
257
|
-
"""
|
258
|
-
Formats properties according to their types in the database.
|
259
|
-
"""
|
260
|
-
if not self._active_schema:
|
261
|
-
self.logger.error("No active schema available for database %s", database_id)
|
262
|
-
return None
|
263
|
-
|
264
|
-
property_types = await self._active_schema.get_property_types()
|
265
|
-
if not property_types:
|
266
|
-
self.logger.error(
|
267
|
-
"Could not get property types for database %s", database_id
|
268
|
-
)
|
269
|
-
return None
|
270
|
-
|
271
|
-
formatted_props: Dict[str, NotionFormattedValue] = {}
|
272
|
-
|
273
|
-
for prop_name, value in properties.items():
|
274
|
-
if prop_name not in property_types:
|
275
|
-
self.logger.warning(
|
276
|
-
"Property '%s' does not exist in database %s",
|
277
|
-
prop_name,
|
278
|
-
database_id,
|
279
|
-
)
|
280
|
-
continue
|
281
|
-
|
282
|
-
prop_type = property_types[prop_name]
|
283
|
-
|
284
|
-
formatted_value = self._formatter.format_value(prop_type, value)
|
285
|
-
if formatted_value:
|
286
|
-
formatted_props[prop_name] = cast(NotionFormattedValue, formatted_value)
|
287
|
-
else:
|
288
|
-
self.logger.warning(
|
289
|
-
"Could not format value for property '%s' of type '%s'",
|
290
|
-
prop_name,
|
291
|
-
prop_type,
|
292
|
-
)
|
293
|
-
|
294
|
-
return formatted_props
|
295
|
-
|
296
|
-
async def _process_relations(
|
297
|
-
self, database_id: str, relations: Dict[str, Union[str, List[str]]]
|
298
|
-
) -> Dict[str, NotionRelationProperty]:
|
299
|
-
"""
|
300
|
-
Processes relation properties and converts titles to IDs.
|
301
|
-
"""
|
302
|
-
if not self._relation_handler:
|
303
|
-
self.logger.error("No relation handler available")
|
304
|
-
return {}
|
305
|
-
|
306
|
-
formatted_relations: Dict[str, NotionRelationProperty] = {}
|
307
|
-
property_types = (
|
308
|
-
await self._active_schema.get_property_types()
|
309
|
-
if self._active_schema
|
310
|
-
else {}
|
311
|
-
)
|
312
|
-
|
313
|
-
for prop_name, titles in relations.items():
|
314
|
-
relation_property = await self._process_single_relation(
|
315
|
-
database_id, prop_name, titles, property_types
|
316
|
-
)
|
317
|
-
if relation_property:
|
318
|
-
formatted_relations[prop_name] = relation_property
|
319
|
-
|
320
|
-
return formatted_relations
|
321
|
-
|
322
|
-
async def _process_single_relation(
|
323
|
-
self,
|
324
|
-
database_id: str,
|
325
|
-
prop_name: str,
|
326
|
-
titles: Union[str, List[str]],
|
327
|
-
property_types: Dict[str, str],
|
328
|
-
) -> Optional[NotionRelationProperty]:
|
329
|
-
"""
|
330
|
-
Process a single relation property and convert titles to IDs.
|
331
|
-
|
332
|
-
Args:
|
333
|
-
database_id: The database ID
|
334
|
-
prop_name: The property name
|
335
|
-
titles: The title or list of titles to convert
|
336
|
-
property_types: Dictionary of property types
|
337
|
-
|
338
|
-
Returns:
|
339
|
-
A formatted relation property or None if invalid
|
340
|
-
"""
|
341
|
-
if prop_name not in property_types:
|
342
|
-
self.logger.warning(
|
343
|
-
"Property '%s' does not exist in database %s", prop_name, database_id
|
344
|
-
)
|
345
|
-
return None
|
346
|
-
|
347
|
-
prop_type = property_types[prop_name]
|
348
|
-
if prop_type != "relation":
|
349
|
-
self.logger.warning(
|
350
|
-
"Property '%s' is not a relation (type: %s)", prop_name, prop_type
|
351
|
-
)
|
352
|
-
return None
|
353
|
-
|
354
|
-
title_list: List[str] = [titles] if isinstance(titles, str) else titles
|
355
|
-
relation_ids = await self._get_relation_ids(database_id, prop_name, title_list)
|
356
|
-
|
357
|
-
if not relation_ids:
|
358
|
-
return None
|
359
|
-
|
360
|
-
return {"relation": [{"id": rel_id} for rel_id in relation_ids]}
|
361
|
-
|
362
|
-
async def _get_relation_ids(
|
363
|
-
self, database_id: str, prop_name: str, titles: List[str]
|
364
|
-
) -> List[str]:
|
365
|
-
"""
|
366
|
-
Get relation IDs for a list of titles.
|
367
|
-
|
368
|
-
Args:
|
369
|
-
database_id: The database ID
|
370
|
-
prop_name: The property name
|
371
|
-
titles: List of titles to convert
|
372
|
-
|
373
|
-
Returns:
|
374
|
-
List of relation IDs
|
375
|
-
"""
|
376
|
-
relation_ids: List[str] = []
|
377
|
-
|
378
|
-
for title in titles:
|
379
|
-
relation_id = await self._relation_handler.find_relation_by_title(
|
380
|
-
database_id, prop_name, title
|
381
|
-
)
|
382
|
-
|
383
|
-
if relation_id:
|
384
|
-
relation_ids.append(relation_id)
|
385
|
-
else:
|
386
|
-
self.logger.warning(
|
387
|
-
"Could not find relation ID for '%s' in '%s'", title, prop_name
|
388
|
-
)
|
389
|
-
|
390
|
-
return relation_ids
|