notionary 0.2.11__tar.gz → 0.2.13__tar.gz

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 (76) hide show
  1. {notionary-0.2.11 → notionary-0.2.13}/PKG-INFO +2 -1
  2. {notionary-0.2.11 → notionary-0.2.13}/notionary/__init__.py +0 -4
  3. notionary-0.2.13/notionary/cli/main.py +347 -0
  4. notionary-0.2.13/notionary/cli/onboarding.py +116 -0
  5. {notionary-0.2.11 → notionary-0.2.13}/notionary/database/notion_database.py +0 -2
  6. {notionary-0.2.11 → notionary-0.2.13}/notionary/database/notion_database_factory.py +0 -3
  7. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/audio_element.py +1 -2
  8. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/bookmark_element.py +1 -2
  9. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/bulleted_list_element.py +1 -2
  10. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/callout_element.py +1 -2
  11. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/code_block_element.py +1 -2
  12. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/column_element.py +1 -2
  13. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/divider_element.py +1 -2
  14. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/embed_element.py +1 -2
  15. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/heading_element.py +1 -2
  16. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/image_element.py +1 -2
  17. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/mention_element.py +1 -2
  18. notionary-0.2.13/notionary/elements/notion_block_element.py +35 -0
  19. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/numbered_list_element.py +1 -2
  20. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/paragraph_element.py +1 -2
  21. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/qoute_element.py +1 -2
  22. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/table_element.py +1 -2
  23. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/todo_element.py +1 -2
  24. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/toggle_element.py +1 -2
  25. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/toggleable_heading_element.py +1 -2
  26. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/video_element.py +1 -2
  27. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/notion_page_factory.py +0 -4
  28. {notionary-0.2.11 → notionary-0.2.13}/notionary.egg-info/PKG-INFO +2 -1
  29. {notionary-0.2.11 → notionary-0.2.13}/notionary.egg-info/SOURCES.txt +3 -3
  30. notionary-0.2.13/notionary.egg-info/entry_points.txt +2 -0
  31. {notionary-0.2.11 → notionary-0.2.13}/notionary.egg-info/requires.txt +1 -0
  32. {notionary-0.2.11 → notionary-0.2.13}/setup.py +7 -1
  33. notionary-0.2.11/notionary/elements/notion_block_element.py +0 -70
  34. notionary-0.2.11/notionary/telemetry/__init__.py +0 -7
  35. notionary-0.2.11/notionary/telemetry/telemetry.py +0 -226
  36. notionary-0.2.11/notionary/telemetry/track_usage_decorator.py +0 -76
  37. {notionary-0.2.11 → notionary-0.2.13}/LICENSE +0 -0
  38. {notionary-0.2.11 → notionary-0.2.13}/README.md +0 -0
  39. {notionary-0.2.11 → notionary-0.2.13}/notionary/database/database_discovery.py +0 -0
  40. {notionary-0.2.11 → notionary-0.2.13}/notionary/database/models/page_result.py +0 -0
  41. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/registry/block_registry.py +0 -0
  42. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/registry/block_registry_builder.py +0 -0
  43. {notionary-0.2.11 → notionary-0.2.13}/notionary/elements/text_inline_formatter.py +0 -0
  44. {notionary-0.2.11 → notionary-0.2.13}/notionary/exceptions/database_exceptions.py +0 -0
  45. {notionary-0.2.11 → notionary-0.2.13}/notionary/exceptions/page_creation_exception.py +0 -0
  46. {notionary-0.2.11 → notionary-0.2.13}/notionary/models/notion_block_response.py +0 -0
  47. {notionary-0.2.11 → notionary-0.2.13}/notionary/models/notion_database_response.py +0 -0
  48. {notionary-0.2.11 → notionary-0.2.13}/notionary/models/notion_page_response.py +0 -0
  49. {notionary-0.2.11 → notionary-0.2.13}/notionary/notion_client.py +0 -0
  50. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/content/notion_page_content_chunker.py +0 -0
  51. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/content/page_content_retriever.py +0 -0
  52. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/content/page_content_writer.py +0 -0
  53. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/formatting/markdown_to_notion_converter.py +0 -0
  54. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/formatting/spacer_rules.py +0 -0
  55. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/metadata/metadata_editor.py +0 -0
  56. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/metadata/notion_icon_manager.py +0 -0
  57. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/metadata/notion_page_cover_manager.py +0 -0
  58. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/notion_page.py +0 -0
  59. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/notion_to_markdown_converter.py +0 -0
  60. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/properites/database_property_service.py +0 -0
  61. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/properites/page_property_manager.py +0 -0
  62. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/properites/property_formatter.py +0 -0
  63. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/properites/property_value_extractor.py +0 -0
  64. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/relations/notion_page_relation_manager.py +0 -0
  65. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/relations/notion_page_title_resolver.py +0 -0
  66. {notionary-0.2.11 → notionary-0.2.13}/notionary/page/relations/page_database_relation.py +0 -0
  67. {notionary-0.2.11 → notionary-0.2.13}/notionary/prompting/element_prompt_content.py +0 -0
  68. {notionary-0.2.11 → notionary-0.2.13}/notionary/prompting/markdown_syntax_prompt_generator.py +0 -0
  69. {notionary-0.2.11 → notionary-0.2.13}/notionary/util/__init__.py +0 -0
  70. {notionary-0.2.11 → notionary-0.2.13}/notionary/util/logging_mixin.py +0 -0
  71. {notionary-0.2.11 → notionary-0.2.13}/notionary/util/page_id_utils.py +0 -0
  72. {notionary-0.2.11 → notionary-0.2.13}/notionary/util/singleton.py +0 -0
  73. {notionary-0.2.11 → notionary-0.2.13}/notionary/util/warn_direct_constructor_usage.py +0 -0
  74. {notionary-0.2.11 → notionary-0.2.13}/notionary.egg-info/dependency_links.txt +0 -0
  75. {notionary-0.2.11 → notionary-0.2.13}/notionary.egg-info/top_level.txt +0 -0
  76. {notionary-0.2.11 → notionary-0.2.13}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: notionary
3
- Version: 0.2.11
3
+ Version: 0.2.13
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
@@ -14,6 +14,7 @@ Requires-Dist: httpx>=0.28.0
14
14
  Requires-Dist: python-dotenv>=1.1.0
15
15
  Requires-Dist: pydantic>=2.11.4
16
16
  Requires-Dist: posthog>=3.0.0
17
+ Requires-Dist: click>=8.0.0
17
18
  Dynamic: author
18
19
  Dynamic: author-email
19
20
  Dynamic: classifier
@@ -14,10 +14,6 @@ from .elements.registry.block_registry_builder import (
14
14
  BlockRegistryBuilder,
15
15
  )
16
16
 
17
- from .telemetry.telemetry import NotionaryTelemetry
18
-
19
- _telemetry = NotionaryTelemetry()
20
-
21
17
  __all__ = [
22
18
  "NotionClient",
23
19
  "NotionDatabase",
@@ -0,0 +1,347 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Notionary CLI - Integration Key Setup
4
+ """
5
+
6
+ import click
7
+ import os
8
+ import platform
9
+ import asyncio
10
+ import logging
11
+ from pathlib import Path
12
+ from dotenv import load_dotenv
13
+ from rich.console import Console
14
+ from rich.panel import Panel
15
+ from rich.prompt import Prompt, Confirm
16
+ from rich.table import Table
17
+ from rich import box
18
+ from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
19
+ from notionary.notion_client import NotionClient
20
+ from notionary.database.database_discovery import DatabaseDiscovery
21
+
22
+ # Disable logging for CLI usage
23
+ def disable_notionary_logging():
24
+ """Disable logging for notionary modules when used in CLI"""
25
+ # Option 1: Set to WARNING level (recommended for CLI)
26
+ logging.getLogger('notionary').setLevel(logging.WARNING)
27
+ logging.getLogger('DatabaseDiscovery').setLevel(logging.WARNING)
28
+ logging.getLogger('NotionClient').setLevel(logging.WARNING)
29
+
30
+ def enable_verbose_logging():
31
+ """Enable verbose logging for debugging (use with --verbose flag)"""
32
+ logging.getLogger('notionary').setLevel(logging.DEBUG)
33
+ logging.getLogger('DatabaseDiscovery').setLevel(logging.DEBUG)
34
+ logging.getLogger('NotionClient').setLevel(logging.DEBUG)
35
+
36
+ # Initialize logging configuration for CLI
37
+ disable_notionary_logging()
38
+
39
+ console = Console()
40
+
41
+ def get_paste_tips():
42
+ """Get platform-specific paste tips"""
43
+ system = platform.system().lower()
44
+
45
+ if system == "darwin": # macOS
46
+ return [
47
+ "• Terminal: [cyan]Cmd+V[/cyan]",
48
+ "• iTerm2: [cyan]Cmd+V[/cyan]",
49
+ ]
50
+ elif system == "windows":
51
+ return [
52
+ "• PowerShell: [cyan]Right-click[/cyan] or [cyan]Shift+Insert[/cyan]",
53
+ "• cmd: [cyan]Right-click[/cyan]",
54
+ ]
55
+ else: # Linux and others
56
+ return [
57
+ "• Terminal: [cyan]Ctrl+Shift+V[/cyan] or [cyan]Right-click[/cyan]",
58
+ "• Some terminals: [cyan]Shift+Insert[/cyan]",
59
+ ]
60
+
61
+ def show_paste_tips():
62
+ """Show platform-specific paste tips"""
63
+ console.print("\n[bold yellow]💡 Paste Tips:[/bold yellow]")
64
+ for tip in get_paste_tips():
65
+ console.print(tip)
66
+ console.print()
67
+
68
+ def get_notion_secret() -> str:
69
+ """Get NOTION_SECRET using the same logic as NotionClient"""
70
+ load_dotenv()
71
+ return os.getenv("NOTION_SECRET", "")
72
+
73
+ async def fetch_notion_databases_with_progress():
74
+ """Fetch databases using DatabaseDiscovery with progress animation"""
75
+ try:
76
+ # Initialize NotionClient and DatabaseDiscovery
77
+ client = NotionClient()
78
+ discovery = DatabaseDiscovery(client)
79
+
80
+ # Create progress display with custom spinner
81
+ with Progress(
82
+ SpinnerColumn(spinner_name="dots12", style="cyan"),
83
+ TextColumn("[bold blue]Discovering databases..."),
84
+ TimeElapsedColumn(),
85
+ console=console,
86
+ transient=True
87
+ ) as progress:
88
+ # Add progress task
89
+ task = progress.add_task("Fetching...", total=None)
90
+
91
+ # Fetch databases
92
+ databases = await discovery._discover(page_size=50)
93
+
94
+ # Update progress to show completion
95
+ progress.update(task, description=f"[bold green]Found {len(databases)} databases!")
96
+
97
+ # Brief pause to show completion
98
+ await asyncio.sleep(0.5)
99
+
100
+ return {"databases": databases, "success": True}
101
+
102
+ except Exception as e:
103
+ return {"error": str(e), "success": False}
104
+
105
+ def show_databases_overview(api_key: str):
106
+ """Show available databases with nice formatting"""
107
+ console.print("\n[bold blue]🔍 Connecting to Notion...[/bold blue]")
108
+
109
+ # Run async function in sync context
110
+ try:
111
+ result = asyncio.run(fetch_notion_databases_with_progress())
112
+ except Exception as e:
113
+ console.print(Panel.fit(
114
+ f"[bold red]❌ Unexpected error[/bold red]\n\n"
115
+ f"[red]{str(e)}[/red]\n\n"
116
+ "[yellow]Please check:[/yellow]\n"
117
+ "• Your internet connection\n"
118
+ "• Your integration key validity\n"
119
+ "• Try running the command again",
120
+ title="Connection Error"
121
+ ))
122
+ return
123
+
124
+ if not result["success"]:
125
+ console.print(Panel.fit(
126
+ f"[bold red]❌ Could not fetch databases[/bold red]\n\n"
127
+ f"[red]{result['error']}[/red]\n\n"
128
+ "[yellow]Common issues:[/yellow]\n"
129
+ "• Check your integration key\n"
130
+ "• Make sure your integration has access to databases\n"
131
+ "• Visit your integration settings to grant access",
132
+ title="Connection Error"
133
+ ))
134
+ return
135
+
136
+ databases = result["databases"]
137
+
138
+ if not databases:
139
+ console.print(Panel.fit(
140
+ "[bold yellow]⚠️ No databases found[/bold yellow]\n\n"
141
+ "Your integration key is valid, but no databases are accessible.\n\n"
142
+ "[bold blue]To grant access:[/bold blue]\n"
143
+ "1. Go to any Notion database\n"
144
+ "2. Click the '...' menu (top right)\n"
145
+ "3. Go to 'Add connections'\n"
146
+ "4. Find and select your integration\n\n"
147
+ "[cyan]https://www.notion.so/help/add-and-manage-connections-with-the-api[/cyan]",
148
+ title="No Databases Available"
149
+ ))
150
+ return
151
+
152
+ # Create beautiful table
153
+ table = Table(
154
+ title=f"📊 Available Databases ({len(databases)} found)",
155
+ box=box.ROUNDED,
156
+ title_style="bold green",
157
+ header_style="bold cyan"
158
+ )
159
+
160
+ table.add_column("#", style="dim", justify="right", width=3)
161
+ table.add_column("Database Name", style="bold white", min_width=25)
162
+ table.add_column("ID", style="dim cyan", min_width=36)
163
+
164
+ for i, (title, db_id) in enumerate(databases, 1):
165
+ table.add_row(
166
+ str(i),
167
+ title or "Untitled Database",
168
+ db_id
169
+ )
170
+
171
+ console.print("\n")
172
+ console.print(table)
173
+
174
+ # Success message with next steps
175
+ console.print(Panel.fit(
176
+ "[bold green]🎉 Setup Complete![/bold green]\n\n"
177
+ f"Found [bold cyan]{len(databases)}[/bold cyan] accessible database(s).\n"
178
+ "You can now use notionary in your Python code!\n\n"
179
+ "[bold yellow]💡 Tip:[/bold yellow] Run [cyan]notionary db[/cyan] anytime to see this overview again.",
180
+ title="Ready to Go!"
181
+ ))
182
+
183
+ @click.group()
184
+ @click.version_option() # Automatische Version aus setup.py
185
+ @click.option('--verbose', '-v', is_flag=True, help='Enable verbose logging')
186
+ def main(verbose):
187
+ """
188
+ Notionary CLI - Notion API Integration
189
+ """
190
+ if verbose:
191
+ enable_verbose_logging()
192
+ console.print("[dim]Verbose logging enabled[/dim]")
193
+ pass
194
+
195
+ @main.command()
196
+ def init():
197
+ """
198
+ Setup your Notion Integration Key
199
+ """
200
+ # Check if key already exists
201
+ existing_key = get_notion_secret()
202
+
203
+ if existing_key:
204
+ console.print(Panel.fit(
205
+ "[bold green]✅ You're all set![/bold green]\n"
206
+ f"Your Notion Integration Key is already configured.\n"
207
+ f"Key: [dim]{existing_key[:8]}...[/dim]",
208
+ title="Already Configured"
209
+ ))
210
+
211
+ # Option to reconfigure or show databases
212
+ choice = Prompt.ask(
213
+ "\n[yellow]What would you like to do?[/yellow]",
214
+ choices=["show", "update", "exit"],
215
+ default="show"
216
+ )
217
+
218
+ if choice == "show":
219
+ show_databases_overview(existing_key)
220
+ elif choice == "update":
221
+ setup_new_key()
222
+ else:
223
+ console.print("\n[blue]Happy coding! 🚀[/blue]")
224
+ else:
225
+ # No key found, start setup
226
+ console.print(Panel.fit(
227
+ "[bold green]🚀 Notionary Setup[/bold green]\n"
228
+ "Enter your Notion Integration Key to get started...\n\n"
229
+ "[bold blue]🔗 Create an Integration Key or get an existing one:[/bold blue]\n"
230
+ "[cyan]https://www.notion.so/profile/integrations[/cyan]",
231
+ title="Initialization"
232
+ ))
233
+ setup_new_key()
234
+
235
+ @main.command()
236
+ def db() -> None:
237
+ """
238
+ Show available Notion databases
239
+ """
240
+ existing_key = get_notion_secret()
241
+
242
+ if not existing_key:
243
+ console.print(Panel.fit(
244
+ "[bold red]❌ No Integration Key found![/bold red]\n\n"
245
+ "Please run [cyan]notionary init[/cyan] first to set up your key.",
246
+ title="Not Configured"
247
+ ))
248
+ return
249
+
250
+ show_databases_overview(existing_key)
251
+
252
+ def setup_new_key():
253
+ """Handle the key setup process"""
254
+ try:
255
+ # Show Integration Key creation link
256
+ console.print("\n[bold blue]🔗 Create an Integration Key:[/bold blue]")
257
+ console.print("[cyan]https://www.notion.so/profile/integrations[/cyan]")
258
+ console.print()
259
+
260
+ # Get integration key
261
+ integration_key = Prompt.ask(
262
+ "[bold cyan]Notion Integration Key[/bold cyan]"
263
+ )
264
+
265
+ # Input validation
266
+ if not integration_key or not integration_key.strip():
267
+ console.print("[bold red]❌ Integration Key cannot be empty![/bold red]")
268
+ return
269
+
270
+ # Trim whitespace
271
+ integration_key = integration_key.strip()
272
+
273
+ # Check for common paste issues
274
+ if integration_key in ["^V", "^v", "^C", "^c"]:
275
+ console.print("[bold red]❌ Paste didn't work! Try:[/bold red]")
276
+ show_paste_tips()
277
+ return
278
+
279
+ # Show masked feedback that paste worked
280
+ masked_key = "•" * len(integration_key)
281
+ console.print(f"[dim]Received: {masked_key} ({len(integration_key)} characters)[/dim]")
282
+
283
+ # Basic validation for Notion keys
284
+ if not integration_key.startswith('ntn_') or len(integration_key) < 30:
285
+ console.print("[bold yellow]⚠️ Warning: This doesn't look like a valid Notion Integration Key[/bold yellow]")
286
+ console.print("[dim]Notion keys usually start with 'ntn_' and are about 50+ characters long[/dim]")
287
+ if not Confirm.ask("Continue anyway?"):
288
+ return
289
+
290
+ # Save the key
291
+ if save_integration_key(integration_key):
292
+ # Show databases overview after successful setup
293
+ show_databases_overview(integration_key)
294
+
295
+ except KeyboardInterrupt:
296
+ console.print("\n[yellow]Setup cancelled.[/yellow]")
297
+ except Exception as e:
298
+ console.print(f"\n[bold red]❌ Error during setup: {e}[/bold red]")
299
+ raise click.Abort()
300
+
301
+ def save_integration_key(integration_key: str) -> bool:
302
+ """Save the integration key to .env file"""
303
+ try:
304
+ # .env Datei im aktuellen Verzeichnis erstellen/aktualisieren
305
+ env_file = Path.cwd() / ".env"
306
+
307
+ # Bestehende .env lesen falls vorhanden
308
+ existing_lines = []
309
+ if env_file.exists():
310
+ with open(env_file, 'r', encoding='utf-8') as f:
311
+ existing_lines = [line.rstrip() for line in f.readlines()]
312
+
313
+ # NOTION_SECRET Zeile hinzufügen/ersetzen
314
+ updated_lines = []
315
+ notion_secret_found = False
316
+
317
+ for line in existing_lines:
318
+ if line.startswith('NOTION_SECRET='):
319
+ updated_lines.append(f'NOTION_SECRET={integration_key}')
320
+ notion_secret_found = True
321
+ else:
322
+ updated_lines.append(line)
323
+
324
+ # Falls NOTION_SECRET noch nicht existiert, hinzufügen
325
+ if not notion_secret_found:
326
+ updated_lines.append(f'NOTION_SECRET={integration_key}')
327
+
328
+ # .env Datei schreiben
329
+ with open(env_file, 'w', encoding='utf-8') as f:
330
+ f.write('\n'.join(updated_lines) + '\n')
331
+
332
+ # Verification
333
+ written_key = get_notion_secret()
334
+ if written_key == integration_key:
335
+ console.print("\n[bold green]✅ Integration Key saved and verified![/bold green]")
336
+ console.print(f"[dim]Configuration: {env_file}[/dim]")
337
+ return True
338
+ else:
339
+ console.print("\n[bold red]❌ Error: Key verification failed![/bold red]")
340
+ return False
341
+
342
+ except Exception as e:
343
+ console.print(f"\n[bold red]❌ Error saving key: {e}[/bold red]")
344
+ return False
345
+
346
+ if __name__ == '__main__':
347
+ main()
@@ -0,0 +1,116 @@
1
+ import asyncio
2
+ from dataclasses import dataclass
3
+ from notionary import NotionDatabase
4
+
5
+ @dataclass
6
+ class OnboardingPageResult:
7
+ url: str
8
+ tile: str
9
+ emoji: str
10
+
11
+ async def generate_doc_for_database(
12
+ datbase_name: str,
13
+ ) -> OnboardingPageResult:
14
+ database = await NotionDatabase.from_database_name(datbase_name)
15
+ page = await database.create_blank_page()
16
+
17
+ page_title = "Welcome to Notionary!"
18
+ page_icon = "📚"
19
+
20
+ markdown_content = """!> [🚀] This page was created fully automatically and serves as a showcase of what is possible with Notionary.
21
+
22
+ ---
23
+
24
+ ## 🗃️ Working with Databases
25
+
26
+ Discover and manage your Notion databases programmatically:
27
+
28
+ ```python
29
+ import asyncio
30
+ from notionary import NotionDatabase, DatabaseDiscovery
31
+
32
+ async def main():
33
+ # Discover available databases
34
+ discovery = DatabaseDiscovery()
35
+ await discovery()
36
+
37
+ # Connect to a database by name
38
+ db = await NotionDatabase.from_database_name("Projects")
39
+
40
+ # Create a new page in the database
41
+ page = await db.create_blank_page()
42
+
43
+ # Query pages from database
44
+ async for page in db.iter_pages():
45
+ title = await page.get_title()
46
+ print(f"Page: {title}")
47
+
48
+ if __name__ == "__main__":
49
+ asyncio.run(main())
50
+ ```
51
+
52
+ ## 📄 Creating and Managing Pages
53
+ Create and update Notion pages with rich content:
54
+ ```python
55
+ import asyncio
56
+ from notionary import NotionPage
57
+
58
+ async def main():
59
+ # Create a page from URL
60
+ page = NotionPage.from_url("https://www.notion.so/your-page-url")
61
+
62
+ # Or find by name
63
+ page = await NotionPage.from_page_name("My Project Page")
64
+
65
+ # Update page metadata
66
+ await page.set_title("Updated Title")
67
+ await page.set_emoji_icon("🚀")
68
+ await page.set_random_gradient_cover()
69
+
70
+ # Add markdown content
71
+ markdown = '''
72
+ # Project Overview
73
+
74
+ !> [💡] This page was created programmatically using Notionary.
75
+
76
+ ## Features
77
+ - **Rich** Markdown support
78
+ - Async functionality
79
+ - Custom syntax extensions
80
+ '''
81
+
82
+ await page.replace_content(markdown)
83
+
84
+ if __name__ == "__main__":
85
+ asyncio.run(main())
86
+ ```
87
+
88
+ ## 📊 Tables and Structured Data
89
+ Create tables for organizing information:
90
+ FeatureStatusPriorityAPI IntegrationCompleteHighDocumentationIn ProgressMediumDatabase QueriesCompleteHighFile UploadsCompleteMedium
91
+
92
+ 🎥 Media Embedding
93
+ Embed videos directly in your pages:
94
+ @[Caption](https://www.youtube.com/watch?v=dQw4w9WgXcQ) - Never gonna give you up!
95
+
96
+ Happy building with Notionary! 🎉"""
97
+
98
+
99
+ await page.set_title(page_title)
100
+ await page.set_emoji_icon(page_icon)
101
+ await page.set_random_gradient_cover()
102
+ await page.append_markdown(markdown_content)
103
+
104
+ url = await page.get_url()
105
+
106
+ return OnboardingPageResult(
107
+ url=url,
108
+ tile=page_title,
109
+ emoji=page_icon,
110
+ )
111
+
112
+
113
+ if __name__ == "__main__":
114
+ print("🚀 Starting Notionary onboarding page generation...")
115
+ result = asyncio.run(generate_doc_for_database("Wissen & Notizen"))
116
+ print(f"✅ Onboarding page created: {result.tile} {result.emoji} - {result.url}")
@@ -3,7 +3,6 @@ from typing import Any, AsyncGenerator, Dict, List, Optional
3
3
 
4
4
  from notionary.notion_client import NotionClient
5
5
  from notionary.page.notion_page import NotionPage
6
- from notionary.telemetry import NotionaryTelemetry
7
6
  from notionary.util.warn_direct_constructor_usage import warn_direct_constructor_usage
8
7
  from notionary.util import LoggingMixin
9
8
  from notionary.util.page_id_utils import format_uuid
@@ -26,7 +25,6 @@ class NotionDatabase(LoggingMixin):
26
25
  token: Optional Notion API token
27
26
  """
28
27
  self.database_id = database_id
29
- self._telemetry = NotionaryTelemetry.get_instance()
30
28
  self._client = NotionClient(token=token)
31
29
 
32
30
  @classmethod
@@ -10,7 +10,6 @@ from notionary.exceptions.database_exceptions import (
10
10
  DatabaseParsingError,
11
11
  NotionDatabaseException,
12
12
  )
13
- from notionary.telemetry import track_usage
14
13
  from notionary.util import LoggingMixin
15
14
  from notionary.util import format_uuid
16
15
  from notionary.util import singleton
@@ -24,7 +23,6 @@ class NotionDatabaseFactory(LoggingMixin):
24
23
  """
25
24
 
26
25
  @classmethod
27
- @track_usage('page_factory_method_used', {'method': 'from_page_id'})
28
26
  def from_database_id(
29
27
  cls, database_id: str, token: Optional[str] = None
30
28
  ) -> NotionDatabase:
@@ -59,7 +57,6 @@ class NotionDatabaseFactory(LoggingMixin):
59
57
  raise DatabaseConnectionError(error_msg) from e
60
58
 
61
59
  @classmethod
62
- @track_usage('page_factory_method_used', {'method': 'from_url'})
63
60
  async def from_database_name(
64
61
  cls, database_name: str, token: Optional[str] = None
65
62
  ) -> NotionDatabase:
@@ -1,12 +1,11 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
  from notionary.prompting.element_prompt_content import (
5
5
  ElementPromptBuilder,
6
6
  ElementPromptContent,
7
7
  )
8
8
 
9
- @auto_track_conversions
10
9
  class AudioElement(NotionBlockElement):
11
10
  """
12
11
  Handles conversion between Markdown audio embeds and Notion audio blocks.
@@ -1,13 +1,12 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List, Tuple
3
3
 
4
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
  from notionary.prompting.element_prompt_content import (
6
6
  ElementPromptBuilder,
7
7
  ElementPromptContent,
8
8
  )
9
9
 
10
- @auto_track_conversions
11
10
  class BookmarkElement(NotionBlockElement):
12
11
  """
13
12
  Handles conversion between Markdown bookmarks and Notion bookmark blocks.
@@ -1,13 +1,12 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional
3
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
  from notionary.prompting.element_prompt_content import (
5
5
  ElementPromptBuilder,
6
6
  ElementPromptContent,
7
7
  )
8
8
  from notionary.elements.text_inline_formatter import TextInlineFormatter
9
9
 
10
- @auto_track_conversions
11
10
  class BulletedListElement(NotionBlockElement):
12
11
  """Class for converting between Markdown bullet lists and Notion bulleted list items."""
13
12
 
@@ -6,9 +6,8 @@ from notionary.prompting.element_prompt_content import (
6
6
  ElementPromptContent,
7
7
  )
8
8
  from notionary.elements.text_inline_formatter import TextInlineFormatter
9
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
9
+ from notionary.elements.notion_block_element import NotionBlockElement
10
10
 
11
- @auto_track_conversions
12
11
  class CalloutElement(NotionBlockElement):
13
12
  """
14
13
  Handles conversion between Markdown callouts and Notion callout blocks.
@@ -1,12 +1,11 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List, Tuple
3
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
  from notionary.prompting.element_prompt_content import (
5
5
  ElementPromptBuilder,
6
6
  ElementPromptContent,
7
7
  )
8
8
 
9
- @auto_track_conversions
10
9
  class CodeBlockElement(NotionBlockElement):
11
10
  """
12
11
  Handles conversion between Markdown code blocks and Notion code blocks.
@@ -1,14 +1,13 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List, Tuple, Callable
3
3
 
4
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
  from notionary.page.formatting.spacer_rules import SPACER_MARKER
6
6
  from notionary.prompting.element_prompt_content import (
7
7
  ElementPromptBuilder,
8
8
  ElementPromptContent,
9
9
  )
10
10
 
11
- @auto_track_conversions
12
11
  class ColumnElement(NotionBlockElement):
13
12
  """
14
13
  Handles conversion between custom Markdown column syntax and Notion column blocks.
@@ -1,13 +1,12 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional
3
3
 
4
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
  from notionary.prompting.element_prompt_content import (
6
6
  ElementPromptBuilder,
7
7
  ElementPromptContent,
8
8
  )
9
9
 
10
- @auto_track_conversions
11
10
  class DividerElement(NotionBlockElement):
12
11
  """
13
12
  Handles conversion between Markdown horizontal dividers and Notion divider blocks.
@@ -1,12 +1,11 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
  from notionary.prompting.element_prompt_content import (
5
5
  ElementPromptBuilder,
6
6
  ElementPromptContent,
7
7
  )
8
8
 
9
- @auto_track_conversions
10
9
  class EmbedElement(NotionBlockElement):
11
10
  """
12
11
  Handles conversion between Markdown embeds and Notion embed blocks.
@@ -1,14 +1,13 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional
3
3
 
4
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
4
+ from notionary.elements.notion_block_element import NotionBlockElement
5
5
  from notionary.prompting.element_prompt_content import (
6
6
  ElementPromptBuilder,
7
7
  ElementPromptContent,
8
8
  )
9
9
  from notionary.elements.text_inline_formatter import TextInlineFormatter
10
10
 
11
- @auto_track_conversions
12
11
  class HeadingElement(NotionBlockElement):
13
12
  """Handles conversion between Markdown headings and Notion heading blocks."""
14
13
 
@@ -1,12 +1,11 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List
3
- from notionary.elements.notion_block_element import NotionBlockElement, auto_track_conversions
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
4
  from notionary.prompting.element_prompt_content import (
5
5
  ElementPromptBuilder,
6
6
  ElementPromptContent,
7
7
  )
8
8
 
9
- @auto_track_conversions
10
9
  class ImageElement(NotionBlockElement):
11
10
  """
12
11
  Handles conversion between Markdown images and Notion image blocks.