notionary 0.2.12__py3-none-any.whl → 0.2.14__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 (86) hide show
  1. notionary/__init__.py +3 -20
  2. notionary/{notion_client.py → base_notion_client.py} +92 -98
  3. notionary/blocks/__init__.py +61 -0
  4. notionary/{elements → blocks}/audio_element.py +6 -4
  5. notionary/{elements → blocks}/bookmark_element.py +3 -6
  6. notionary/{elements → blocks}/bulleted_list_element.py +5 -7
  7. notionary/{elements → blocks}/callout_element.py +5 -8
  8. notionary/{elements → blocks}/code_block_element.py +4 -6
  9. notionary/{elements → blocks}/column_element.py +3 -6
  10. notionary/{elements → blocks}/divider_element.py +3 -6
  11. notionary/{elements → blocks}/embed_element.py +4 -6
  12. notionary/{elements → blocks}/heading_element.py +5 -9
  13. notionary/{elements → blocks}/image_element.py +4 -6
  14. notionary/{elements → blocks}/mention_element.py +3 -7
  15. notionary/blocks/notion_block_client.py +26 -0
  16. notionary/blocks/notion_block_element.py +34 -0
  17. notionary/{elements → blocks}/numbered_list_element.py +4 -7
  18. notionary/{elements → blocks}/paragraph_element.py +4 -7
  19. notionary/{prompting/element_prompt_content.py → blocks/prompts/element_prompt_builder.py} +1 -40
  20. notionary/blocks/prompts/element_prompt_content.py +41 -0
  21. notionary/{elements → blocks}/qoute_element.py +4 -6
  22. notionary/{elements → blocks}/registry/block_registry.py +4 -26
  23. notionary/{elements → blocks}/registry/block_registry_builder.py +26 -25
  24. notionary/{elements → blocks}/table_element.py +6 -8
  25. notionary/{elements → blocks}/text_inline_formatter.py +1 -4
  26. notionary/{elements → blocks}/todo_element.py +6 -8
  27. notionary/{elements → blocks}/toggle_element.py +3 -6
  28. notionary/{elements → blocks}/toggleable_heading_element.py +5 -8
  29. notionary/{elements → blocks}/video_element.py +4 -6
  30. notionary/cli/main.py +245 -53
  31. notionary/cli/onboarding.py +117 -0
  32. notionary/database/__init__.py +0 -0
  33. notionary/database/client.py +132 -0
  34. notionary/database/database_exceptions.py +13 -0
  35. notionary/database/factory.py +0 -0
  36. notionary/database/filter_builder.py +175 -0
  37. notionary/database/notion_database.py +339 -128
  38. notionary/database/notion_database_provider.py +230 -0
  39. notionary/elements/__init__.py +0 -0
  40. notionary/models/notion_database_response.py +294 -13
  41. notionary/models/notion_page_response.py +9 -31
  42. notionary/models/search_response.py +0 -0
  43. notionary/page/__init__.py +0 -0
  44. notionary/page/client.py +110 -0
  45. notionary/page/content/page_content_retriever.py +5 -20
  46. notionary/page/content/page_content_writer.py +3 -4
  47. notionary/page/formatting/markdown_to_notion_converter.py +1 -3
  48. notionary/{prompting → page}/markdown_syntax_prompt_generator.py +1 -2
  49. notionary/page/notion_page.py +354 -317
  50. notionary/page/notion_to_markdown_converter.py +1 -4
  51. notionary/page/properites/property_value_extractor.py +0 -64
  52. notionary/page/{properites/property_formatter.py → property_formatter.py} +7 -4
  53. notionary/page/search_filter_builder.py +131 -0
  54. notionary/page/utils.py +60 -0
  55. notionary/util/__init__.py +12 -3
  56. notionary/util/factory_decorator.py +33 -0
  57. notionary/util/fuzzy_matcher.py +82 -0
  58. notionary/util/page_id_utils.py +0 -21
  59. notionary/util/singleton_metaclass.py +22 -0
  60. notionary/workspace.py +69 -0
  61. {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/METADATA +4 -1
  62. notionary-0.2.14.dist-info/RECORD +72 -0
  63. notionary/database/database_discovery.py +0 -142
  64. notionary/database/notion_database_factory.py +0 -193
  65. notionary/elements/notion_block_element.py +0 -70
  66. notionary/exceptions/database_exceptions.py +0 -76
  67. notionary/exceptions/page_creation_exception.py +0 -9
  68. notionary/page/metadata/metadata_editor.py +0 -150
  69. notionary/page/metadata/notion_icon_manager.py +0 -77
  70. notionary/page/metadata/notion_page_cover_manager.py +0 -56
  71. notionary/page/notion_page_factory.py +0 -332
  72. notionary/page/properites/database_property_service.py +0 -302
  73. notionary/page/properites/page_property_manager.py +0 -152
  74. notionary/page/relations/notion_page_relation_manager.py +0 -350
  75. notionary/page/relations/notion_page_title_resolver.py +0 -104
  76. notionary/page/relations/page_database_relation.py +0 -68
  77. notionary/telemetry/__init__.py +0 -7
  78. notionary/telemetry/telemetry.py +0 -226
  79. notionary/telemetry/track_usage_decorator.py +0 -76
  80. notionary/util/warn_direct_constructor_usage.py +0 -54
  81. notionary-0.2.12.dist-info/RECORD +0 -70
  82. /notionary/util/{singleton.py → singleton_decorator.py} +0 -0
  83. {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/WHEEL +0 -0
  84. {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/entry_points.txt +0 -0
  85. {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/licenses/LICENSE +0 -0
  86. {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,110 @@
1
+ from typing import Dict, Any, List, Optional
2
+ from notionary.base_notion_client import BaseNotionClient
3
+ from notionary.models.notion_page_response import NotionPageResponse
4
+ from notionary.models.notion_database_response import NotionQueryDatabaseResponse
5
+ from notionary.util import singleton
6
+
7
+
8
+ @singleton
9
+ class NotionPageClient(BaseNotionClient):
10
+ """
11
+ Client for Notion page-specific operations.
12
+ Inherits base HTTP functionality from BaseNotionClient.
13
+ """
14
+
15
+ async def get_page(self, page_id: str) -> NotionPageResponse:
16
+ """
17
+ Gets metadata for a Notion page by its ID.
18
+ """
19
+ response = await self.get(f"pages/{page_id}")
20
+ return NotionPageResponse.model_validate(response)
21
+
22
+ async def create_page(
23
+ self,
24
+ parent_database_id: Optional[str] = None,
25
+ properties: Optional[Dict[str, Any]] = None,
26
+ ) -> NotionPageResponse:
27
+ """
28
+ Creates a new page in a Notion database or as a child page.
29
+ """
30
+ page_data = {
31
+ "parent": {"database_id": parent_database_id} if parent_database_id else {},
32
+ "properties": properties or {},
33
+ }
34
+
35
+ response = await self.post("pages", page_data)
36
+ return NotionPageResponse.model_validate(response)
37
+
38
+ async def patch_page(
39
+ self, page_id: str, data: Optional[Dict[str, Any]] = None
40
+ ) -> NotionPageResponse:
41
+ """
42
+ Updates a Notion page with the provided data.
43
+ """
44
+ response = await self.patch(f"pages/{page_id}", data=data)
45
+ return NotionPageResponse.model_validate(response)
46
+
47
+ async def delete_page(self, page_id: str) -> bool:
48
+ """
49
+ Deletes (archives) a Notion page.
50
+ """
51
+ # Notion doesn't have a direct delete endpoint, we archive by setting archived=True
52
+ data = {"archived": True}
53
+ response = await self.patch(f"pages/{page_id}", data=data)
54
+ return response is not None
55
+
56
+ async def search_pages(
57
+ self, query: str, sort_ascending: bool = True, limit: int = 100
58
+ ) -> NotionQueryDatabaseResponse:
59
+ """
60
+ Searches for pages in Notion using the search endpoint.
61
+ """
62
+ from notionary.page.search_filter_builder import SearchFilterBuilder
63
+
64
+ search_filter = (
65
+ SearchFilterBuilder()
66
+ .with_query(query)
67
+ .with_pages_only()
68
+ .with_sort_direction("ascending" if sort_ascending else "descending")
69
+ .with_page_size(limit)
70
+ )
71
+
72
+ result = await self.post("search", search_filter.build())
73
+ return NotionQueryDatabaseResponse.model_validate(result)
74
+
75
+ async def update_page_properties(
76
+ self, page_id: str, properties: Dict[str, Any]
77
+ ) -> NotionPageResponse:
78
+ """
79
+ Updates only the properties of a Notion page.
80
+ """
81
+ data = {"properties": properties}
82
+ return await self.patch_page(page_id, data)
83
+
84
+ async def archive_page(self, page_id: str) -> NotionPageResponse:
85
+ """
86
+ Archives a Notion page (soft delete).
87
+ """
88
+ data = {"archived": True}
89
+ return await self.patch_page(page_id, data)
90
+
91
+ async def unarchive_page(self, page_id: str) -> NotionPageResponse:
92
+ """
93
+ Unarchives a previously archived Notion page.
94
+ """
95
+ data = {"archived": False}
96
+ return await self.patch_page(page_id, data)
97
+
98
+ async def get_page_blocks(self, page_id: str) -> List[Dict[str, Any]]:
99
+ """
100
+ Retrieves all blocks of a Notion page.
101
+ """
102
+ response = await self.get(f"blocks/{page_id}/children")
103
+ return response.get("results", [])
104
+
105
+ async def get_block_children(self, block_id: str) -> List[Dict[str, Any]]:
106
+ """
107
+ Retrieves all children blocks of a specific block.
108
+ """
109
+ response = await self.get(f"blocks/{block_id}/children")
110
+ return response.get("results", [])
@@ -1,8 +1,8 @@
1
1
  from typing import Any, Dict, List, Optional
2
2
 
3
- from notionary.elements.registry.block_registry import BlockRegistry
4
- from notionary.notion_client import NotionClient
3
+ from notionary.blocks.registry.block_registry import BlockRegistry
5
4
 
5
+ from notionary.blocks import NotionBlockClient
6
6
  from notionary.page.notion_to_markdown_converter import (
7
7
  NotionToMarkdownConverter,
8
8
  )
@@ -13,14 +13,13 @@ class PageContentRetriever(LoggingMixin):
13
13
  def __init__(
14
14
  self,
15
15
  page_id: str,
16
- client: NotionClient,
17
16
  block_registry: BlockRegistry,
18
17
  ):
19
18
  self.page_id = page_id
20
- self._client = client
21
19
  self._notion_to_markdown_converter = NotionToMarkdownConverter(
22
20
  block_registry=block_registry
23
21
  )
22
+ self.client = NotionBlockClient()
24
23
 
25
24
  async def get_page_content(self) -> str:
26
25
  blocks = await self._get_page_blocks_with_children()
@@ -30,9 +29,9 @@ class PageContentRetriever(LoggingMixin):
30
29
  self, parent_id: Optional[str] = None
31
30
  ) -> List[Dict[str, Any]]:
32
31
  blocks = (
33
- await self._get_blocks()
32
+ await self.client.get_page_blocks(page_id=self.page_id)
34
33
  if parent_id is None
35
- else await self._get_block_children(parent_id)
34
+ else await self.client.get_block_children(parent_id)
36
35
  )
37
36
 
38
37
  if not blocks:
@@ -51,17 +50,3 @@ class PageContentRetriever(LoggingMixin):
51
50
  block["children"] = children
52
51
 
53
52
  return blocks
54
-
55
- async def _get_blocks(self) -> List[Dict[str, Any]]:
56
- result = await self._client.get(f"blocks/{self.page_id}/children")
57
- if not result:
58
- self.logger.error("Error retrieving page content: %s", result.error)
59
- return []
60
- return result.get("results", [])
61
-
62
- async def _get_block_children(self, block_id: str) -> List[Dict[str, Any]]:
63
- result = await self._client.get(f"blocks/{block_id}/children")
64
- if not result:
65
- self.logger.error("Error retrieving block children: %s", result.error)
66
- return []
67
- return result.get("results", [])
@@ -1,9 +1,8 @@
1
1
  from typing import Any, Dict
2
2
 
3
- from notionary.elements.divider_element import DividerElement
4
- from notionary.elements.registry.block_registry import BlockRegistry
5
- from notionary.notion_client import NotionClient
3
+ from notionary.blocks import DividerElement, BlockRegistry
6
4
 
5
+ from notionary.page.client import NotionPageClient
7
6
  from notionary.page.formatting.markdown_to_notion_converter import (
8
7
  MarkdownToNotionConverter,
9
8
  )
@@ -20,7 +19,7 @@ class PageContentWriter(LoggingMixin):
20
19
  def __init__(
21
20
  self,
22
21
  page_id: str,
23
- client: NotionClient,
22
+ client: NotionPageClient,
24
23
  block_registry: BlockRegistry,
25
24
  ):
26
25
  self.page_id = page_id
@@ -1,9 +1,7 @@
1
1
  import re
2
2
  from typing import Dict, Any, List, Optional, Tuple
3
3
 
4
- from notionary.elements.column_element import ColumnElement
5
- from notionary.elements.registry.block_registry import BlockRegistry
6
- from notionary.elements.registry.block_registry_builder import BlockRegistryBuilder
4
+ from notionary.blocks import ColumnElement, BlockRegistry, BlockRegistryBuilder
7
5
  from notionary.page.formatting.spacer_rules import SpacerRule, SpacerRuleEngine
8
6
 
9
7
 
@@ -1,6 +1,5 @@
1
1
  from typing import Type, List
2
- from notionary.elements.notion_block_element import NotionBlockElement
3
- from notionary.elements.text_inline_formatter import TextInlineFormatter
2
+ from notionary.blocks import NotionBlockElement
4
3
 
5
4
 
6
5
  class MarkdownSyntaxPromptGenerator: