notionary 0.1.13__py3-none-any.whl → 0.1.15__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 (37) hide show
  1. notionary/__init__.py +2 -2
  2. notionary/{converters/elements → elements}/audio_element.py +1 -1
  3. notionary/{converters/registry → elements}/block_element_registry.py +2 -5
  4. notionary/elements/block_element_registry_builder.py +383 -0
  5. notionary/{converters/elements → elements}/bookmark_element.py +1 -1
  6. notionary/{converters/elements → elements}/callout_element.py +2 -2
  7. notionary/{converters/elements → elements}/code_block_element.py +1 -1
  8. notionary/{converters/elements → elements}/column_element.py +1 -1
  9. notionary/{converters/elements → elements}/divider_element.py +1 -1
  10. notionary/{converters/elements → elements}/embed_element.py +1 -1
  11. notionary/{converters/elements → elements}/heading_element.py +2 -2
  12. notionary/{converters/elements → elements}/image_element.py +1 -1
  13. notionary/{converters/elements → elements}/list_element.py +2 -2
  14. notionary/elements/mention_element.py +227 -0
  15. notionary/{converters/elements → elements}/paragraph_element.py +2 -2
  16. notionary/{converters/elements → elements}/qoute_element.py +1 -1
  17. notionary/{converters/elements → elements}/table_element.py +2 -2
  18. notionary/{converters/elements → elements}/todo_lists.py +2 -2
  19. notionary/{converters/elements → elements}/toggle_element.py +1 -1
  20. notionary/{converters/elements → elements}/video_element.py +1 -1
  21. notionary/notion_client.py +55 -5
  22. notionary/page/content/page_content_manager.py +98 -26
  23. notionary/{converters → page}/markdown_to_notion_converter.py +2 -4
  24. notionary/page/notion_page.py +23 -5
  25. notionary/page/notion_page_factory.py +1 -15
  26. notionary/page/notion_to_markdown_converter.py +261 -0
  27. {notionary-0.1.13.dist-info → notionary-0.1.15.dist-info}/METADATA +1 -1
  28. notionary-0.1.15.dist-info/RECORD +56 -0
  29. notionary/converters/__init__.py +0 -50
  30. notionary/converters/notion_to_markdown_converter.py +0 -45
  31. notionary/converters/registry/block_element_registry_builder.py +0 -284
  32. notionary-0.1.13.dist-info/RECORD +0 -56
  33. /notionary/{converters/elements → elements}/notion_block_element.py +0 -0
  34. /notionary/{converters/elements → elements}/text_inline_formatter.py +0 -0
  35. {notionary-0.1.13.dist-info → notionary-0.1.15.dist-info}/WHEEL +0 -0
  36. {notionary-0.1.13.dist-info → notionary-0.1.15.dist-info}/licenses/LICENSE +0 -0
  37. {notionary-0.1.13.dist-info → notionary-0.1.15.dist-info}/top_level.txt +0 -0
notionary/__init__.py CHANGED
@@ -7,8 +7,8 @@ from .database.database_discovery import DatabaseDiscovery
7
7
  from .page.notion_page import NotionPage
8
8
  from .page.notion_page_factory import NotionPageFactory
9
9
 
10
- from .converters.registry.block_element_registry import BlockElementRegistry
11
- from .converters.registry.block_element_registry_builder import (
10
+ from .elements.block_element_registry import BlockElementRegistry
11
+ from .elements.block_element_registry_builder import (
12
12
  BlockElementRegistryBuilder,
13
13
  )
14
14
 
@@ -1,6 +1,6 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
- from notionary.converters.elements.notion_block_element import NotionBlockElement
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
 
5
5
 
6
6
  class AudioElement(NotionBlockElement):
@@ -1,7 +1,7 @@
1
1
  from typing import Dict, Any, Optional, List, Type
2
2
 
3
- from notionary.converters.elements.notion_block_element import NotionBlockElement
4
- from notionary.converters.elements.text_inline_formatter import TextInlineFormatter
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
+ from notionary.elements.text_inline_formatter import TextInlineFormatter
5
5
 
6
6
 
7
7
  class BlockElementRegistry:
@@ -96,9 +96,6 @@ class BlockElementRegistry:
96
96
  # Create a copy of registered elements
97
97
  element_classes = self._elements.copy()
98
98
 
99
- # TODO: Das hier besser formattieren und über debug level lösen . )
100
- print("Elements in registry:", element_classes)
101
-
102
99
  formatter_names = [e.__name__ for e in element_classes]
103
100
  if "TextInlineFormatter" not in formatter_names:
104
101
  element_classes = [TextInlineFormatter] + element_classes
@@ -0,0 +1,383 @@
1
+ from __future__ import annotations
2
+ from typing import List, Type
3
+ from collections import OrderedDict
4
+
5
+ from notionary.elements.audio_element import AudioElement
6
+ from notionary.elements.embed_element import EmbedElement
7
+ from notionary.elements.mention_element import MentionElement
8
+ from notionary.elements.notion_block_element import NotionBlockElement
9
+ from notionary.elements.block_element_registry import (
10
+ BlockElementRegistry,
11
+ )
12
+
13
+ from notionary.elements.paragraph_element import ParagraphElement
14
+ from notionary.elements.heading_element import HeadingElement
15
+ from notionary.elements.callout_element import CalloutElement
16
+ from notionary.elements.code_block_element import CodeBlockElement
17
+ from notionary.elements.divider_element import DividerElement
18
+ from notionary.elements.table_element import TableElement
19
+ from notionary.elements.todo_lists import TodoElement
20
+ from notionary.elements.list_element import (
21
+ BulletedListElement,
22
+ NumberedListElement,
23
+ )
24
+ from notionary.elements.qoute_element import QuoteElement
25
+ from notionary.elements.image_element import ImageElement
26
+ from notionary.elements.video_element import VideoElement
27
+ from notionary.elements.toggle_element import ToggleElement
28
+ from notionary.elements.bookmark_element import BookmarkElement
29
+ from notionary.elements.column_element import ColumnElement
30
+
31
+
32
+ class BlockElementRegistryBuilder:
33
+ """
34
+ True builder for constructing BlockElementRegistry instances.
35
+
36
+ This builder allows for incremental construction of registry instances
37
+ with specific configurations of block elements.
38
+ """
39
+
40
+ def __init__(self):
41
+ """Initialize a new builder with an empty element list."""
42
+ self._elements = OrderedDict()
43
+
44
+ @classmethod
45
+ def start_empty(cls) -> BlockElementRegistryBuilder:
46
+ """
47
+ Start with a completely empty registry builder.
48
+
49
+ Returns:
50
+ A new builder instance with no elements
51
+ """
52
+ return cls()
53
+
54
+ @classmethod
55
+ def start_minimal(cls) -> BlockElementRegistryBuilder:
56
+ """
57
+ Start with a minimal set of essential elements.
58
+
59
+ Returns:
60
+ A new builder instance with basic elements
61
+ """
62
+ builder = cls()
63
+ return builder.with_headings().with_lists().with_paragraphs()
64
+
65
+ @classmethod
66
+ def start_standard(cls) -> BlockElementRegistryBuilder:
67
+ """
68
+ Start with all standard elements in recommended order.
69
+
70
+ Returns:
71
+ A new builder instance with all standard elements
72
+ """
73
+ builder = cls()
74
+ return (
75
+ builder.with_headings()
76
+ .with_callouts()
77
+ .with_code()
78
+ .with_dividers()
79
+ .with_tables()
80
+ .with_columns()
81
+ .with_lists()
82
+ .with_toggles()
83
+ .with_quotes()
84
+ .with_todos()
85
+ .with_bookmarks()
86
+ .with_images()
87
+ .with_videos()
88
+ .with_embeds()
89
+ .with_audio()
90
+ .with_mention()
91
+ .with_paragraphs()
92
+ )
93
+
94
+ # Element manipulation methods
95
+
96
+ def add_element(
97
+ self, element_class: Type[NotionBlockElement]
98
+ ) -> BlockElementRegistryBuilder:
99
+ """
100
+ Add an element class to the registry configuration.
101
+ If the element already exists, it's moved to the end.
102
+
103
+ Args:
104
+ element_class: The element class to add
105
+
106
+ Returns:
107
+ Self for method chaining
108
+ """
109
+ self._elements.pop(element_class.__name__, None)
110
+ self._elements[element_class.__name__] = element_class
111
+
112
+ return self
113
+
114
+ def add_elements(
115
+ self, element_classes: List[Type[NotionBlockElement]]
116
+ ) -> BlockElementRegistryBuilder:
117
+ """
118
+ Add multiple element classes to the registry configuration.
119
+
120
+ Args:
121
+ element_classes: List of element classes to add
122
+
123
+ Returns:
124
+ Self for method chaining
125
+ """
126
+ for element_class in element_classes:
127
+ self.add_element(element_class)
128
+ return self
129
+
130
+ def remove_element(
131
+ self, element_class: Type[NotionBlockElement]
132
+ ) -> BlockElementRegistryBuilder:
133
+ """
134
+ Remove an element class from the registry configuration.
135
+
136
+ Args:
137
+ element_class: The element class to remove
138
+
139
+ Returns:
140
+ Self for method chaining
141
+ """
142
+ self._elements.pop(element_class.__name__, None)
143
+ return self
144
+
145
+ def move_element_to_end(
146
+ self, element_class: Type[NotionBlockElement]
147
+ ) -> BlockElementRegistryBuilder:
148
+ """
149
+ Move an existing element to the end of the registry.
150
+ If the element doesn't exist, it will be added.
151
+
152
+ Args:
153
+ element_class: The element class to move
154
+
155
+ Returns:
156
+ Self for method chaining
157
+ """
158
+ return self.add_element(element_class)
159
+
160
+ def _ensure_paragraph_at_end(self) -> None:
161
+ """
162
+ Internal method to ensure ParagraphElement is the last element in the registry.
163
+ """
164
+ if ParagraphElement.__name__ in self._elements:
165
+ paragraph_class = self._elements.pop(ParagraphElement.__name__)
166
+ self._elements[ParagraphElement.__name__] = paragraph_class
167
+
168
+ def with_paragraphs(self) -> BlockElementRegistryBuilder:
169
+ """
170
+ Add support for paragraph elements.
171
+
172
+ Returns:
173
+ Self for method chaining
174
+ """
175
+ return self.add_element(ParagraphElement)
176
+
177
+ def with_headings(self) -> BlockElementRegistryBuilder:
178
+ """
179
+ Add support for heading elements.
180
+
181
+ Returns:
182
+ Self for method chaining
183
+ """
184
+ return self.add_element(HeadingElement)
185
+
186
+ def with_callouts(self) -> BlockElementRegistryBuilder:
187
+ """
188
+ Add support for callout elements.
189
+
190
+ Returns:
191
+ Self for method chaining
192
+ """
193
+ return self.add_element(CalloutElement)
194
+
195
+ def with_code(self) -> BlockElementRegistryBuilder:
196
+ """
197
+ Add support for code blocks.
198
+
199
+ Returns:
200
+ Self for method chaining
201
+ """
202
+ return self.add_element(CodeBlockElement)
203
+
204
+ def with_dividers(self) -> BlockElementRegistryBuilder:
205
+ """
206
+ Add support for divider elements.
207
+
208
+ Returns:
209
+ Self for method chaining
210
+ """
211
+ return self.add_element(DividerElement)
212
+
213
+ def with_tables(self) -> BlockElementRegistryBuilder:
214
+ """
215
+ Add support for tables.
216
+
217
+ Returns:
218
+ Self for method chaining
219
+ """
220
+ return self.add_element(TableElement)
221
+
222
+ def with_columns(self) -> BlockElementRegistryBuilder:
223
+ """
224
+ Add support for column elements.
225
+
226
+ Returns:
227
+ Self for method chaining
228
+ """
229
+ return self.add_element(ColumnElement)
230
+
231
+ def with_lists(self) -> BlockElementRegistryBuilder:
232
+ """
233
+ Add support for list elements.
234
+
235
+ Returns:
236
+ Self for method chaining
237
+ """
238
+ return self.add_element(BulletedListElement).add_element(NumberedListElement)
239
+
240
+ def with_toggles(self) -> BlockElementRegistryBuilder:
241
+ """
242
+ Add support for toggle elements.
243
+
244
+ Returns:
245
+ Self for method chaining
246
+ """
247
+ return self.add_element(ToggleElement)
248
+
249
+ def with_quotes(self) -> BlockElementRegistryBuilder:
250
+ """
251
+ Add support for quote elements.
252
+
253
+ Returns:
254
+ Self for method chaining
255
+ """
256
+ return self.add_element(QuoteElement)
257
+
258
+ def with_todos(self) -> BlockElementRegistryBuilder:
259
+ """
260
+ Add support for todo elements.
261
+
262
+ Returns:
263
+ Self for method chaining
264
+ """
265
+ return self.add_element(TodoElement)
266
+
267
+ def with_bookmarks(self) -> BlockElementRegistryBuilder:
268
+ """
269
+ Add support for bookmark elements.
270
+
271
+ Returns:
272
+ Self for method chaining
273
+ """
274
+ return self.add_element(BookmarkElement)
275
+
276
+ def with_images(self) -> BlockElementRegistryBuilder:
277
+ """
278
+ Add support for image elements.
279
+
280
+ Returns:
281
+ Self for method chaining
282
+ """
283
+ return self.add_element(ImageElement)
284
+
285
+ def with_videos(self) -> BlockElementRegistryBuilder:
286
+ """
287
+ Add support for video elements.
288
+
289
+ Returns:
290
+ Self for method chaining
291
+ """
292
+ return self.add_element(VideoElement)
293
+
294
+ def with_embeds(self) -> BlockElementRegistryBuilder:
295
+ """
296
+ Add support for embed elements.
297
+
298
+ Returns:
299
+ Self for method chaining
300
+ """
301
+ return self.add_element(EmbedElement)
302
+
303
+ def with_audio(self) -> BlockElementRegistryBuilder:
304
+ """
305
+ Add support for audio elements.
306
+
307
+ Returns:
308
+ Self for method chaining
309
+ """
310
+ return self.add_element(AudioElement)
311
+
312
+ def with_media_support(self) -> BlockElementRegistryBuilder:
313
+ """
314
+ Add support for media elements (images, videos, audio).
315
+
316
+ Returns:
317
+ Self for method chaining
318
+ """
319
+ return self.with_images().with_videos().with_audio()
320
+
321
+ def with_mention(self) -> BlockElementRegistryBuilder:
322
+ return self.add_element(MentionElement)
323
+
324
+ def build(self) -> BlockElementRegistry:
325
+ """
326
+ Build and return the configured BlockElementRegistry instance.
327
+
328
+ This automatically ensures that ParagraphElement is at the end
329
+ of the registry (if present) as a fallback element, unless
330
+ this behavior was explicitly disabled.
331
+
332
+ Returns:
333
+ A configured BlockElementRegistry instance
334
+ """
335
+ if ParagraphElement.__name__ not in self._elements:
336
+ # Add paragraph as fallback if not present
337
+ self.add_element(ParagraphElement)
338
+ else:
339
+ # Ensure it's at the end
340
+ self._ensure_paragraph_at_end()
341
+
342
+ registry = BlockElementRegistry()
343
+
344
+ # Add elements in the recorded order
345
+ for element_class in self._elements.values():
346
+ registry.register(element_class)
347
+
348
+ return registry
349
+
350
+ @classmethod
351
+ def create_standard_registry(cls) -> BlockElementRegistry:
352
+ """
353
+ Factory method to directly create a standard registry.
354
+
355
+ Returns:
356
+ A fully configured registry instance
357
+ """
358
+ return cls.start_standard().build()
359
+
360
+ @classmethod
361
+ def create_minimal_registry(cls) -> BlockElementRegistry:
362
+ """
363
+ Factory method to directly create a minimal registry.
364
+
365
+ Returns:
366
+ A minimal registry instance
367
+ """
368
+ return cls.start_minimal().build()
369
+
370
+ @classmethod
371
+ def create_custom_registry(
372
+ cls, element_classes: List[Type[NotionBlockElement]]
373
+ ) -> BlockElementRegistry:
374
+ """
375
+ Factory method to directly create a custom registry.
376
+
377
+ Args:
378
+ element_classes: List of element classes to register
379
+
380
+ Returns:
381
+ A custom configured registry instance
382
+ """
383
+ return cls().add_elements(element_classes).build()
@@ -2,7 +2,7 @@ import re
2
2
  from typing import Dict, Any, Optional, List, Tuple
3
3
  from typing_extensions import override
4
4
 
5
- from notionary.converters.elements.notion_block_element import NotionBlockElement
5
+ from notionary.elements.notion_block_element import NotionBlockElement
6
6
 
7
7
 
8
8
  class BookmarkElement(NotionBlockElement):
@@ -2,8 +2,8 @@ from typing import Dict, Any, Optional
2
2
  from typing_extensions import override
3
3
  import re
4
4
 
5
- from notionary.converters.elements.text_inline_formatter import TextInlineFormatter
6
- from notionary.converters.elements.notion_block_element import NotionBlockElement
5
+ from notionary.elements.text_inline_formatter import TextInlineFormatter
6
+ from notionary.elements.notion_block_element import NotionBlockElement
7
7
 
8
8
 
9
9
  class CalloutElement(NotionBlockElement):
@@ -1,7 +1,7 @@
1
1
  from typing import Dict, Any, Optional, List, Tuple
2
2
  from typing_extensions import override
3
3
  import re
4
- from notionary.converters.elements.notion_block_element import NotionBlockElement
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
 
6
6
 
7
7
  class CodeBlockElement(NotionBlockElement):
@@ -2,7 +2,7 @@ import re
2
2
  from typing import Dict, Any, Optional, List, Tuple, Callable
3
3
  from typing_extensions import override
4
4
 
5
- from notionary.converters.elements.notion_block_element import NotionBlockElement
5
+ from notionary.elements.notion_block_element import NotionBlockElement
6
6
 
7
7
 
8
8
  class ColumnElement(NotionBlockElement):
@@ -4,7 +4,7 @@ from typing import Dict, Any, Optional
4
4
  from typing_extensions import override
5
5
  import re
6
6
 
7
- from notionary.converters.elements.notion_block_element import NotionBlockElement
7
+ from notionary.elements.notion_block_element import NotionBlockElement
8
8
 
9
9
 
10
10
  class DividerElement(NotionBlockElement):
@@ -1,6 +1,6 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
- from notionary.converters.elements.notion_block_element import NotionBlockElement
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
 
5
5
 
6
6
  class EmbedElement(NotionBlockElement):
@@ -2,8 +2,8 @@ from typing import Dict, Any, Optional
2
2
  from typing_extensions import override
3
3
  import re
4
4
 
5
- from notionary.converters.elements.notion_block_element import NotionBlockElement
6
- from notionary.converters.elements.text_inline_formatter import TextInlineFormatter
5
+ from notionary.elements.notion_block_element import NotionBlockElement
6
+ from notionary.elements.text_inline_formatter import TextInlineFormatter
7
7
 
8
8
 
9
9
  class HeadingElement(NotionBlockElement):
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
3
  from typing_extensions import override
4
- from notionary.converters.elements.notion_block_element import NotionBlockElement
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
 
6
6
 
7
7
  class ImageElement(NotionBlockElement):
@@ -1,8 +1,8 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional
3
3
  from typing_extensions import override
4
- from notionary.converters.elements.notion_block_element import NotionBlockElement
5
- from notionary.converters.elements.text_inline_formatter import TextInlineFormatter
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
+ from notionary.elements.text_inline_formatter import TextInlineFormatter
6
6
 
7
7
 
8
8
  class BulletedListElement(NotionBlockElement):