notionary 0.2.25__py3-none-any.whl → 0.2.27__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.
@@ -27,6 +27,7 @@ class CalloutBlock(BaseModel):
27
27
  icon: Optional[IconObject] = None
28
28
  children: Optional[list[Block]] = None
29
29
 
30
+
30
31
  class CreateCalloutBlock(BaseModel):
31
32
  type: Literal["callout"] = "callout"
32
33
  callout: CalloutBlock
@@ -1,7 +1,5 @@
1
1
  from typing import Any, Dict, Optional
2
2
 
3
- from urllib3.util import response
4
-
5
3
  from notionary.base_notion_client import BaseNotionClient
6
4
  from notionary.database.models import (
7
5
  NotionDatabaseResponse,
notionary/page/models.py CHANGED
@@ -2,6 +2,8 @@ from typing import Any, Literal, Optional, Union
2
2
 
3
3
  from pydantic import BaseModel, ConfigDict
4
4
 
5
+ from notionary.blocks.models import ParentObject
6
+
5
7
 
6
8
  class TextContent(BaseModel):
7
9
  content: str
@@ -241,13 +243,6 @@ class NotionCover(BaseModel):
241
243
  external: Optional[ExternalCover] = None
242
244
 
243
245
 
244
- # Parent types for Pydantic
245
- class NotionParent(BaseModel):
246
- type: str # 'database_id', 'page_id', 'workspace'
247
- database_id: Optional[str] = None
248
- page_id: Optional[str] = None
249
-
250
-
251
246
  # User type for Pydantic
252
247
  class NotionUser(BaseModel):
253
248
  object: str # 'user'
@@ -274,7 +269,7 @@ class NotionDatabaseResponse(BaseModel):
274
269
  properties: dict[
275
270
  str, Any
276
271
  ] # Using Any for flexibility with different property schemas
277
- parent: NotionParent
272
+ parent: ParentObject
278
273
  url: str
279
274
  public_url: Optional[str] = None
280
275
  archived: bool
@@ -290,7 +285,7 @@ class NotionPageResponse(BaseModel):
290
285
  last_edited_by: NotionUser
291
286
  cover: Optional[NotionCover] = None
292
287
  icon: Optional[Icon] = None
293
- parent: NotionParent
288
+ parent: ParentObject
294
289
  archived: bool
295
290
  in_trash: bool
296
291
  properties: dict[str, Any]
@@ -1,13 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from ast import Dict
3
4
  import asyncio
4
5
  import random
5
6
  from typing import TYPE_CHECKING, Any, Callable, Optional, Union
6
7
 
8
+ from yaml import Token
9
+
7
10
  from notionary.blocks.client import NotionBlockClient
8
11
  from notionary.comments import CommentClient, Comment
9
12
  from notionary.blocks.syntax_prompt_builder import SyntaxPromptBuilder
10
- from notionary.blocks.models import DatabaseParent
13
+ from notionary.blocks.models import DatabaseParent, ParentObject
11
14
  from notionary.blocks.registry.block_registry import BlockRegistry
12
15
  from notionary.database.client import NotionDatabaseClient
13
16
  from notionary.file_upload.client import NotionFileUploadClient
@@ -43,6 +46,7 @@ class NotionPage(LoggingMixin):
43
46
  archived: bool,
44
47
  in_trash: bool,
45
48
  emoji_icon: Optional[str] = None,
49
+ external_icon_url: Optional[str] = None,
46
50
  properties: Optional[dict[str, Any]] = None,
47
51
  parent_database: Optional[NotionDatabase] = None,
48
52
  token: Optional[str] = None,
@@ -56,11 +60,13 @@ class NotionPage(LoggingMixin):
56
60
  self._is_archived = archived
57
61
  self._is_in_trash = in_trash
58
62
  self._emoji_icon = emoji_icon
63
+ self._external_icon_url = external_icon_url
59
64
  self._properties = properties
60
65
  self._parent_database = parent_database
61
66
 
62
67
  self._client = NotionPageClient(token=token)
63
68
  self._block_client = NotionBlockClient(token=token)
69
+ self._database_client = NotionDatabaseClient(token=token)
64
70
  self._comment_client = CommentClient(token=token)
65
71
  self._page_data = None
66
72
 
@@ -188,6 +194,13 @@ class NotionPage(LoggingMixin):
188
194
  """
189
195
  return self._url
190
196
 
197
+ @property
198
+ def external_icon_url(self) -> Optional[str]:
199
+ """
200
+ Get the icon of the page.
201
+ """
202
+ return self._external_icon_url
203
+
191
204
  @property
192
205
  def emoji_icon(self) -> Optional[str]:
193
206
  """
@@ -341,12 +354,32 @@ class NotionPage(LoggingMixin):
341
354
  )
342
355
 
343
356
  self._emoji = page_response.icon.emoji
357
+ self._external_icon_url = None
344
358
  return page_response.icon.emoji
345
359
  except Exception as e:
346
360
 
347
361
  self.logger.error(f"Error updating page emoji: {str(e)}")
348
362
  return None
349
363
 
364
+ async def set_external_icon(self, url: str) -> Optional[str]:
365
+ """
366
+ Sets the page icon to an external image.
367
+ """
368
+ try:
369
+ icon = {"type": "external", "external": {"url": url}}
370
+ page_response = await self._client.patch_page(
371
+ page_id=self._page_id, data={"icon": icon}
372
+ )
373
+
374
+ self._icon = url
375
+ self._emoji = None
376
+ self.logger.info(f"Successfully updated page external icon to: {url}")
377
+ return page_response.icon.external.url
378
+
379
+ except Exception as e:
380
+ self.logger.error(f"Error updating page external icon: {str(e)}")
381
+ return None
382
+
350
383
  async def create_child_database(self, title: str) -> NotionDatabase:
351
384
  from notionary import NotionDatabase
352
385
 
@@ -433,30 +466,20 @@ class NotionPage(LoggingMixin):
433
466
  """
434
467
  Get the value of a specific property.
435
468
  """
436
- if not self._parent_database:
437
- return None
438
-
439
- database_property_schema = self._parent_database.properties.get(property_name)
440
-
441
- if not database_property_schema:
469
+ if property_name not in self._properties:
442
470
  self.logger.warning(
443
- "Property '%s' not found in database schema", property_name
471
+ "Property '%s' not found in page properties", property_name
444
472
  )
445
473
  return None
446
474
 
447
- property_type = database_property_schema.get("type")
475
+ property_schema: dict = self._properties.get(property_name)
476
+
477
+ property_type = property_schema.get("type")
448
478
 
449
479
  if property_type == "relation":
450
480
  return await self._get_relation_property_values_by_name(property_name)
451
481
 
452
- if property_name not in self._properties:
453
- self.logger.warning(
454
- "Property '%s' not found in page properties", property_name
455
- )
456
- return None
457
-
458
- property_data = self._properties.get(property_name)
459
- return extract_property_value(property_data)
482
+ return extract_property_value(property_schema)
460
483
 
461
484
  async def _get_relation_property_values_by_name(
462
485
  self, property_name: str
@@ -464,7 +487,7 @@ class NotionPage(LoggingMixin):
464
487
  """
465
488
  Retrieve the titles of all related pages for a relation property.
466
489
  """
467
- page_property_schema = self.properties.get(property_name)
490
+ page_property_schema = self._properties.get(property_name)
468
491
  relation_page_ids = [
469
492
  rel.get("id") for rel in page_property_schema.get("relation", [])
470
493
  ]
@@ -477,23 +500,25 @@ class NotionPage(LoggingMixin):
477
500
  """
478
501
  Get the available options for a property (select, multi_select, status, relation).
479
502
  """
480
- if not self._parent_database:
481
- self.logger.error(
482
- "Parent database not set. Cannot get options for property: %s",
483
- property_name,
503
+ if property_name not in self.properties:
504
+ self.logger.warning(
505
+ "Property '%s' not found in page properties", property_name
484
506
  )
485
507
  return []
486
508
 
487
- try:
488
- return await self._parent_database.get_options_by_property_name(
489
- property_name=property_name
490
- )
491
- except Exception as e:
492
- self.logger.error(
493
- "Error getting options for property '%s': %s", property_name, str(e)
494
- )
495
- return []
509
+ property_schema: dict = self.properties.get(property_name)
510
+ property_type = property_schema.get("type")
511
+
512
+ if property_type in ["select", "multi_select", "status"]:
513
+ options = property_schema.get(property_type, {}).get("options", [])
514
+ return [option.get("name", "") for option in options]
515
+
516
+ if property_type == "relation" and self._parent_database:
517
+ return await self._parent_database._get_relation_options(property_name)
518
+
519
+ return []
496
520
 
521
+ # Fix this for pages that do not ah
497
522
  async def set_property_value_by_name(self, property_name: str, value: Any) -> Any:
498
523
  """
499
524
  Set the value of a specific property by its name.
@@ -603,7 +628,8 @@ class NotionPage(LoggingMixin):
603
628
  from notionary.database.database import NotionDatabase
604
629
 
605
630
  title = cls._extract_title(page_response)
606
- emoji = cls._extract_emoji(page_response)
631
+ emoji_icon = cls._extract_page_emoji_icon(page_response)
632
+ external_icon_url = cls._extract_external_icon_url(page_response)
607
633
  parent_database_id = cls._extract_parent_database_id(page_response)
608
634
 
609
635
  parent_database = (
@@ -616,7 +642,8 @@ class NotionPage(LoggingMixin):
616
642
  page_id=page_response.id,
617
643
  title=title,
618
644
  url=page_response.url,
619
- emoji_icon=emoji,
645
+ emoji_icon=emoji_icon,
646
+ external_icon_url=external_icon_url,
620
647
  archived=page_response.archived,
621
648
  in_trash=page_response.in_trash,
622
649
  properties=page_response.properties,
@@ -653,15 +680,22 @@ class NotionPage(LoggingMixin):
653
680
  return ""
654
681
 
655
682
  @staticmethod
656
- def _extract_emoji(page_response: NotionPageResponse) -> Optional[str]:
657
- """Extract emoji from database response."""
683
+ def _extract_page_emoji_icon(page_response: NotionPageResponse) -> Optional[str]:
684
+ """Extract external icon URL from page response."""
658
685
  if not page_response.icon:
659
686
  return None
660
687
 
661
688
  if page_response.icon.type == "emoji":
662
689
  return page_response.icon.emoji
663
690
 
664
- return None
691
+ @staticmethod
692
+ def _extract_external_icon_url(page_response: NotionPageResponse) -> Optional[str]:
693
+ """Extract emoji from database response."""
694
+ if not page_response.icon:
695
+ return None
696
+
697
+ if page_response.icon.type == "external":
698
+ return page_response.icon.external.url
665
699
 
666
700
  @staticmethod
667
701
  def _extract_parent_database_id(page_response: NotionPageResponse) -> Optional[str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: notionary
3
- Version: 0.2.25
3
+ Version: 0.2.27
4
4
  Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
5
5
  License: MIT
6
6
  Author: Mathis Arends
@@ -22,7 +22,7 @@ notionary/blocks/bulleted_list/bulleted_list_models.py,sha256=QN21PIwAP7MQoIjZeU
22
22
  notionary/blocks/callout/__init__.py,sha256=17rdvOF5W1aPxkp-pk13rLgkx6pIciCsub3ncAv_zXk,363
23
23
  notionary/blocks/callout/callout_element.py,sha256=6Ss1jv1cqAM4GuNGvuy7dCFjpp-dLavf-wXevn3IEmw,3575
24
24
  notionary/blocks/callout/callout_markdown_node.py,sha256=2zZNMwg8uiGBqaMOUVOTlIK8kiq20IQ0Ylv7ZFUm-bc,602
25
- notionary/blocks/callout/callout_models.py,sha256=E58ko2ujDV80HlI20S9etbCMTm6a_IaSp9waUozWTa8,863
25
+ notionary/blocks/callout/callout_models.py,sha256=g_xU7oiRRseoSO86dqHPIiwoseGvvnl3jsPZbBMT-mE,865
26
26
  notionary/blocks/child_database/__init__.py,sha256=FzjjHOS9Je2oXuxLK9S9Oq56-EDEZRTJBfDzkacFpY0,368
27
27
  notionary/blocks/child_database/child_database_element.py,sha256=1pxtoB_XTIWorYp984TpsPMZy8A5IdQ15nJALyzme-c,2279
28
28
  notionary/blocks/child_database/child_database_models.py,sha256=SP6S9tKTetKNdCkYY3QCxeXd2lq1DyfdNvDhKlhD22Q,264
@@ -123,7 +123,7 @@ notionary/comments/__init__.py,sha256=G0OWsaN2VgbykvhLlNSweL_f0bl16j9NpidH2UNbFc
123
123
  notionary/comments/client.py,sha256=vWjgPFk_TPY7peq10aJc7WTG-b0q6Fn8qirAlzlqLls,7311
124
124
  notionary/comments/models.py,sha256=O2-yg-0Xrs8xrzLUa4793FlyNn3HbTRsv4dqaskI6ps,3409
125
125
  notionary/database/__init__.py,sha256=4tdML0fBzkOCpiWT6q-L--5NELFLbTPD0IUA_E8yZno,155
126
- notionary/database/client.py,sha256=mN_8XHvIQkRxiWbgBfvncgw4IRiCFX3bVLMLBvtk1Ig,5398
126
+ notionary/database/client.py,sha256=NQWUcfMLAYsnTefFgOjgOHMYN7rn_IRBrsKPUlUY0c8,5361
127
127
  notionary/database/database.py,sha256=sdo830KVInR4enaEaeMHaPadNfYnPLy5R3OW2f74w28,16558
128
128
  notionary/database/database_filter_builder.py,sha256=YIkdghD5VbdwLJISMRiJ0WIJTm8jcDIL22yrvZau4sA,5950
129
129
  notionary/database/database_provider.py,sha256=HB-hZ9pMjronLJS8w_b1GiQ-Ecz1uJbrWpnePL67BCA,8956
@@ -137,8 +137,8 @@ notionary/file_upload/models.py,sha256=bSNgw5WzkOuotyalqkkcVC_Ue6YRHR-CSJV7nZRV_
137
137
  notionary/file_upload/notion_file_upload.py,sha256=vOEEh8g8Sj4JedrK9e-NYjJ0HXH3iGdM5N74kkVXVZQ,13221
138
138
  notionary/page/client.py,sha256=IOsjWOsmODxOq-7OF0y-gcuC2HUbMIT0SvJZHrH9weQ,4520
139
139
  notionary/page/markdown_whitespace_processor.py,sha256=SbWLL6bdeTGds_khDNX2mQe00lGYUFvH6PX8_xpNvBA,4634
140
- notionary/page/models.py,sha256=pD8FlK8KtnUrIITTd2jg_yJICakgPE4ysZiS9KiMpr0,7088
141
- notionary/page/notion_page.py,sha256=6aQqAqiEg6gb5lISKkV6a2UzIixgOZ-7eivlvXpyHvc,23689
140
+ notionary/page/models.py,sha256=zk9QOgCDzVfYfT1Gp2bL1_Bw-QUyfWxwTTIPzIayQ7g,6945
141
+ notionary/page/notion_page.py,sha256=_Hj0U9gl3laRKs3l1Cd8tBODXZrHYxrK2Z5gw0O0Fvo,25146
142
142
  notionary/page/page_content_deleting_service.py,sha256=G3im6VotG1tgI-SaqoQR-gSnOloF6CEnft1qxLps4as,4546
143
143
  notionary/page/page_content_writer.py,sha256=t8N7yfW--ac7szvDmTdecFEfcF5Nz95vyCQ-lpYcOUw,3046
144
144
  notionary/page/page_context.py,sha256=27vrTRZP7NsaS4dEp4pBNR30Re2hh00qKlL3xt4YtpI,1773
@@ -196,7 +196,7 @@ notionary/util/page_id_utils.py,sha256=AA00kRO-g3Cc50tf_XW_tb5RBuPKLuBxRa0D8LYhL
196
196
  notionary/util/singleton.py,sha256=CKAvykndwPRZsA3n3MAY_XdCR59MBjjKP0vtm2BcvF0,428
197
197
  notionary/util/singleton_metaclass.py,sha256=DMvrh0IbAV8nIG1oX-2Yz57Uk1YHB647DNxoI3pAT3s,809
198
198
  notionary/workspace.py,sha256=QP4WcOIdQnlVr4M7hpGaFT-Fori_QRhsV-SBC2lnwTU,3809
199
- notionary-0.2.25.dist-info/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
200
- notionary-0.2.25.dist-info/METADATA,sha256=Bzep6uh4Odk8Hx_SyIYfoyR0tzAchXL1Un7LillnwQQ,9143
201
- notionary-0.2.25.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
202
- notionary-0.2.25.dist-info/RECORD,,
199
+ notionary-0.2.27.dist-info/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
200
+ notionary-0.2.27.dist-info/METADATA,sha256=NabOWlvkZwSL3tGqEiC1DGDd-cWAUNPJaT6hdFH3KAo,9143
201
+ notionary-0.2.27.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
202
+ notionary-0.2.27.dist-info/RECORD,,