notionary 0.1.16__py3-none-any.whl → 0.1.18__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.
- notionary/database/notion_database.py +20 -0
- notionary/page/content/page_content_manager.py +1 -3
- {notionary-0.1.16.dist-info → notionary-0.1.18.dist-info}/METADATA +89 -43
- {notionary-0.1.16.dist-info → notionary-0.1.18.dist-info}/RECORD +7 -7
- {notionary-0.1.16.dist-info → notionary-0.1.18.dist-info}/WHEEL +0 -0
- {notionary-0.1.16.dist-info → notionary-0.1.18.dist-info}/licenses/LICENSE +0 -0
- {notionary-0.1.16.dist-info → notionary-0.1.18.dist-info}/top_level.txt +0 -0
@@ -217,6 +217,26 @@ class NotionDatabase(LoggingMixin):
|
|
217
217
|
self.logger.error("Error in delete_page: %s", str(e))
|
218
218
|
return {"success": False, "message": f"Error: {str(e)}"}
|
219
219
|
|
220
|
+
async def get_last_edited_time(self) -> Optional[str]:
|
221
|
+
"""
|
222
|
+
Retrieve the last edited time of the database.
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
ISO 8601 timestamp string of the last database edit, or None if request fails
|
226
|
+
"""
|
227
|
+
try:
|
228
|
+
response = await self._client.get(f"databases/{self.database_id}")
|
229
|
+
|
230
|
+
if response and "last_edited_time" in response:
|
231
|
+
return response["last_edited_time"]
|
232
|
+
|
233
|
+
self.logger.warning("Could not retrieve last_edited_time for database %s", self.database_id)
|
234
|
+
return None
|
235
|
+
|
236
|
+
except Exception as e:
|
237
|
+
self.logger.error("Error fetching last_edited_time: %s", str(e))
|
238
|
+
return None
|
239
|
+
|
220
240
|
async def close(self) -> None:
|
221
241
|
"""Close the client connection."""
|
222
242
|
await self._client.close()
|
@@ -39,8 +39,7 @@ class PageContentManager(LoggingMixin):
|
|
39
39
|
"""
|
40
40
|
try:
|
41
41
|
blocks = self._markdown_to_notion_converter.convert(markdown_text)
|
42
|
-
|
43
|
-
|
42
|
+
|
44
43
|
fixed_blocks = self._chunker.fix_blocks_content_length(blocks)
|
45
44
|
|
46
45
|
result = await self._client.patch(
|
@@ -173,5 +172,4 @@ class PageContentManager(LoggingMixin):
|
|
173
172
|
|
174
173
|
async def get_text(self) -> str:
|
175
174
|
blocks = await self.get_page_blocks_with_children()
|
176
|
-
print(json.dumps(blocks, indent=4))
|
177
175
|
return self._notion_to_markdown_converter.convert(blocks)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: notionary
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.18
|
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
|
@@ -33,12 +33,14 @@ Dynamic: summary
|
|
33
33
|
[](https://www.python.org/downloads/)
|
34
34
|
[](LICENSE)
|
35
35
|
|
36
|
-
**Notionary** is a powerful Python library for interacting with the Notion API, making it easy to create, update, and manage Notion pages and databases programmatically with a clean, intuitive interface.
|
36
|
+
**Notionary** is a powerful Python library for interacting with the Notion API, making it easy to create, update, and manage Notion pages and databases programmatically with a clean, intuitive interface. It's specifically designed to be the foundation for AI-driven Notion content generation.
|
37
37
|
|
38
38
|
## Features
|
39
39
|
|
40
|
-
- **Rich Markdown Support**:
|
40
|
+
- **Rich Markdown Support**: Create Notion pages using intuitive Markdown syntax with custom extensions
|
41
41
|
- **Dynamic Database Operations**: Create, update, and query database entries with schema auto-detection
|
42
|
+
- **Extensible Block Registry**: Add, customize, or remove Notion block elements with a flexible registry pattern
|
43
|
+
- **LLM-Ready Prompts**: Generate system prompts explaining Markdown syntax for LLMs to create Notion content
|
42
44
|
- **Async-First Design**: Built for modern Python with full async/await support
|
43
45
|
- **Schema-Based Validation**: Automatic property validation based on database schemas
|
44
46
|
- **Intelligent Content Conversion**: Bidirectional conversion between Markdown and Notion blocks
|
@@ -56,7 +58,7 @@ Notionary extends standard Markdown with special syntax to support Notion-specif
|
|
56
58
|
### Text Formatting
|
57
59
|
|
58
60
|
- Standard Markdown: `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
|
59
|
-
- Highlights: `==highlighted text==`, `==red
|
61
|
+
- Highlights: `==highlighted text==`, `==red:warning==`, `==blue:note==`
|
60
62
|
|
61
63
|
### Block Elements
|
62
64
|
|
@@ -111,50 +113,43 @@ Notionary makes it easy to work with Notion databases, automatically handling sc
|
|
111
113
|
|
112
114
|
```python
|
113
115
|
import asyncio
|
114
|
-
from notionary
|
116
|
+
from notionary import NotionDatabaseFactory
|
115
117
|
|
116
118
|
async def main():
|
117
|
-
|
118
|
-
|
119
|
-
await db.initialize()
|
119
|
+
# Find database by name with fuzzy matching
|
120
|
+
db_manager = await NotionDatabaseFactory.from_database_name("Projects")
|
120
121
|
|
122
|
+
# Create a new page with properties
|
121
123
|
properties = {
|
122
124
|
"Title": "Created via Notionary",
|
123
|
-
"Description": "This entry was created using Notionary.",
|
124
125
|
"Status": "In Progress",
|
125
126
|
"Priority": "High"
|
126
127
|
}
|
127
128
|
|
128
|
-
|
129
|
+
page = await db_manager.create_blank_page()
|
129
130
|
|
130
|
-
|
131
|
-
|
132
|
-
|
131
|
+
# Set page content with rich Markdown
|
132
|
+
await page.set_title("My New Project")
|
133
|
+
await page.set_page_icon(emoji="🚀")
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
"status": {"equals": "Completed"}
|
137
|
-
}
|
135
|
+
markdown = """
|
136
|
+
# Project Overview
|
138
137
|
|
139
|
-
|
138
|
+
!> [💡] This page was created programmatically using Notionary.
|
140
139
|
|
141
|
-
|
140
|
+
## Tasks
|
141
|
+
- [ ] Define project scope
|
142
|
+
- [ ] Create timeline
|
143
|
+
- [ ] Assign resources
|
142
144
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
## Finding Databases by Name
|
148
|
-
|
149
|
-
Use fuzzy matching to find databases:
|
145
|
+
+++ Implementation Details
|
146
|
+
This project will use our standard architecture with custom extensions.
|
147
|
+
"""
|
150
148
|
|
151
|
-
|
152
|
-
from notionary.core.database.notion_database_manager_factory import NotionDatabaseFactory
|
149
|
+
await page.replace_content(markdown)
|
153
150
|
|
154
|
-
|
155
|
-
|
156
|
-
print(f"Found database: {db_manager.title}")
|
157
|
-
await db_manager.close()
|
151
|
+
if __name__ == "__main__":
|
152
|
+
asyncio.run(main())
|
158
153
|
```
|
159
154
|
|
160
155
|
## Page Content Management
|
@@ -162,11 +157,11 @@ async def main():
|
|
162
157
|
Create rich Notion pages using enhanced Markdown:
|
163
158
|
|
164
159
|
```python
|
165
|
-
from notionary
|
160
|
+
from notionary import NotionPage
|
166
161
|
|
167
162
|
async def create_rich_page():
|
168
163
|
url = "https://www.notion.so/Your-Page-1cd389d57bd381e58be9d35ce24adf3d"
|
169
|
-
page_manager =
|
164
|
+
page_manager = NotionPage(url=url)
|
170
165
|
|
171
166
|
await page_manager.set_title("Notionary Demo")
|
172
167
|
await page_manager.set_page_icon(emoji="✨")
|
@@ -190,20 +185,71 @@ async def create_rich_page():
|
|
190
185
|
await page_manager.replace_content(markdown)
|
191
186
|
```
|
192
187
|
|
193
|
-
##
|
188
|
+
## Block Registry & Builder
|
194
189
|
|
195
|
-
|
196
|
-
|
197
|
-
|
190
|
+
Notionary uses a flexible registry pattern with a builder to customize which Notion elements are supported, allowing programmatic creation of complex UI layouts that were previously only possible through Notion's UI:
|
191
|
+
|
192
|
+
```python
|
193
|
+
from notionary import NotionPage
|
194
|
+
from notionary.elements.block_element_registry_builder import BlockElementRegistryBuilder
|
195
|
+
|
196
|
+
# Create a registry with standard Notion elements
|
197
|
+
registry = BlockElementRegistryBuilder.create_standard_registry()
|
198
|
+
|
199
|
+
# Or build a custom registry with only the elements you need
|
200
|
+
custom_registry = (
|
201
|
+
BlockElementRegistryBuilder()
|
202
|
+
.with_headings()
|
203
|
+
.with_callouts()
|
204
|
+
.with_toggles()
|
205
|
+
.with_lists()
|
206
|
+
.with_tables()
|
207
|
+
.with_paragraphs()
|
208
|
+
.build()
|
209
|
+
)
|
210
|
+
|
211
|
+
# Apply this registry to a page to enable custom Markdown support
|
212
|
+
page = NotionPage(url="https://www.notion.so/your-page-url")
|
213
|
+
page.block_registry = custom_registry
|
214
|
+
|
215
|
+
# Now your page supports exactly the elements you've defined
|
216
|
+
await page.replace_content("# Custom heading with only selected elements")
|
217
|
+
```
|
218
|
+
|
219
|
+
This registry approach gives you granular control over which Notion UI elements can be created through Markdown, making it possible to programmatically construct any page layout that would normally require manual UI interaction.
|
220
|
+
|
221
|
+
## AI-Ready LLM Prompt Generation
|
222
|
+
|
223
|
+
Notionary can automatically generate comprehensive system prompts for LLMs to understand Notion's custom Markdown syntax:
|
224
|
+
|
225
|
+
```python
|
226
|
+
from notionary.elements.block_element_registry_builder import BlockElementRegistryBuilder
|
227
|
+
|
228
|
+
registry = BlockElementRegistryBuilder.create_standard_registry()
|
229
|
+
llm_system_prompt = registry.generate_llm_prompt()
|
230
|
+
|
231
|
+
# Use this prompt with your LLM to generate Notion-compatible Markdown
|
232
|
+
print(llm_system_prompt)
|
233
|
+
```
|
234
|
+
|
235
|
+
This makes Notionary the perfect foundation for AI-driven Notion content generation, enabling LLMs to create properly formatted Notion pages.
|
198
236
|
|
199
237
|
## Examples
|
200
238
|
|
201
|
-
See the
|
239
|
+
See the [examples folder](examples/) for more comprehensive demonstrations:
|
240
|
+
|
241
|
+
- [Database discovery and querying](examples/database_discovery_example.py)
|
242
|
+
- [Rich page creation with Markdown](examples/page_example.py)
|
243
|
+
- [Database factory usage](examples/database_factory_example.py)
|
244
|
+
- [Page lookup and access](examples/page_factory_by_url_example.py)
|
245
|
+
- [Iterating through database entries](examples/iter_database_example.py)
|
246
|
+
|
247
|
+
## Perfect for AI Agents and Automation
|
202
248
|
|
203
|
-
-
|
204
|
-
-
|
205
|
-
-
|
206
|
-
-
|
249
|
+
- **LLM Integration**: Generate Notion-compatible content with LLMs using the system prompt generator
|
250
|
+
- **Dynamic Content Generation**: AI agents can generate content in Markdown and render it as Notion pages
|
251
|
+
- **Schema-Aware Operations**: Automatically validate and format properties
|
252
|
+
- **Simplified API**: Easier integration with AI workflows
|
207
253
|
|
208
254
|
## License
|
209
255
|
|
@@ -2,7 +2,7 @@ notionary/__init__.py,sha256=sVqdwzMQcc9jf6FKi1qflilsx8rnWzluVhWewVi5gyI,717
|
|
2
2
|
notionary/notion_client.py,sha256=NPPK7zId6EaC-hQeFJ7geaiROGtZfmc8cVP2nQez5DU,6040
|
3
3
|
notionary/database/database_discovery.py,sha256=qDGFhXG9s-_6CXdRg8tMiwX4dvX7jLjgAUFPSNlYtlI,4506
|
4
4
|
notionary/database/database_info_service.py,sha256=Ig6gx8jUSPYORJvfgEV5kV6t72pZQsWU8HPMqd43B-o,1336
|
5
|
-
notionary/database/notion_database.py,sha256=
|
5
|
+
notionary/database/notion_database.py,sha256=Zm5Ev0n4idKUe3ms8l3B4fyIezNNCCEDWHZ5vDoTknQ,7985
|
6
6
|
notionary/database/notion_database_factory.py,sha256=Af57yaUHidD8TKJ8uyXOc2nnqHm7on6VGFdDRjxiq9o,6692
|
7
7
|
notionary/database/models/page_result.py,sha256=Vmm5_oYpYAkIIJVoTd1ZZGloeC3cmFLMYP255mAmtaw,233
|
8
8
|
notionary/elements/audio_element.py,sha256=XLARz5zlPPW_Qof6uhcYXFmyYzyS1fLdxdfsvh6GMOs,5589
|
@@ -33,7 +33,7 @@ notionary/page/notion_page.py,sha256=KIjVeiMJGWWxR6ty1uuNvMoQf2IoRmSUxwMdDIyOu40
|
|
33
33
|
notionary/page/notion_page_factory.py,sha256=UUEZ-cyEWL0OMVPrgjc4vJdcplEa1bO2yHCYooACYC8,8189
|
34
34
|
notionary/page/notion_to_markdown_converter.py,sha256=WHrESgMZPqnp3kufi0YB7Cyy8U1rwhJ0d4HHdBRfRdU,8053
|
35
35
|
notionary/page/content/notion_page_content_chunker.py,sha256=xRks74Dqec-De6-AVTxMPnXs-MSJBzSm1HfJfaHiKr8,3330
|
36
|
-
notionary/page/content/page_content_manager.py,sha256=
|
36
|
+
notionary/page/content/page_content_manager.py,sha256=JM4ga-Y6k6mTbyH9YGYWbdrxpSLAdmZa845EwFyADMg,6142
|
37
37
|
notionary/page/metadata/metadata_editor.py,sha256=61uiw8oB25O8ePhytoJvZDetuof5sjPoM6aoHZGo4wc,4949
|
38
38
|
notionary/page/metadata/notion_icon_manager.py,sha256=ixZrWsHGVpmF05Ncy9LCt8vZlKAQHYFZW-2yI5JZZDI,1426
|
39
39
|
notionary/page/metadata/notion_page_cover_manager.py,sha256=qgQxQE-bx4oWjLFUQvpXD5GzO1Mx7w7htz1xC2BOqUg,1717
|
@@ -49,8 +49,8 @@ notionary/page/relations/relation_operation_result.py,sha256=NDxBzGntOxc_89ti-HG
|
|
49
49
|
notionary/util/logging_mixin.py,sha256=fKsx9t90bwvL74ZX3dU-sXdC4TZCQyO6qU9I8txkw_U,1369
|
50
50
|
notionary/util/page_id_utils.py,sha256=EYNMxgf-7ghzL5K8lKZBZfW7g5CsdY0Xuj4IYmU8RPk,1381
|
51
51
|
notionary/util/singleton_decorator.py,sha256=GTNMfIlVNRUVMw_c88xqd12-DcqZJjmyidN54yqiNVw,472
|
52
|
-
notionary-0.1.
|
53
|
-
notionary-0.1.
|
54
|
-
notionary-0.1.
|
55
|
-
notionary-0.1.
|
56
|
-
notionary-0.1.
|
52
|
+
notionary-0.1.18.dist-info/licenses/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
|
53
|
+
notionary-0.1.18.dist-info/METADATA,sha256=-k4dWxkINEoOhfulMYuFZvP7WVsgejcVdAypcX0ldDM,8522
|
54
|
+
notionary-0.1.18.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
55
|
+
notionary-0.1.18.dist-info/top_level.txt,sha256=fhONa6BMHQXqthx5PanWGbPL0b8rdFqhrJKVLf_adSs,10
|
56
|
+
notionary-0.1.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|