notionary 0.1.27__py3-none-any.whl → 0.1.29__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.
@@ -17,6 +17,8 @@ from notionary.util.logging_mixin import LoggingMixin
17
17
 
18
18
 
19
19
  class PageContentManager(LoggingMixin):
20
+ BATCH_SIZE = 100
21
+
20
22
  def __init__(
21
23
  self,
22
24
  page_id: str,
@@ -33,27 +35,40 @@ class PageContentManager(LoggingMixin):
33
35
  )
34
36
  self._chunker = NotionPageContentChunker()
35
37
 
36
- async def append_markdown(self, markdown_text: str) -> str:
38
+ async def append_markdown(self, markdown_text: str, append_divider = False) -> str:
37
39
  """
38
40
  Append markdown text to a Notion page, automatically handling content length limits.
39
- First strips out triple backtick markdown fences if they wrap the entire content.
40
41
 
41
42
  Args:
42
43
  markdown_text: The markdown text to append
43
44
  append_divider: If True, appends a divider after the markdown content (default: False)
44
45
  """
45
46
  try:
47
+ # Just the markdown synthax for the divider as it will be converted to a Notion divider block
48
+ if append_divider:
49
+ markdown_text = markdown_text + "\n\n---\n\n"
50
+
46
51
  blocks = self._markdown_to_notion_converter.convert(markdown_text)
47
52
  fixed_blocks = self._chunker.fix_blocks_content_length(blocks)
48
53
 
49
- result = await self._client.patch(
50
- f"blocks/{self.page_id}/children", {"children": fixed_blocks}
51
- )
52
- return (
53
- "Successfully added text to the page."
54
- if result
55
- else "Failed to add text."
56
- )
54
+ total_blocks = len(fixed_blocks)
55
+ num_batches = (total_blocks + self.BATCH_SIZE - 1) // self.BATCH_SIZE
56
+
57
+ all_success = True
58
+ for batch_num in range(num_batches):
59
+ start_idx = batch_num * self.BATCH_SIZE
60
+ end_idx = min((batch_num + 1) * self.BATCH_SIZE, total_blocks)
61
+ batch = fixed_blocks[start_idx:end_idx]
62
+
63
+ batch_success = await self._process_batch(batch, batch_num, num_batches)
64
+ if not batch_success:
65
+ all_success = False
66
+ break
67
+
68
+ if all_success:
69
+ return f"Successfully added {total_blocks} blocks to the page in {num_batches} batch(es)."
70
+ return "Failed to add all blocks. See logs for details."
71
+
57
72
  except Exception as e:
58
73
  self.logger.error("Error appending markdown: %s", str(e))
59
74
  raise
@@ -178,3 +193,19 @@ class PageContentManager(LoggingMixin):
178
193
  async def get_text(self) -> str:
179
194
  blocks = await self.get_page_blocks_with_children()
180
195
  return self._notion_to_markdown_converter.convert(blocks)
196
+
197
+
198
+ async def _process_batch(self, batch: List[Dict], batch_num: int, num_batches: int) -> bool:
199
+ """
200
+ Verarbeitet einen einzelnen Batch von Blöcken und gibt zurück, ob es erfolgreich war.
201
+ """
202
+ result = await self._client.patch(
203
+ f"blocks/{self.page_id}/children", {"children": batch}
204
+ )
205
+
206
+ if not result:
207
+ self.logger.error("Failed to add batch %d/%d to page.", batch_num + 1, num_batches)
208
+ return False
209
+
210
+ self.logger.info("Successfully added batch %d/%d (%d blocks) to page.", batch_num + 1, num_batches, len(batch))
211
+ return True
@@ -32,14 +32,14 @@ class NotionPageIconManager(LoggingMixin):
32
32
 
33
33
  if not page_data:
34
34
  return ""
35
-
35
+
36
36
  # Get icon data, default to empty dict if not present or None
37
37
  icon_data = page_data.get("icon")
38
-
38
+
39
39
  # If icon is None or not present, return None
40
40
  if not icon_data:
41
41
  return ""
42
-
42
+
43
43
  icon_type = icon_data.get("type")
44
44
 
45
45
  if icon_type == "emoji":
@@ -40,4 +40,14 @@ class NotionPageCoverManager(LoggingMixin):
40
40
  if not page_data:
41
41
  return ""
42
42
 
43
- return page_data.get("cover", {}).get("external", {}).get("url", "")
43
+ cover = page_data.get("cover")
44
+
45
+ if not cover or not isinstance(cover, dict):
46
+ return ""
47
+
48
+ external = cover.get("external")
49
+
50
+ if not external or not isinstance(external, dict):
51
+ return ""
52
+
53
+ return external.get("url", "")
@@ -130,7 +130,7 @@ class NotionPage(LoggingMixin):
130
130
  self._url_loaded = True
131
131
  return self._url
132
132
 
133
- async def append_markdown(self, markdown: str) -> str:
133
+ async def append_markdown(self, markdown: str, append_divider = False) -> str:
134
134
  """
135
135
  Append markdown content to the page.
136
136
 
@@ -140,7 +140,7 @@ class NotionPage(LoggingMixin):
140
140
  Returns:
141
141
  str: Status or confirmation message.
142
142
  """
143
- return await self._page_content_manager.append_markdown(markdown_text=markdown)
143
+ return await self._page_content_manager.append_markdown(markdown_text=markdown, append_divider=append_divider)
144
144
 
145
145
  async def clear(self) -> str:
146
146
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: notionary
3
- Version: 0.1.27
3
+ Version: 0.1.29
4
4
  Summary: A toolkit to convert between Markdown and Notion blocks
5
5
  Home-page: https://github.com/mathisarends/notionary
6
6
  Author: Mathis Arends
@@ -32,14 +32,14 @@ notionary/elements/registry/block_element_registry_builder.py,sha256=C6W64CwFqZB
32
32
  notionary/exceptions/database_exceptions.py,sha256=I-Tx6bYRLpi5pjGPtbT-Mqxvz3BFgYTiuZxknJeLxtI,2638
33
33
  notionary/exceptions/page_creation_exception.py,sha256=4v7IuZD6GsQLrqhDLriGjuG3ML638gAO53zDCrLePuU,281
34
34
  notionary/page/markdown_to_notion_converter.py,sha256=LFnv98uU3QRzxH7sZI0AE5_QxeHkNQZMxVcab-r8Qls,15877
35
- notionary/page/notion_page.py,sha256=OXE2sw9Drkqduy96uVvXT3vHwHPh5FMJk6QyPRADoFU,17653
35
+ notionary/page/notion_page.py,sha256=GkQ7m50e1wPFd-El7JtdIuJr4eSGyBA8Bt4OXqN8yew,17708
36
36
  notionary/page/notion_page_factory.py,sha256=UUEZ-cyEWL0OMVPrgjc4vJdcplEa1bO2yHCYooACYC8,8189
37
37
  notionary/page/notion_to_markdown_converter.py,sha256=EUiHeurQb73zQJ5Gatvf_67vWd-vOI8qg3yFLz8bf8Q,6452
38
38
  notionary/page/content/notion_page_content_chunker.py,sha256=xRks74Dqec-De6-AVTxMPnXs-MSJBzSm1HfJfaHiKr8,3330
39
- notionary/page/content/page_content_manager.py,sha256=0Bl52mEqKuhDGuJhOEMhGjJWHgxCiqGYjrqO1LqYzJM,6403
39
+ notionary/page/content/page_content_manager.py,sha256=mzY-w68LUQD4Nv-iAqVf8v5TsCKzZJbbZZkYXokkl40,7796
40
40
  notionary/page/metadata/metadata_editor.py,sha256=61uiw8oB25O8ePhytoJvZDetuof5sjPoM6aoHZGo4wc,4949
41
- notionary/page/metadata/notion_icon_manager.py,sha256=JWHeJ8yjvAnj1361C-Z3RI8c8aeR9VZw81KP4ks0b6k,1603
42
- notionary/page/metadata/notion_page_cover_manager.py,sha256=qgQxQE-bx4oWjLFUQvpXD5GzO1Mx7w7htz1xC2BOqUg,1717
41
+ notionary/page/metadata/notion_icon_manager.py,sha256=I4MczURRYc1PV0qDFwbCCzicqiDyOhKpdk9E2b9lWMc,1579
42
+ notionary/page/metadata/notion_page_cover_manager.py,sha256=hasXPIbTy9rD55tHr_zzF2yj_lD0RsULz5UP0rNRx4g,1929
43
43
  notionary/page/properites/database_property_service.py,sha256=AJuBGahbb53VQa6IGGHxBMoOgCy6vFZg08uR_eDjNUs,11570
44
44
  notionary/page/properites/page_property_manager.py,sha256=Xl8Cwn8WVszqpFXT_NvASkmP5igpCTEgRVhG_F45424,6914
45
45
  notionary/page/properites/property_formatter.py,sha256=d_Nr5XQxgjB6VIS0u3ey14MOUKY416o_BvdXjbkUNAQ,3667
@@ -51,8 +51,8 @@ notionary/page/relations/page_database_relation.py,sha256=F9aGXFjjL8ZLNbfTGeGm_Q
51
51
  notionary/page/relations/relation_operation_result.py,sha256=NDxBzGntOxc_89ti-HG8xDSqfY6PwyGHKHrrKbCzNjM,5010
52
52
  notionary/util/logging_mixin.py,sha256=fKsx9t90bwvL74ZX3dU-sXdC4TZCQyO6qU9I8txkw_U,1369
53
53
  notionary/util/page_id_utils.py,sha256=EYNMxgf-7ghzL5K8lKZBZfW7g5CsdY0Xuj4IYmU8RPk,1381
54
- notionary-0.1.27.dist-info/licenses/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
55
- notionary-0.1.27.dist-info/METADATA,sha256=k1K58w6kqtLVWc9pvRgH1O5kFuCR-qivL-vNk9C2IJA,8342
56
- notionary-0.1.27.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
57
- notionary-0.1.27.dist-info/top_level.txt,sha256=fhONa6BMHQXqthx5PanWGbPL0b8rdFqhrJKVLf_adSs,10
58
- notionary-0.1.27.dist-info/RECORD,,
54
+ notionary-0.1.29.dist-info/licenses/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
55
+ notionary-0.1.29.dist-info/METADATA,sha256=69g2NERYbBfVTloeDP3yKBtTV_n2fL8iJ2UOrY9TdjQ,8342
56
+ notionary-0.1.29.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
57
+ notionary-0.1.29.dist-info/top_level.txt,sha256=fhONa6BMHQXqthx5PanWGbPL0b8rdFqhrJKVLf_adSs,10
58
+ notionary-0.1.29.dist-info/RECORD,,