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.
- notionary/__init__.py +3 -20
- notionary/{notion_client.py → base_notion_client.py} +92 -98
- notionary/blocks/__init__.py +61 -0
- notionary/{elements → blocks}/audio_element.py +6 -4
- notionary/{elements → blocks}/bookmark_element.py +3 -6
- notionary/{elements → blocks}/bulleted_list_element.py +5 -7
- notionary/{elements → blocks}/callout_element.py +5 -8
- notionary/{elements → blocks}/code_block_element.py +4 -6
- notionary/{elements → blocks}/column_element.py +3 -6
- notionary/{elements → blocks}/divider_element.py +3 -6
- notionary/{elements → blocks}/embed_element.py +4 -6
- notionary/{elements → blocks}/heading_element.py +5 -9
- notionary/{elements → blocks}/image_element.py +4 -6
- notionary/{elements → blocks}/mention_element.py +3 -7
- notionary/blocks/notion_block_client.py +26 -0
- notionary/blocks/notion_block_element.py +34 -0
- notionary/{elements → blocks}/numbered_list_element.py +4 -7
- notionary/{elements → blocks}/paragraph_element.py +4 -7
- notionary/{prompting/element_prompt_content.py → blocks/prompts/element_prompt_builder.py} +1 -40
- notionary/blocks/prompts/element_prompt_content.py +41 -0
- notionary/{elements → blocks}/qoute_element.py +4 -6
- notionary/{elements → blocks}/registry/block_registry.py +4 -26
- notionary/{elements → blocks}/registry/block_registry_builder.py +26 -25
- notionary/{elements → blocks}/table_element.py +6 -8
- notionary/{elements → blocks}/text_inline_formatter.py +1 -4
- notionary/{elements → blocks}/todo_element.py +6 -8
- notionary/{elements → blocks}/toggle_element.py +3 -6
- notionary/{elements → blocks}/toggleable_heading_element.py +5 -8
- notionary/{elements → blocks}/video_element.py +4 -6
- notionary/cli/main.py +245 -53
- notionary/cli/onboarding.py +117 -0
- notionary/database/__init__.py +0 -0
- notionary/database/client.py +132 -0
- notionary/database/database_exceptions.py +13 -0
- notionary/database/factory.py +0 -0
- notionary/database/filter_builder.py +175 -0
- notionary/database/notion_database.py +339 -128
- notionary/database/notion_database_provider.py +230 -0
- notionary/elements/__init__.py +0 -0
- notionary/models/notion_database_response.py +294 -13
- notionary/models/notion_page_response.py +9 -31
- notionary/models/search_response.py +0 -0
- notionary/page/__init__.py +0 -0
- notionary/page/client.py +110 -0
- notionary/page/content/page_content_retriever.py +5 -20
- notionary/page/content/page_content_writer.py +3 -4
- notionary/page/formatting/markdown_to_notion_converter.py +1 -3
- notionary/{prompting → page}/markdown_syntax_prompt_generator.py +1 -2
- notionary/page/notion_page.py +354 -317
- notionary/page/notion_to_markdown_converter.py +1 -4
- notionary/page/properites/property_value_extractor.py +0 -64
- notionary/page/{properites/property_formatter.py → property_formatter.py} +7 -4
- notionary/page/search_filter_builder.py +131 -0
- notionary/page/utils.py +60 -0
- notionary/util/__init__.py +12 -3
- notionary/util/factory_decorator.py +33 -0
- notionary/util/fuzzy_matcher.py +82 -0
- notionary/util/page_id_utils.py +0 -21
- notionary/util/singleton_metaclass.py +22 -0
- notionary/workspace.py +69 -0
- {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/METADATA +4 -1
- notionary-0.2.14.dist-info/RECORD +72 -0
- notionary/database/database_discovery.py +0 -142
- notionary/database/notion_database_factory.py +0 -193
- notionary/elements/notion_block_element.py +0 -70
- notionary/exceptions/database_exceptions.py +0 -76
- notionary/exceptions/page_creation_exception.py +0 -9
- notionary/page/metadata/metadata_editor.py +0 -150
- notionary/page/metadata/notion_icon_manager.py +0 -77
- notionary/page/metadata/notion_page_cover_manager.py +0 -56
- notionary/page/notion_page_factory.py +0 -332
- notionary/page/properites/database_property_service.py +0 -302
- notionary/page/properites/page_property_manager.py +0 -152
- notionary/page/relations/notion_page_relation_manager.py +0 -350
- notionary/page/relations/notion_page_title_resolver.py +0 -104
- notionary/page/relations/page_database_relation.py +0 -68
- notionary/telemetry/__init__.py +0 -7
- notionary/telemetry/telemetry.py +0 -226
- notionary/telemetry/track_usage_decorator.py +0 -76
- notionary/util/warn_direct_constructor_usage.py +0 -54
- notionary-0.2.12.dist-info/RECORD +0 -70
- /notionary/util/{singleton.py → singleton_decorator.py} +0 -0
- {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/WHEEL +0 -0
- {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/entry_points.txt +0 -0
- {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/licenses/LICENSE +0 -0
- {notionary-0.2.12.dist-info → notionary-0.2.14.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import Any, Dict, List
|
4
|
+
from datetime import datetime, timedelta
|
5
|
+
from dataclasses import dataclass, field
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass
|
9
|
+
class FilterConfig:
|
10
|
+
"""Einfache Konfiguration für Notion Database Filter."""
|
11
|
+
|
12
|
+
conditions: List[Dict[str, Any]] = field(default_factory=list)
|
13
|
+
page_size: int = 100
|
14
|
+
|
15
|
+
def to_filter_dict(self) -> Dict[str, Any]:
|
16
|
+
"""Konvertiert zu einem Notion-Filter-Dictionary."""
|
17
|
+
if len(self.conditions) == 0:
|
18
|
+
return {}
|
19
|
+
if len(self.conditions) == 1:
|
20
|
+
return self.conditions[0]
|
21
|
+
|
22
|
+
return {"and": self.conditions}
|
23
|
+
|
24
|
+
|
25
|
+
class FilterBuilder:
|
26
|
+
"""
|
27
|
+
Builder class for creating complex Notion filters with comprehensive property type support.
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(self, config: FilterConfig = None):
|
31
|
+
self.config = config or FilterConfig()
|
32
|
+
|
33
|
+
def with_page_object_filter(self) -> FilterBuilder:
|
34
|
+
"""Filter: Nur Datenbank-Objekte (Notion API search)."""
|
35
|
+
self.config.conditions.append({"value": "page", "property": "object"})
|
36
|
+
return self
|
37
|
+
|
38
|
+
def with_database_object_filter(self) -> FilterBuilder:
|
39
|
+
"""Filter: Nur Datenbank-Objekte (Notion API search)."""
|
40
|
+
self.config.conditions.append({"value": "database", "property": "object"})
|
41
|
+
return self
|
42
|
+
|
43
|
+
# TIMESTAMP FILTERS (Created/Updated)
|
44
|
+
def with_created_after(self, date: datetime) -> FilterBuilder:
|
45
|
+
"""Add condition: created after specific date."""
|
46
|
+
self.config.conditions.append(
|
47
|
+
{"timestamp": "created_time", "created_time": {"after": date.isoformat()}}
|
48
|
+
)
|
49
|
+
return self
|
50
|
+
|
51
|
+
def with_created_before(self, date: datetime) -> FilterBuilder:
|
52
|
+
"""Add condition: created before specific date."""
|
53
|
+
self.config.conditions.append(
|
54
|
+
{"timestamp": "created_time", "created_time": {"before": date.isoformat()}}
|
55
|
+
)
|
56
|
+
return self
|
57
|
+
|
58
|
+
def with_updated_after(self, date: datetime) -> FilterBuilder:
|
59
|
+
"""Add condition: updated after specific date."""
|
60
|
+
self.config.conditions.append(
|
61
|
+
{
|
62
|
+
"timestamp": "last_edited_time",
|
63
|
+
"last_edited_time": {"after": date.isoformat()},
|
64
|
+
}
|
65
|
+
)
|
66
|
+
return self
|
67
|
+
|
68
|
+
def with_created_last_n_days(self, days: int) -> FilterBuilder:
|
69
|
+
"""In den letzten N Tagen erstellt."""
|
70
|
+
cutoff = datetime.now() - timedelta(days=days)
|
71
|
+
return self.with_created_after(cutoff)
|
72
|
+
|
73
|
+
def with_updated_last_n_hours(self, hours: int) -> FilterBuilder:
|
74
|
+
"""In den letzten N Stunden bearbeitet."""
|
75
|
+
cutoff = datetime.now() - timedelta(hours=hours)
|
76
|
+
return self.with_updated_after(cutoff)
|
77
|
+
|
78
|
+
# RICH TEXT FILTERS
|
79
|
+
def with_text_contains(self, property_name: str, value: str) -> FilterBuilder:
|
80
|
+
"""Rich text contains value."""
|
81
|
+
self.config.conditions.append(
|
82
|
+
{"property": property_name, "rich_text": {"contains": value}}
|
83
|
+
)
|
84
|
+
return self
|
85
|
+
|
86
|
+
def with_text_equals(self, property_name: str, value: str) -> FilterBuilder:
|
87
|
+
"""Rich text equals value."""
|
88
|
+
self.config.conditions.append(
|
89
|
+
{"property": property_name, "rich_text": {"equals": value}}
|
90
|
+
)
|
91
|
+
return self
|
92
|
+
|
93
|
+
# TITLE FILTERS
|
94
|
+
def with_title_contains(self, value: str) -> FilterBuilder:
|
95
|
+
"""Title contains value."""
|
96
|
+
self.config.conditions.append(
|
97
|
+
{"property": "title", "title": {"contains": value}}
|
98
|
+
)
|
99
|
+
return self
|
100
|
+
|
101
|
+
def with_title_equals(self, value: str) -> FilterBuilder:
|
102
|
+
"""Title equals value."""
|
103
|
+
self.config.conditions.append({"property": "title", "title": {"equals": value}})
|
104
|
+
return self
|
105
|
+
|
106
|
+
# SELECT FILTERS (Single Select)
|
107
|
+
def with_select_equals(self, property_name: str, value: str) -> FilterBuilder:
|
108
|
+
"""Select equals value."""
|
109
|
+
self.config.conditions.append(
|
110
|
+
{"property": property_name, "select": {"equals": value}}
|
111
|
+
)
|
112
|
+
return self
|
113
|
+
|
114
|
+
def with_select_is_empty(self, property_name: str) -> FilterBuilder:
|
115
|
+
"""Select is empty."""
|
116
|
+
self.config.conditions.append(
|
117
|
+
{"property": property_name, "select": {"is_empty": True}}
|
118
|
+
)
|
119
|
+
return self
|
120
|
+
|
121
|
+
def with_multi_select_contains(
|
122
|
+
self, property_name: str, value: str
|
123
|
+
) -> FilterBuilder:
|
124
|
+
"""Multi-select contains value."""
|
125
|
+
self.config.conditions.append(
|
126
|
+
{"property": property_name, "multi_select": {"contains": value}}
|
127
|
+
)
|
128
|
+
return self
|
129
|
+
|
130
|
+
def with_status_equals(self, property_name: str, value: str) -> FilterBuilder:
|
131
|
+
"""Status equals value."""
|
132
|
+
self.config.conditions.append(
|
133
|
+
{"property": property_name, "status": {"equals": value}}
|
134
|
+
)
|
135
|
+
return self
|
136
|
+
|
137
|
+
def with_page_size(self, size: int) -> FilterBuilder:
|
138
|
+
"""Set page size for pagination."""
|
139
|
+
self.config.page_size = size
|
140
|
+
return self
|
141
|
+
|
142
|
+
def with_or_condition(self, *builders: FilterBuilder) -> FilterBuilder:
|
143
|
+
"""Add OR condition with multiple sub-conditions."""
|
144
|
+
or_conditions = []
|
145
|
+
for builder in builders:
|
146
|
+
filter_dict = builder.build()
|
147
|
+
if filter_dict:
|
148
|
+
or_conditions.append(filter_dict)
|
149
|
+
|
150
|
+
if len(or_conditions) > 1:
|
151
|
+
self.config.conditions.append({"or": or_conditions})
|
152
|
+
elif len(or_conditions) == 1:
|
153
|
+
self.config.conditions.append(or_conditions[0])
|
154
|
+
|
155
|
+
return self
|
156
|
+
|
157
|
+
def build(self) -> Dict[str, Any]:
|
158
|
+
"""Build the final filter dictionary."""
|
159
|
+
return self.config.to_filter_dict()
|
160
|
+
|
161
|
+
def get_config(self) -> FilterConfig:
|
162
|
+
"""Get the underlying FilterConfig."""
|
163
|
+
return self.config
|
164
|
+
|
165
|
+
def copy(self) -> FilterBuilder:
|
166
|
+
"""Create a copy of the builder."""
|
167
|
+
new_config = FilterConfig(
|
168
|
+
conditions=self.config.conditions.copy(), page_size=self.config.page_size
|
169
|
+
)
|
170
|
+
return FilterBuilder(new_config)
|
171
|
+
|
172
|
+
def reset(self) -> FilterBuilder:
|
173
|
+
"""Reset all conditions."""
|
174
|
+
self.config = FilterConfig()
|
175
|
+
return self
|