notionary 0.1.11__py3-none-any.whl → 0.1.13__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.
Files changed (55) hide show
  1. notionary/__init__.py +21 -6
  2. notionary/{core/converters → converters}/elements/audio_element.py +7 -5
  3. notionary/{core/converters → converters}/elements/bookmark_element.py +1 -1
  4. notionary/{core/converters → converters}/elements/callout_element.py +2 -2
  5. notionary/{core/converters → converters}/elements/code_block_element.py +1 -1
  6. notionary/{core/converters → converters}/elements/column_element.py +1 -1
  7. notionary/{core/converters → converters}/elements/divider_element.py +1 -1
  8. notionary/{core/converters → converters}/elements/embed_element.py +3 -5
  9. notionary/{core/converters → converters}/elements/heading_element.py +2 -2
  10. notionary/{core/converters → converters}/elements/image_element.py +1 -1
  11. notionary/{core/converters → converters}/elements/list_element.py +2 -2
  12. notionary/{core/converters → converters}/elements/paragraph_element.py +2 -2
  13. notionary/{core/converters → converters}/elements/qoute_element.py +1 -1
  14. notionary/{core/converters → converters}/elements/table_element.py +2 -2
  15. notionary/{core/converters → converters}/elements/todo_lists.py +2 -2
  16. notionary/{core/converters → converters}/elements/toggle_element.py +24 -21
  17. notionary/{core/converters → converters}/elements/video_element.py +1 -1
  18. notionary/{core/converters → converters}/markdown_to_notion_converter.py +72 -111
  19. notionary/{core/converters → converters}/notion_to_markdown_converter.py +2 -2
  20. notionary/{core/converters → converters}/registry/block_element_registry.py +5 -5
  21. notionary/{core/converters → converters}/registry/block_element_registry_builder.py +18 -18
  22. notionary/database/database_discovery.py +142 -0
  23. notionary/{core/database → database}/database_info_service.py +1 -1
  24. notionary/{core/database/notion_database_manager.py → database/notion_database.py} +33 -57
  25. notionary/{core/database/notion_database_manager_factory.py → database/notion_database_factory.py} +18 -16
  26. notionary/{core/notion_client.py → notion_client.py} +4 -2
  27. notionary/page/content/notion_page_content_chunker.py +84 -0
  28. notionary/{core/page → page}/content/page_content_manager.py +29 -13
  29. notionary/{core/page → page}/metadata/metadata_editor.py +59 -46
  30. notionary/{core/page → page}/metadata/notion_icon_manager.py +10 -12
  31. notionary/{core/page → page}/metadata/notion_page_cover_manager.py +16 -21
  32. notionary/page/notion_page.py +504 -0
  33. notionary/page/notion_page_factory.py +256 -0
  34. notionary/{core/page → page}/properites/database_property_service.py +115 -99
  35. notionary/{core/page → page}/properites/page_property_manager.py +81 -52
  36. notionary/{core/page → page}/properites/property_formatter.py +1 -1
  37. notionary/{core/page → page}/properites/property_operation_result.py +43 -30
  38. notionary/{core/page → page}/properites/property_value_extractor.py +26 -8
  39. notionary/{core/page → page}/relations/notion_page_relation_manager.py +72 -53
  40. notionary/{core/page → page}/relations/notion_page_title_resolver.py +12 -12
  41. notionary/{core/page → page}/relations/page_database_relation.py +15 -15
  42. notionary/{core/page → page}/relations/relation_operation_result.py +50 -41
  43. notionary/util/page_id_utils.py +14 -8
  44. {notionary-0.1.11.dist-info → notionary-0.1.13.dist-info}/METADATA +1 -1
  45. notionary-0.1.13.dist-info/RECORD +56 -0
  46. notionary/core/database/notion_database_schema.py +0 -104
  47. notionary/core/page/notion_page_manager.py +0 -322
  48. notionary-0.1.11.dist-info/RECORD +0 -54
  49. /notionary/{core/converters → converters}/__init__.py +0 -0
  50. /notionary/{core/converters → converters}/elements/notion_block_element.py +0 -0
  51. /notionary/{core/converters → converters}/elements/text_inline_formatter.py +0 -0
  52. /notionary/{core/database → database}/models/page_result.py +0 -0
  53. {notionary-0.1.11.dist-info → notionary-0.1.13.dist-info}/WHEEL +0 -0
  54. {notionary-0.1.11.dist-info → notionary-0.1.13.dist-info}/licenses/LICENSE +0 -0
  55. {notionary-0.1.11.dist-info → notionary-0.1.13.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Dict, Optional
2
- from notionary.core.notion_client import NotionClient
3
- from notionary.core.page.properites.property_formatter import NotionPropertyFormatter
2
+ from notionary.notion_client import NotionClient
3
+ from notionary.page.properites.property_formatter import NotionPropertyFormatter
4
4
  from notionary.util.logging_mixin import LoggingMixin
5
5
 
6
6
 
@@ -20,90 +20,103 @@ class MetadataEditor(LoggingMixin):
20
20
  },
21
21
  )
22
22
 
23
- async def set_property(self, property_name: str, property_value: Any, property_type: str) -> Optional[Dict[str, Any]]:
24
- """
25
- Generic method to set any property on a Notion page.
26
-
27
- Args:
28
- property_name: The name of the property in Notion
29
- property_value: The value to set
30
- property_type: The type of property ('select', 'multi_select', 'status', 'relation', etc.)
31
-
32
- Returns:
33
- Optional[Dict[str, Any]]: The API response or None if the operation fails
34
- """
35
- property_payload = self._property_formatter.format_value(property_type, property_value)
36
-
37
- if not property_payload:
38
- self.logger.warning("Could not create payload for property type: %s", property_type)
39
- return None
40
-
41
- return await self._client.patch(
42
- f"pages/{self.page_id}",
43
- {
44
- "properties": {
45
- property_name: property_payload
46
- }
47
- },
23
+ async def set_property(
24
+ self, property_name: str, property_value: Any, property_type: str
25
+ ) -> Optional[Dict[str, Any]]:
26
+ """
27
+ Generic method to set any property on a Notion page.
28
+
29
+ Args:
30
+ property_name: The name of the property in Notion
31
+ property_value: The value to set
32
+ property_type: The type of property ('select', 'multi_select', 'status', 'relation', etc.)
33
+
34
+ Returns:
35
+ Optional[Dict[str, Any]]: The API response or None if the operation fails
36
+ """
37
+ property_payload = self._property_formatter.format_value(
38
+ property_type, property_value
39
+ )
40
+
41
+ if not property_payload:
42
+ self.logger.warning(
43
+ "Could not create payload for property type: %s", property_type
48
44
  )
45
+ return None
49
46
 
47
+ return await self._client.patch(
48
+ f"pages/{self.page_id}",
49
+ {"properties": {property_name: property_payload}},
50
+ )
50
51
 
51
52
  async def get_property_schema(self) -> Dict[str, Dict[str, Any]]:
52
53
  """
53
54
  Retrieves the schema for all properties of the page.
54
-
55
+
55
56
  Returns:
56
57
  Dict[str, Dict[str, Any]]: A dictionary mapping property names to their schema
57
58
  """
58
59
  page_data = await self._client.get_page(self.page_id)
59
60
  property_schema = {}
60
-
61
+
61
62
  if not page_data or "properties" not in page_data:
62
63
  return property_schema
63
-
64
+
64
65
  for prop_name, prop_data in page_data["properties"].items():
65
66
  prop_type = prop_data.get("type")
66
67
  property_schema[prop_name] = {
67
68
  "id": prop_data.get("id"),
68
69
  "type": prop_type,
69
- "name": prop_name
70
+ "name": prop_name,
70
71
  }
71
-
72
+
72
73
  try:
73
74
  if prop_type == "select" and "select" in prop_data:
74
75
  # Make sure prop_data["select"] is a dictionary before calling .get()
75
76
  if isinstance(prop_data["select"], dict):
76
- property_schema[prop_name]["options"] = prop_data["select"].get("options", [])
77
+ property_schema[prop_name]["options"] = prop_data["select"].get(
78
+ "options", []
79
+ )
77
80
  elif prop_type == "multi_select" and "multi_select" in prop_data:
78
81
  # Make sure prop_data["multi_select"] is a dictionary before calling .get()
79
82
  if isinstance(prop_data["multi_select"], dict):
80
- property_schema[prop_name]["options"] = prop_data["multi_select"].get("options", [])
83
+ property_schema[prop_name]["options"] = prop_data[
84
+ "multi_select"
85
+ ].get("options", [])
81
86
  elif prop_type == "status" and "status" in prop_data:
82
87
  # Make sure prop_data["status"] is a dictionary before calling .get()
83
88
  if isinstance(prop_data["status"], dict):
84
- property_schema[prop_name]["options"] = prop_data["status"].get("options", [])
89
+ property_schema[prop_name]["options"] = prop_data["status"].get(
90
+ "options", []
91
+ )
85
92
  except Exception as e:
86
- if hasattr(self, 'logger') and self.logger:
87
- self.logger.warning("Error processing property schema for '%s': %s", prop_name, e)
88
-
93
+ if hasattr(self, "logger") and self.logger:
94
+ self.logger.warning(
95
+ "Error processing property schema for '%s': %s", prop_name, e
96
+ )
97
+
89
98
  return property_schema
90
-
91
- async def set_property_by_name(self, property_name: str, value: Any) -> Optional[Dict[str, Any]]:
99
+
100
+ async def set_property_by_name(
101
+ self, property_name: str, value: Any
102
+ ) -> Optional[Dict[str, Any]]:
92
103
  """
93
104
  Sets a property value based on the property name, automatically detecting the property type.
94
-
105
+
95
106
  Args:
96
107
  property_name: The name of the property in Notion
97
108
  value: The value to set
98
-
109
+
99
110
  Returns:
100
111
  Optional[Dict[str, Any]]: The API response or None if the operation fails
101
112
  """
102
113
  property_schema = await self.get_property_schema()
103
-
114
+
104
115
  if property_name not in property_schema:
105
- self.logger.warning("Property '%s' not found in database schema", property_name)
116
+ self.logger.warning(
117
+ "Property '%s' not found in database schema", property_name
118
+ )
106
119
  return None
107
-
120
+
108
121
  property_type = property_schema[property_name]["type"]
109
- return await self.set_property(property_name, value, property_type)
122
+ return await self.set_property(property_name, value, property_type)
@@ -1,13 +1,14 @@
1
1
  from typing import Any, Dict, Optional
2
2
 
3
- from notionary.core.notion_client import NotionClient
3
+ from notionary.notion_client import NotionClient
4
4
  from notionary.util.logging_mixin import LoggingMixin
5
5
 
6
+
6
7
  class NotionPageIconManager(LoggingMixin):
7
8
  def __init__(self, page_id: str, client: NotionClient):
8
9
  self.page_id = page_id
9
10
  self._client = client
10
-
11
+
11
12
  async def set_icon(
12
13
  self, emoji: Optional[str] = None, external_url: Optional[str] = None
13
14
  ) -> Optional[Dict[str, Any]]:
@@ -19,28 +20,25 @@ class NotionPageIconManager(LoggingMixin):
19
20
  return None
20
21
 
21
22
  return await self._client.patch(f"pages/{self.page_id}", {"icon": icon})
22
-
23
-
23
+
24
24
  async def get_icon(self) -> Optional[str]:
25
25
  """
26
26
  Retrieves the page icon - either emoji or external URL.
27
-
27
+
28
28
  Returns:
29
29
  str: Emoji character or URL if set, None if no icon
30
30
  """
31
31
  page_data = await self._client.get_page(self.page_id)
32
-
32
+
33
33
  if not page_data or "icon" not in page_data:
34
34
  return None
35
-
35
+
36
36
  icon_data = page_data.get("icon", {})
37
37
  icon_type = icon_data.get("type")
38
-
38
+
39
39
  if icon_type == "emoji":
40
40
  return icon_data.get("emoji")
41
41
  elif icon_type == "external":
42
42
  return icon_data.get("external", {}).get("url")
43
-
44
- return None
45
-
46
-
43
+
44
+ return None
@@ -1,48 +1,43 @@
1
-
2
1
  import random
3
2
  from typing import Any, Dict, Optional
4
- from notionary.core.notion_client import NotionClient
3
+ from notionary.notion_client import NotionClient
5
4
  from notionary.util.logging_mixin import LoggingMixin
6
5
 
6
+
7
7
  class NotionPageCoverManager(LoggingMixin):
8
8
  def __init__(self, page_id: str, client: NotionClient):
9
9
  self.page_id = page_id
10
10
  self._client = client
11
-
11
+
12
12
  async def set_cover(self, external_url: str) -> Optional[Dict[str, Any]]:
13
- """Sets a cover image from an external URL.
14
- """
15
-
13
+ """Sets a cover image from an external URL."""
14
+
16
15
  return await self._client.patch(
17
16
  f"pages/{self.page_id}",
18
17
  {"cover": {"type": "external", "external": {"url": external_url}}},
19
18
  )
20
-
19
+
21
20
  async def set_random_gradient_cover(self) -> Optional[Dict[str, Any]]:
22
- """ Sets a random gradient cover from Notion's default gradient covers.
23
- """
21
+ """Sets a random gradient cover from Notion's default gradient covers."""
24
22
  default_notion_covers = [
25
- "https://www.notion.so/images/page-cover/gradients_8.png",
23
+ "https://www.notion.so/images/page-cover/gradients_8.png",
26
24
  "https://www.notion.so/images/page-cover/gradients_2.png",
27
25
  "https://www.notion.so/images/page-cover/gradients_11.jpg",
28
26
  "https://www.notion.so/images/page-cover/gradients_10.jpg",
29
27
  "https://www.notion.so/images/page-cover/gradients_5.png",
30
- "https://www.notion.so/images/page-cover/gradients_3.png"
28
+ "https://www.notion.so/images/page-cover/gradients_3.png",
31
29
  ]
32
-
30
+
33
31
  random_cover_url = random.choice(default_notion_covers)
34
-
32
+
35
33
  return await self.set_cover(random_cover_url)
36
-
37
-
34
+
38
35
  async def get_cover_url(self) -> str:
39
- """Retrieves the current cover image URL of the page.
40
- """
41
-
36
+ """Retrieves the current cover image URL of the page."""
37
+
42
38
  page_data = await self._client.get_page(self.page_id)
43
-
39
+
44
40
  if not page_data:
45
41
  return ""
46
-
42
+
47
43
  return page_data.get("cover", {}).get("external", {}).get("url", "")
48
-