notionary 0.1.10__py3-none-any.whl → 0.1.12__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 +13 -2
- notionary/core/converters/elements/audio_element.py +143 -0
- notionary/core/converters/elements/embed_element.py +2 -4
- notionary/core/converters/elements/toggle_element.py +28 -20
- notionary/core/converters/markdown_to_notion_converter.py +70 -109
- notionary/core/converters/registry/block_element_registry.py +2 -6
- notionary/core/converters/registry/block_element_registry_builder.py +2 -0
- notionary/core/database/database_discovery.py +140 -0
- notionary/core/database/notion_database_manager.py +26 -49
- notionary/core/database/notion_database_manager_factory.py +10 -4
- notionary/core/notion_client.py +4 -2
- notionary/core/page/content/notion_page_content_chunker.py +84 -0
- notionary/core/page/content/page_content_manager.py +26 -8
- notionary/core/page/metadata/metadata_editor.py +57 -44
- notionary/core/page/metadata/notion_icon_manager.py +9 -11
- notionary/core/page/metadata/notion_page_cover_manager.py +15 -20
- notionary/core/page/notion_page_manager.py +137 -156
- notionary/core/page/properites/database_property_service.py +114 -98
- notionary/core/page/properites/page_property_manager.py +78 -49
- notionary/core/page/properites/property_formatter.py +1 -1
- notionary/core/page/properites/property_operation_result.py +43 -30
- notionary/core/page/properites/property_value_extractor.py +26 -8
- notionary/core/page/relations/notion_page_relation_manager.py +71 -52
- notionary/core/page/relations/notion_page_title_resolver.py +11 -11
- notionary/core/page/relations/page_database_relation.py +14 -14
- notionary/core/page/relations/relation_operation_result.py +50 -41
- notionary/util/page_id_utils.py +11 -7
- {notionary-0.1.10.dist-info → notionary-0.1.12.dist-info}/METADATA +1 -1
- {notionary-0.1.10.dist-info → notionary-0.1.12.dist-info}/RECORD +32 -30
- notionary/core/database/notion_database_schema.py +0 -104
- {notionary-0.1.10.dist-info → notionary-0.1.12.dist-info}/WHEEL +0 -0
- {notionary-0.1.10.dist-info → notionary-0.1.12.dist-info}/licenses/LICENSE +0 -0
- {notionary-0.1.10.dist-info → notionary-0.1.12.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
from typing import Any, Dict, List, Optional
|
2
2
|
from dataclasses import dataclass
|
3
3
|
|
4
|
+
|
4
5
|
@dataclass
|
5
6
|
class PropertyOperationResult:
|
6
7
|
"""
|
7
8
|
Result of a property operation in Notion.
|
8
|
-
|
9
|
+
|
9
10
|
Attributes:
|
10
11
|
success: Whether the operation was successful
|
11
12
|
property_name: Name of the affected property
|
@@ -14,90 +15,102 @@ class PropertyOperationResult:
|
|
14
15
|
available_options: Available options for select-like properties
|
15
16
|
api_response: The original API response
|
16
17
|
"""
|
18
|
+
|
17
19
|
success: bool
|
18
20
|
property_name: str
|
19
21
|
value: Optional[Any] = None
|
20
22
|
error: Optional[str] = None
|
21
23
|
available_options: Optional[List[str]] = None
|
22
24
|
api_response: Optional[Dict[str, Any]] = None
|
23
|
-
|
25
|
+
|
24
26
|
# Common error messages
|
25
27
|
NO_API_RESPONSE = "Failed to set property (no API response)"
|
26
28
|
RELATION_TYPE_ERROR = "Property '{}' is of type 'relation'. Relations must be set using the RelationManager."
|
27
|
-
|
29
|
+
|
28
30
|
@classmethod
|
29
|
-
def from_success(
|
31
|
+
def from_success(
|
32
|
+
cls, property_name: str, value: Any, api_response: Dict[str, Any]
|
33
|
+
) -> "PropertyOperationResult":
|
30
34
|
"""Creates a success result."""
|
31
35
|
return cls(
|
32
|
-
success=True,
|
33
|
-
property_name=property_name,
|
34
|
-
value=value,
|
35
|
-
api_response=api_response
|
36
|
+
success=True,
|
37
|
+
property_name=property_name,
|
38
|
+
value=value,
|
39
|
+
api_response=api_response,
|
36
40
|
)
|
37
|
-
|
41
|
+
|
38
42
|
@classmethod
|
39
|
-
def from_error(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
def from_error(
|
44
|
+
cls,
|
45
|
+
property_name: str,
|
46
|
+
error: str,
|
47
|
+
value: Optional[Any] = None,
|
48
|
+
available_options: Optional[List[str]] = None,
|
49
|
+
) -> "PropertyOperationResult":
|
43
50
|
"""Creates an error result."""
|
44
51
|
return cls(
|
45
52
|
success=False,
|
46
53
|
property_name=property_name,
|
47
54
|
value=value,
|
48
55
|
error=error,
|
49
|
-
available_options=available_options or []
|
56
|
+
available_options=available_options or [],
|
50
57
|
)
|
51
|
-
|
58
|
+
|
52
59
|
@classmethod
|
53
|
-
def from_api_error(
|
60
|
+
def from_api_error(
|
61
|
+
cls, property_name: str, api_response: Dict[str, Any]
|
62
|
+
) -> "PropertyOperationResult":
|
54
63
|
"""Creates a result from an API error response."""
|
55
64
|
return cls(
|
56
65
|
success=False,
|
57
66
|
property_name=property_name,
|
58
67
|
error=api_response.get("message", "Unknown API error"),
|
59
|
-
api_response=api_response
|
68
|
+
api_response=api_response,
|
60
69
|
)
|
61
|
-
|
70
|
+
|
62
71
|
@classmethod
|
63
|
-
def from_no_api_response(
|
72
|
+
def from_no_api_response(
|
73
|
+
cls, property_name: str, value: Optional[Any] = None
|
74
|
+
) -> "PropertyOperationResult":
|
64
75
|
"""Creates a standardized result for missing API responses."""
|
65
76
|
return cls.from_error(property_name, cls.NO_API_RESPONSE, value)
|
66
77
|
|
67
78
|
@classmethod
|
68
|
-
def from_relation_type_error(
|
79
|
+
def from_relation_type_error(
|
80
|
+
cls, property_name: str, value: Optional[Any] = None
|
81
|
+
) -> "PropertyOperationResult":
|
69
82
|
"""Creates a standardized error result for relation type properties."""
|
70
83
|
error_msg = cls.RELATION_TYPE_ERROR.format(property_name)
|
71
84
|
return cls.from_error(property_name, error_msg, value)
|
72
|
-
|
85
|
+
|
73
86
|
def to_dict(self) -> Dict[str, Any]:
|
74
87
|
"""Converts the result to a dictionary."""
|
75
88
|
result = {
|
76
89
|
"success": self.success,
|
77
90
|
"property": self.property_name,
|
78
91
|
}
|
79
|
-
|
92
|
+
|
80
93
|
if self.value is not None:
|
81
94
|
result["value"] = self.value
|
82
|
-
|
95
|
+
|
83
96
|
if not self.success:
|
84
97
|
result["error"] = self.error
|
85
|
-
|
98
|
+
|
86
99
|
if self.available_options:
|
87
100
|
result["available_options"] = self.available_options
|
88
|
-
|
101
|
+
|
89
102
|
if self.api_response:
|
90
103
|
result["api_response"] = self.api_response
|
91
|
-
|
104
|
+
|
92
105
|
return result
|
93
|
-
|
106
|
+
|
94
107
|
def __str__(self) -> str:
|
95
108
|
"""String representation of the result."""
|
96
109
|
if self.success:
|
97
110
|
return f"Success: Property '{self.property_name}' set to '{self.value}'"
|
98
|
-
|
111
|
+
|
99
112
|
if self.available_options:
|
100
113
|
options = "', '".join(self.available_options)
|
101
114
|
return f"Error: {self.error}\nAvailable options for '{self.property_name}': '{options}'"
|
102
|
-
|
103
|
-
return f"Error: {self.error}"
|
115
|
+
|
116
|
+
return f"Error: {self.error}"
|
@@ -10,19 +10,33 @@ class PropertyValueExtractor:
|
|
10
10
|
self,
|
11
11
|
property_name: str,
|
12
12
|
prop_data: dict,
|
13
|
-
relation_resolver: Callable[[str], Awaitable[Any]]
|
13
|
+
relation_resolver: Callable[[str], Awaitable[Any]],
|
14
14
|
) -> Any:
|
15
15
|
prop_type = prop_data.get("type")
|
16
16
|
if not prop_type:
|
17
17
|
return None
|
18
18
|
|
19
19
|
handlers: dict[str, Callable[[], Awaitable[Any] | Any]] = {
|
20
|
-
"title": lambda: "".join(
|
21
|
-
|
20
|
+
"title": lambda: "".join(
|
21
|
+
t.get("plain_text", "") for t in prop_data.get("title", [])
|
22
|
+
),
|
23
|
+
"rich_text": lambda: "".join(
|
24
|
+
t.get("plain_text", "") for t in prop_data.get("rich_text", [])
|
25
|
+
),
|
22
26
|
"number": lambda: prop_data.get("number"),
|
23
|
-
"select": lambda:
|
24
|
-
|
25
|
-
|
27
|
+
"select": lambda: (
|
28
|
+
prop_data.get("select", {}).get("name")
|
29
|
+
if prop_data.get("select")
|
30
|
+
else None
|
31
|
+
),
|
32
|
+
"multi_select": lambda: [
|
33
|
+
o.get("name") for o in prop_data.get("multi_select", [])
|
34
|
+
],
|
35
|
+
"status": lambda: (
|
36
|
+
prop_data.get("status", {}).get("name")
|
37
|
+
if prop_data.get("status")
|
38
|
+
else None
|
39
|
+
),
|
26
40
|
"date": lambda: prop_data.get("date"),
|
27
41
|
"checkbox": lambda: prop_data.get("checkbox"),
|
28
42
|
"url": lambda: prop_data.get("url"),
|
@@ -31,9 +45,13 @@ class PropertyValueExtractor:
|
|
31
45
|
"relation": lambda: relation_resolver(property_name),
|
32
46
|
"people": lambda: [p.get("id") for p in prop_data.get("people", [])],
|
33
47
|
"files": lambda: [
|
34
|
-
|
48
|
+
(
|
49
|
+
f.get("external", {}).get("url")
|
50
|
+
if f.get("type") == "external"
|
51
|
+
else f.get("name")
|
52
|
+
)
|
35
53
|
for f in prop_data.get("files", [])
|
36
|
-
]
|
54
|
+
],
|
37
55
|
}
|
38
56
|
|
39
57
|
handler = handlers.get(prop_type)
|
@@ -1,17 +1,24 @@
|
|
1
1
|
from typing import Any, Dict, List, Optional
|
2
2
|
from notionary.core.notion_client import NotionClient
|
3
|
-
from notionary.core.page.relations.notion_page_title_resolver import
|
4
|
-
|
3
|
+
from notionary.core.page.relations.notion_page_title_resolver import (
|
4
|
+
NotionPageTitleResolver,
|
5
|
+
)
|
6
|
+
from notionary.core.page.relations.relation_operation_result import (
|
7
|
+
RelationOperationResult,
|
8
|
+
)
|
5
9
|
from notionary.util.logging_mixin import LoggingMixin
|
6
10
|
from notionary.util.page_id_utils import is_valid_uuid
|
7
11
|
|
12
|
+
|
8
13
|
class NotionRelationManager(LoggingMixin):
|
9
14
|
"""
|
10
15
|
Manager for relation properties of a Notion page.
|
11
16
|
Manages links between pages and loads available relation options.
|
12
17
|
"""
|
13
18
|
|
14
|
-
def __init__(
|
19
|
+
def __init__(
|
20
|
+
self, page_id: str, client: NotionClient, database_id: Optional[str] = None
|
21
|
+
):
|
15
22
|
"""
|
16
23
|
Initializes the relation manager.
|
17
24
|
|
@@ -75,7 +82,8 @@ class NotionRelationManager(LoggingMixin):
|
|
75
82
|
properties = await self._get_page_properties()
|
76
83
|
|
77
84
|
return [
|
78
|
-
prop_name
|
85
|
+
prop_name
|
86
|
+
for prop_name, prop_data in properties.items()
|
79
87
|
if prop_data.get("type") == "relation"
|
80
88
|
]
|
81
89
|
|
@@ -101,7 +109,9 @@ class NotionRelationManager(LoggingMixin):
|
|
101
109
|
|
102
110
|
return [rel.get("id") for rel in prop_data["relation"]]
|
103
111
|
|
104
|
-
async def get_relation_details(
|
112
|
+
async def get_relation_details(
|
113
|
+
self, property_name: str
|
114
|
+
) -> Optional[Dict[str, Any]]:
|
105
115
|
"""
|
106
116
|
Returns details about the relation property, including the linked database.
|
107
117
|
|
@@ -153,7 +163,9 @@ class NotionRelationManager(LoggingMixin):
|
|
153
163
|
|
154
164
|
return relation_details.get("database_id")
|
155
165
|
|
156
|
-
async def get_relation_options(
|
166
|
+
async def get_relation_options(
|
167
|
+
self, property_name: str, limit: int = 100
|
168
|
+
) -> List[Dict[str, Any]]:
|
157
169
|
"""
|
158
170
|
Returns available options for a relation property.
|
159
171
|
|
@@ -174,7 +186,7 @@ class NotionRelationManager(LoggingMixin):
|
|
174
186
|
f"databases/{related_db_id}/query",
|
175
187
|
{
|
176
188
|
"page_size": limit,
|
177
|
-
}
|
189
|
+
},
|
178
190
|
)
|
179
191
|
|
180
192
|
if not query_result or "results" not in query_result:
|
@@ -186,10 +198,7 @@ class NotionRelationManager(LoggingMixin):
|
|
186
198
|
title = self._extract_title_from_page(page)
|
187
199
|
|
188
200
|
if page_id and title:
|
189
|
-
options.append({
|
190
|
-
"id": page_id,
|
191
|
-
"name": title
|
192
|
-
})
|
201
|
+
options.append({"id": page_id, "name": title})
|
193
202
|
|
194
203
|
return options
|
195
204
|
except Exception as e:
|
@@ -214,11 +223,15 @@ class NotionRelationManager(LoggingMixin):
|
|
214
223
|
for prop_data in properties.values():
|
215
224
|
if prop_data.get("type") == "title" and "title" in prop_data:
|
216
225
|
title_parts = prop_data["title"]
|
217
|
-
return "".join(
|
226
|
+
return "".join(
|
227
|
+
[text_obj.get("plain_text", "") for text_obj in title_parts]
|
228
|
+
)
|
218
229
|
|
219
230
|
return None
|
220
231
|
|
221
|
-
async def add_relation(
|
232
|
+
async def add_relation(
|
233
|
+
self, property_name: str, page_ids: List[str]
|
234
|
+
) -> Optional[Dict[str, Any]]:
|
222
235
|
"""
|
223
236
|
Adds one or more relations.
|
224
237
|
|
@@ -233,18 +246,12 @@ class NotionRelationManager(LoggingMixin):
|
|
233
246
|
|
234
247
|
all_relations = list(set(existing_relations + page_ids))
|
235
248
|
|
236
|
-
relation_payload = {
|
237
|
-
"relation": [{"id": page_id} for page_id in all_relations]
|
238
|
-
}
|
249
|
+
relation_payload = {"relation": [{"id": page_id} for page_id in all_relations]}
|
239
250
|
|
240
251
|
try:
|
241
252
|
result = await self._client.patch(
|
242
253
|
f"pages/{self._page_id}",
|
243
|
-
{
|
244
|
-
"properties": {
|
245
|
-
property_name: relation_payload
|
246
|
-
}
|
247
|
-
},
|
254
|
+
{"properties": {property_name: relation_payload}},
|
248
255
|
)
|
249
256
|
|
250
257
|
self._page_properties = None
|
@@ -254,7 +261,9 @@ class NotionRelationManager(LoggingMixin):
|
|
254
261
|
self.logger.error("Error adding relation: %s", str(e))
|
255
262
|
return None
|
256
263
|
|
257
|
-
async def add_relation_by_name(
|
264
|
+
async def add_relation_by_name(
|
265
|
+
self, property_name: str, page_titles: List[str]
|
266
|
+
) -> RelationOperationResult:
|
258
267
|
"""
|
259
268
|
Adds one or more relations based on page titles.
|
260
269
|
|
@@ -268,9 +277,13 @@ class NotionRelationManager(LoggingMixin):
|
|
268
277
|
found_pages = []
|
269
278
|
not_found_pages = []
|
270
279
|
page_ids = []
|
271
|
-
|
272
|
-
self.logger.info(
|
273
|
-
|
280
|
+
|
281
|
+
self.logger.info(
|
282
|
+
"Attempting to add %d relation(s) to property '%s'",
|
283
|
+
len(page_titles),
|
284
|
+
property_name,
|
285
|
+
)
|
286
|
+
|
274
287
|
for page in page_titles:
|
275
288
|
if is_valid_uuid(page):
|
276
289
|
page_ids.append(page)
|
@@ -287,38 +300,51 @@ class NotionRelationManager(LoggingMixin):
|
|
287
300
|
self.logger.warning("No page found with title '%s'", page)
|
288
301
|
|
289
302
|
if not page_ids:
|
290
|
-
self.logger.warning(
|
291
|
-
|
303
|
+
self.logger.warning(
|
304
|
+
"No valid page IDs found for any of the titles, no changes applied"
|
305
|
+
)
|
306
|
+
return RelationOperationResult.from_no_pages_found(
|
307
|
+
property_name, not_found_pages
|
308
|
+
)
|
292
309
|
|
293
310
|
api_response = await self.add_relation(property_name, page_ids)
|
294
|
-
|
311
|
+
|
295
312
|
if api_response:
|
296
313
|
result = RelationOperationResult.from_success(
|
297
314
|
property_name=property_name,
|
298
315
|
found_pages=found_pages,
|
299
316
|
not_found_pages=not_found_pages,
|
300
317
|
page_ids_added=page_ids,
|
301
|
-
api_response=api_response
|
318
|
+
api_response=api_response,
|
302
319
|
)
|
303
|
-
|
320
|
+
|
304
321
|
if not_found_pages:
|
305
322
|
not_found_str = "', '".join(not_found_pages)
|
306
|
-
self.logger.info(
|
307
|
-
|
323
|
+
self.logger.info(
|
324
|
+
"Added %d relation(s) to '%s', but couldn't find pages: '%s'",
|
325
|
+
len(page_ids),
|
326
|
+
property_name,
|
327
|
+
not_found_str,
|
328
|
+
)
|
308
329
|
else:
|
309
|
-
self.logger.info(
|
310
|
-
|
311
|
-
|
330
|
+
self.logger.info(
|
331
|
+
"Successfully added all %d relation(s) to '%s'",
|
332
|
+
len(page_ids),
|
333
|
+
property_name,
|
334
|
+
)
|
335
|
+
|
312
336
|
return result
|
313
|
-
|
337
|
+
|
314
338
|
self.logger.error("Failed to add relations to '%s' (API error)", property_name)
|
315
339
|
return RelationOperationResult.from_no_api_response(
|
316
340
|
property_name=property_name,
|
317
341
|
found_pages=found_pages,
|
318
|
-
page_ids_added=page_ids
|
342
|
+
page_ids_added=page_ids,
|
319
343
|
)
|
320
344
|
|
321
|
-
async def set_relations(
|
345
|
+
async def set_relations(
|
346
|
+
self, property_name: str, page_ids: List[str]
|
347
|
+
) -> Optional[Dict[str, Any]]:
|
322
348
|
"""
|
323
349
|
Sets the relations to the specified IDs (replaces existing ones).
|
324
350
|
|
@@ -329,18 +355,12 @@ class NotionRelationManager(LoggingMixin):
|
|
329
355
|
Returns:
|
330
356
|
Optional[Dict[str, Any]]: API response or None on error
|
331
357
|
"""
|
332
|
-
relation_payload = {
|
333
|
-
"relation": [{"id": page_id} for page_id in page_ids]
|
334
|
-
}
|
358
|
+
relation_payload = {"relation": [{"id": page_id} for page_id in page_ids]}
|
335
359
|
|
336
360
|
try:
|
337
361
|
result = await self._client.patch(
|
338
362
|
f"pages/{self._page_id}",
|
339
|
-
{
|
340
|
-
"properties": {
|
341
|
-
property_name: relation_payload
|
342
|
-
}
|
343
|
-
},
|
363
|
+
{"properties": {property_name: relation_payload}},
|
344
364
|
)
|
345
365
|
|
346
366
|
self._page_properties = None
|
@@ -349,16 +369,15 @@ class NotionRelationManager(LoggingMixin):
|
|
349
369
|
except Exception as e:
|
350
370
|
self.logger.error("Error setting relations: %s", str(e))
|
351
371
|
return None
|
352
|
-
|
372
|
+
|
353
373
|
async def get_all_relations(self) -> Dict[str, List[str]]:
|
354
|
-
"""
|
355
|
-
"""
|
374
|
+
"""Returns all relation properties and their values."""
|
356
375
|
relation_properties = await self.get_relation_property_ids()
|
357
376
|
if not relation_properties:
|
358
377
|
return {}
|
359
|
-
|
378
|
+
|
360
379
|
result = {}
|
361
380
|
for prop_name in relation_properties:
|
362
381
|
result[prop_name] = await self.get_relation_values(prop_name)
|
363
|
-
|
364
|
-
return result
|
382
|
+
|
383
|
+
return result
|
@@ -6,7 +6,7 @@ from notionary.util.logging_mixin import LoggingMixin
|
|
6
6
|
class NotionPageTitleResolver(LoggingMixin):
|
7
7
|
def __init__(self, client: NotionClient):
|
8
8
|
self._client = client
|
9
|
-
|
9
|
+
|
10
10
|
async def get_page_id_by_title(self, title: str) -> Optional[str]:
|
11
11
|
"""
|
12
12
|
Searches for a Notion page by its title and returns the corresponding page ID if found.
|
@@ -14,13 +14,7 @@ class NotionPageTitleResolver(LoggingMixin):
|
|
14
14
|
try:
|
15
15
|
search_results = await self._client.post(
|
16
16
|
"search",
|
17
|
-
{
|
18
|
-
"query": title,
|
19
|
-
"filter": {
|
20
|
-
"value": "page",
|
21
|
-
"property": "object"
|
22
|
-
}
|
23
|
-
}
|
17
|
+
{"query": title, "filter": {"value": "page", "property": "object"}},
|
24
18
|
)
|
25
19
|
|
26
20
|
for result in search_results.get("results", []):
|
@@ -30,14 +24,20 @@ class NotionPageTitleResolver(LoggingMixin):
|
|
30
24
|
if prop_value.get("type") == "title":
|
31
25
|
title_texts = prop_value.get("title", [])
|
32
26
|
|
33
|
-
page_title = " ".join(
|
27
|
+
page_title = " ".join(
|
28
|
+
[t.get("plain_text", "") for t in title_texts]
|
29
|
+
)
|
34
30
|
|
35
31
|
if page_title == title or title in page_title:
|
36
|
-
self.logger.debug(
|
32
|
+
self.logger.debug(
|
33
|
+
"Found page: '%s' with ID: %s",
|
34
|
+
page_title,
|
35
|
+
result.get("id"),
|
36
|
+
)
|
37
37
|
return result.get("id")
|
38
38
|
|
39
39
|
self.logger.debug("No page found with title '%s'", title)
|
40
40
|
return None
|
41
41
|
except Exception as e:
|
42
42
|
self.logger.error("Error while searching for page '%s': %s", title, e)
|
43
|
-
return None
|
43
|
+
return None
|
@@ -8,11 +8,11 @@ class PageDatabaseRelation(LoggingMixin):
|
|
8
8
|
Manages the relationship between a Notion page and its parent database.
|
9
9
|
Provides methods to access database schema and property options.
|
10
10
|
"""
|
11
|
-
|
11
|
+
|
12
12
|
def __init__(self, page_id: str, client: NotionClient):
|
13
13
|
"""
|
14
14
|
Initialize the page-database relationship handler.
|
15
|
-
|
15
|
+
|
16
16
|
Args:
|
17
17
|
page_id: ID of the Notion page
|
18
18
|
client: Instance of NotionClient
|
@@ -22,49 +22,49 @@ class PageDatabaseRelation(LoggingMixin):
|
|
22
22
|
self._parent_database_id = None
|
23
23
|
self._database_schema = None
|
24
24
|
self._page_data = None
|
25
|
-
|
25
|
+
|
26
26
|
async def _get_page_data(self, force_refresh=False) -> Dict[str, Any]:
|
27
27
|
"""
|
28
28
|
Gets the page data and caches it for future use.
|
29
|
-
|
29
|
+
|
30
30
|
Args:
|
31
31
|
force_refresh: Whether to force a refresh of the page data
|
32
|
-
|
32
|
+
|
33
33
|
Returns:
|
34
34
|
Dict[str, Any]: The page data
|
35
35
|
"""
|
36
36
|
if self._page_data is None or force_refresh:
|
37
37
|
self._page_data = await self._client.get_page(self._page_id)
|
38
38
|
return self._page_data
|
39
|
-
|
39
|
+
|
40
40
|
async def get_parent_database_id(self) -> Optional[str]:
|
41
41
|
"""
|
42
42
|
Gets the ID of the database this page belongs to, if any.
|
43
|
-
|
43
|
+
|
44
44
|
Returns:
|
45
45
|
Optional[str]: The database ID or None if the page doesn't belong to a database
|
46
46
|
"""
|
47
47
|
if self._parent_database_id is not None:
|
48
48
|
return self._parent_database_id
|
49
|
-
|
49
|
+
|
50
50
|
page_data = await self._get_page_data()
|
51
|
-
|
51
|
+
|
52
52
|
if not page_data or "parent" not in page_data:
|
53
53
|
return None
|
54
|
-
|
54
|
+
|
55
55
|
parent = page_data.get("parent", {})
|
56
56
|
if parent.get("type") == "database_id":
|
57
57
|
self._parent_database_id = parent.get("database_id")
|
58
58
|
return self._parent_database_id
|
59
|
-
|
59
|
+
|
60
60
|
return None
|
61
|
-
|
61
|
+
|
62
62
|
async def is_database_page(self) -> bool:
|
63
63
|
"""
|
64
64
|
Checks if this page belongs to a database.
|
65
|
-
|
65
|
+
|
66
66
|
Returns:
|
67
67
|
bool: True if the page belongs to a database, False otherwise
|
68
68
|
"""
|
69
69
|
database_id = await self.get_parent_database_id()
|
70
|
-
return database_id is not None
|
70
|
+
return database_id is not None
|