notionary 0.1.19__py3-none-any.whl → 0.1.21__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 (42) hide show
  1. notionary/__init__.py +2 -2
  2. notionary/database/notion_database.py +3 -1
  3. notionary/elements/audio_element.py +7 -11
  4. notionary/elements/bookmark_element.py +17 -29
  5. notionary/elements/bulleted_list_element.py +69 -0
  6. notionary/elements/callout_element.py +18 -80
  7. notionary/elements/code_block_element.py +15 -10
  8. notionary/elements/column_element.py +39 -26
  9. notionary/elements/divider_element.py +8 -25
  10. notionary/elements/embed_element.py +10 -18
  11. notionary/elements/heading_element.py +10 -12
  12. notionary/elements/image_element.py +9 -15
  13. notionary/elements/mention_element.py +6 -15
  14. notionary/elements/notion_block_element.py +12 -11
  15. notionary/elements/numbered_list_element.py +68 -0
  16. notionary/elements/paragraph_element.py +11 -7
  17. notionary/elements/prompts/element_prompt_content.py +20 -0
  18. notionary/elements/prompts/synthax_prompt_builder.py +92 -0
  19. notionary/elements/qoute_element.py +20 -89
  20. notionary/elements/registry/block_element_registry.py +90 -0
  21. notionary/elements/{block_element_registry_builder.py → registry/block_element_registry_builder.py} +15 -124
  22. notionary/elements/table_element.py +4 -16
  23. notionary/elements/text_inline_formatter.py +15 -78
  24. notionary/elements/todo_lists.py +14 -18
  25. notionary/elements/toggle_element.py +19 -1
  26. notionary/elements/video_element.py +10 -19
  27. notionary/notion_client.py +2 -2
  28. notionary/page/content/page_content_manager.py +2 -3
  29. notionary/page/markdown_to_notion_converter.py +3 -3
  30. notionary/page/notion_page.py +3 -3
  31. notionary/page/notion_to_markdown_converter.py +3 -3
  32. notionary/page/relations/notion_page_relation_manager.py +24 -24
  33. notionary/page/relations/notion_page_title_resolver.py +1 -2
  34. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/METADATA +3 -3
  35. notionary-0.1.21.dist-info/RECORD +58 -0
  36. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/WHEEL +1 -1
  37. notionary/elements/block_element_registry.py +0 -233
  38. notionary/elements/list_element.py +0 -130
  39. notionary/util/singleton_decorator.py +0 -20
  40. notionary-0.1.19.dist-info/RECORD +0 -56
  41. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/licenses/LICENSE +0 -0
  42. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/top_level.txt +0 -0
@@ -1,233 +0,0 @@
1
- from typing import Dict, Any, Optional, List, Type
2
-
3
- from notionary.elements.notion_block_element import NotionBlockElement
4
- from notionary.elements.text_inline_formatter import TextInlineFormatter
5
-
6
-
7
- class BlockElementRegistry:
8
- """Registry of elements that can convert between Markdown and Notion."""
9
-
10
- def __init__(self, elements=None):
11
- """
12
- Initialize a new registry instance.
13
-
14
- Args:
15
- elements: Optional list of NotionBlockElement classes to register at creation
16
- """
17
- self._elements = []
18
-
19
- # Register initial elements if provided
20
- if elements:
21
- for element in elements:
22
- self.register(element)
23
-
24
- def register(self, element_class: Type[NotionBlockElement]):
25
- """Register an element class."""
26
- self._elements.append(element_class)
27
- return self
28
-
29
- def deregister(self, element_class: Type[NotionBlockElement]) -> bool:
30
- """
31
- Deregister an element class.
32
-
33
- Args:
34
- element_class: The element class to remove from the registry
35
-
36
- Returns:
37
- bool: True if the element was removed, False if it wasn't in the registry
38
- """
39
- if element_class in self._elements:
40
- self._elements.remove(element_class)
41
- return True
42
- return False
43
-
44
- def clear(self):
45
- """Clear the registry completely."""
46
- self._elements.clear()
47
- return self
48
-
49
- def find_markdown_handler(self, text: str) -> Optional[Type[NotionBlockElement]]:
50
- """Find an element that can handle the given markdown text."""
51
- for element in self._elements:
52
- if element.match_markdown(text):
53
- return element
54
- return None
55
-
56
- def find_notion_handler(
57
- self, block: Dict[str, Any]
58
- ) -> Optional[Type[NotionBlockElement]]:
59
- """Find an element that can handle the given Notion block."""
60
- for element in self._elements:
61
- if element.match_notion(block):
62
- return element
63
- return None
64
-
65
- def markdown_to_notion(self, text: str) -> Optional[Dict[str, Any]]:
66
- """Convert markdown to Notion block using registered elements."""
67
- handler = self.find_markdown_handler(text)
68
- if handler:
69
- return handler.markdown_to_notion(text)
70
- return None
71
-
72
- def notion_to_markdown(self, block: Dict[str, Any]) -> Optional[str]:
73
- """Convert Notion block to markdown using registered elements."""
74
- handler = self.find_notion_handler(block)
75
- if handler:
76
- return handler.notion_to_markdown(block)
77
- return None
78
-
79
- def get_multiline_elements(self) -> List[Type[NotionBlockElement]]:
80
- """Get all registered multiline elements."""
81
- return [element for element in self._elements if element.is_multiline()]
82
-
83
- def get_elements(self) -> List[Type[NotionBlockElement]]:
84
- """Get all registered elements."""
85
- return self._elements.copy()
86
-
87
- def generate_llm_prompt(self) -> str:
88
- """
89
- Generates an LLM system prompt that describes the Markdown syntax of all registered elements.
90
-
91
- TextInlineFormatter is automatically added if not already registered.
92
-
93
- Returns:
94
- A complete system prompt for an LLM that should understand Notion-Markdown syntax
95
- """
96
- # Create a copy of registered elements
97
- element_classes = self._elements.copy()
98
-
99
- formatter_names = [e.__name__ for e in element_classes]
100
- if "TextInlineFormatter" not in formatter_names:
101
- element_classes = [TextInlineFormatter] + element_classes
102
-
103
- return MarkdownSyntaxPromptBuilder.generate_system_prompt(element_classes)
104
-
105
-
106
- class MarkdownSyntaxPromptBuilder:
107
- """
108
- Generator for LLM system prompts that describe Notion-Markdown syntax.
109
-
110
- This class extracts information about supported Markdown patterns
111
- and formats them optimally for LLMs.
112
- """
113
-
114
- # Standard system prompt template
115
- SYSTEM_PROMPT_TEMPLATE = """You are a knowledgeable assistant that helps users create content for Notion pages.
116
- Notion supports standard Markdown with some special extensions for creating rich content.
117
-
118
- {element_docs}
119
-
120
- Important usage guidelines:
121
-
122
- 1. The backtick code fence syntax (```) should ONLY be used when creating actual code blocks or diagrams.
123
- Do not wrap examples or regular content in backticks unless you're showing code.
124
-
125
- 2. Use inline formatting (bold, italic, highlights, etc.) across all content to enhance readability.
126
- The highlight syntax (==text== and ==color:text==) is especially useful for emphasizing important points.
127
-
128
- 3. Notion's extensions to Markdown (like callouts, bookmarks, toggles) provide richer formatting options
129
- than standard Markdown while maintaining the familiar Markdown syntax for basic elements.
130
-
131
- 4. You can use these Markdown extensions alongside standard Markdown to create visually appealing
132
- and well-structured content.
133
-
134
- 5. Remember that features like highlighting with ==yellow:important== work in all text blocks including
135
- paragraphs, lists, quotes, etc.
136
- """
137
-
138
- @staticmethod
139
- def generate_element_doc(element_class: Type[NotionBlockElement]) -> str:
140
- """
141
- Generates documentation for a specific NotionBlockElement.
142
-
143
- Uses the element's get_llm_prompt_content method if available.
144
- """
145
- class_name = element_class.__name__
146
- element_name = class_name.replace("Element", "")
147
-
148
- # Start with element name as header
149
- result = [f"## {element_name}"]
150
-
151
- # Use get_llm_prompt_content if available
152
- if hasattr(element_class, "get_llm_prompt_content") and callable(
153
- getattr(element_class, "get_llm_prompt_content")
154
- ):
155
- content = element_class.get_llm_prompt_content()
156
-
157
- if content.get("description"):
158
- result.append(content["description"])
159
-
160
- if content.get("syntax"):
161
- result.append("\n### Syntax:")
162
- for syntax_item in content["syntax"]:
163
- result.append(f"{syntax_item}")
164
-
165
- if content.get("examples"):
166
- result.append("\n### Examples:")
167
- for example in content["examples"]:
168
- result.append(example)
169
-
170
- # Add any additional custom sections
171
- for key, value in content.items():
172
- if key not in ["description", "syntax", "examples"] and isinstance(
173
- value, str
174
- ):
175
- result.append(f"\n### {key.replace('_', ' ').title()}:")
176
- result.append(value)
177
-
178
- return "\n".join(result)
179
-
180
- @classmethod
181
- def generate_element_docs(
182
- cls,
183
- element_classes: List[Type[NotionBlockElement]],
184
- ) -> str:
185
- """
186
- Generates complete documentation for all provided element classes.
187
-
188
- Args:
189
- element_classes: List of NotionBlockElement classes
190
-
191
- Returns:
192
- Documentation text for all elements
193
- """
194
- docs = [
195
- "# Custom Markdown Syntax for Notion Blocks",
196
- "The following custom Markdown patterns are supported for creating Notion blocks:",
197
- ]
198
-
199
- text_formatter = None
200
- other_elements = []
201
-
202
- for element in element_classes:
203
- if element.__name__ == "TextInlineFormatter":
204
- text_formatter = element
205
- else:
206
- other_elements.append(element)
207
-
208
- if text_formatter:
209
- docs.append("\n" + cls.generate_element_doc(text_formatter))
210
-
211
- for element in other_elements:
212
- if element.__name__ != "InlineFormattingElement":
213
- docs.append("\n" + cls.generate_element_doc(element))
214
-
215
- return "\n".join(docs)
216
-
217
- @classmethod
218
- def generate_system_prompt(
219
- cls,
220
- element_classes: List[Type[NotionBlockElement]],
221
- ) -> str:
222
- """
223
- Generates a complete system prompt for LLMs.
224
-
225
- Args:
226
- element_classes: List of element classes to document
227
-
228
- Returns:
229
- Complete system prompt for an LLM
230
- """
231
- element_docs = cls.generate_element_docs(element_classes)
232
-
233
- return cls.SYSTEM_PROMPT_TEMPLATE.format(element_docs=element_docs)
@@ -1,130 +0,0 @@
1
- import re
2
- from typing import Dict, Any, Optional
3
- from typing_extensions import override
4
- from notionary.elements.notion_block_element import NotionBlockElement
5
- from notionary.elements.text_inline_formatter import TextInlineFormatter
6
-
7
-
8
- class BulletedListElement(NotionBlockElement):
9
- """Class for converting between Markdown bullet lists and Notion bulleted list items."""
10
-
11
- @override
12
- @staticmethod
13
- def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
14
- """Convert markdown bulleted list item to Notion block."""
15
- pattern = re.compile(
16
- r"^(\s*)[*\-+]\s+(?!\[[ x]\])(.+)$"
17
- ) # Avoid matching todo items
18
- list_match = pattern.match(text)
19
- if not list_match:
20
- return None
21
-
22
- content = list_match.group(2)
23
-
24
- # Use parse_inline_formatting to handle rich text
25
- rich_text = TextInlineFormatter.parse_inline_formatting(content)
26
-
27
- return {
28
- "type": "bulleted_list_item",
29
- "bulleted_list_item": {"rich_text": rich_text, "color": "default"},
30
- }
31
-
32
- @override
33
- @staticmethod
34
- def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
35
- """Convert Notion bulleted list item block to markdown."""
36
- if block.get("type") != "bulleted_list_item":
37
- return None
38
-
39
- rich_text = block.get("bulleted_list_item", {}).get("rich_text", [])
40
- content = TextInlineFormatter.extract_text_with_formatting(rich_text)
41
-
42
- return f"- {content}"
43
-
44
- @override
45
- @staticmethod
46
- def match_markdown(text: str) -> bool:
47
- """Check if this element can handle the given markdown text."""
48
- pattern = re.compile(r"^(\s*)[*\-+]\s+(?!\[[ x]\])(.+)$")
49
- return bool(pattern.match(text))
50
-
51
- @override
52
- @staticmethod
53
- def match_notion(block: Dict[str, Any]) -> bool:
54
- """Check if this element can handle the given Notion block."""
55
- return block.get("type") == "bulleted_list_item"
56
-
57
- @override
58
- @classmethod
59
- def get_llm_prompt_content(cls) -> dict:
60
- """Returns information for LLM prompts about this element."""
61
- return {
62
- "description": "Creates bulleted list items for unordered lists.",
63
- "when_to_use": "Use for lists where order doesn't matter, such as features, options, or items without hierarchy.",
64
- "syntax": ["- Item text", "* Item text", "+ Item text"],
65
- "examples": ["- First item\n- Second item\n- Third item"],
66
- }
67
-
68
-
69
- class NumberedListElement:
70
- """Class for converting between Markdown numbered lists and Notion numbered list items."""
71
-
72
- @override
73
- @staticmethod
74
- def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
75
- """Convert markdown numbered list item to Notion block."""
76
- pattern = re.compile(r"^\s*(\d+)\.\s+(.+)$")
77
- numbered_match = pattern.match(text)
78
- if not numbered_match:
79
- return None
80
-
81
- content = numbered_match.group(2)
82
-
83
- # Use parse_inline_formatting to handle rich text
84
- rich_text = TextInlineFormatter.parse_inline_formatting(content)
85
-
86
- return {
87
- "type": "numbered_list_item",
88
- "numbered_list_item": {"rich_text": rich_text, "color": "default"},
89
- }
90
-
91
- @override
92
- @staticmethod
93
- def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
94
- """Convert Notion numbered list item block to markdown."""
95
- if block.get("type") != "numbered_list_item":
96
- return None
97
-
98
- rich_text = block.get("numbered_list_item", {}).get("rich_text", [])
99
- content = TextInlineFormatter.extract_text_with_formatting(rich_text)
100
-
101
- return f"1. {content}"
102
-
103
- @override
104
- @staticmethod
105
- def match_markdown(text: str) -> bool:
106
- """Check if this element can handle the given markdown text."""
107
- pattern = re.compile(r"^\s*\d+\.\s+(.+)$")
108
- return bool(pattern.match(text))
109
-
110
- @override
111
- @staticmethod
112
- def match_notion(block: Dict[str, Any]) -> bool:
113
- """Check if this element can handle the given Notion block."""
114
- return block.get("type") == "numbered_list_item"
115
-
116
- @override
117
- @staticmethod
118
- def is_multiline() -> bool:
119
- return False
120
-
121
- @override
122
- @classmethod
123
- def get_llm_prompt_content(cls) -> dict:
124
- """Returns information for LLM prompts about this element."""
125
- return {
126
- "description": "Creates numbered list items for ordered sequences.",
127
- "when_to_use": "Use for lists where order matters, such as steps, rankings, or sequential items.",
128
- "syntax": ["1. Item text"],
129
- "examples": ["1. First step\n2. Second step\n3. Third step"],
130
- }
@@ -1,20 +0,0 @@
1
- from typing import TypeVar
2
- from functools import wraps
3
-
4
- T = TypeVar("T")
5
-
6
-
7
- def singleton(cls: T) -> T:
8
- """
9
- Decorator zur Implementierung des Singleton-Musters.
10
- Stellt sicher, dass nur eine Instanz der Klasse existiert.
11
- """
12
- instances = {}
13
-
14
- @wraps(cls)
15
- def get_instance(*args, **kwargs):
16
- if cls not in instances:
17
- instances[cls] = cls(*args, **kwargs)
18
- return instances[cls]
19
-
20
- return get_instance
@@ -1,56 +0,0 @@
1
- notionary/__init__.py,sha256=sVqdwzMQcc9jf6FKi1qflilsx8rnWzluVhWewVi5gyI,717
2
- notionary/notion_client.py,sha256=NPPK7zId6EaC-hQeFJ7geaiROGtZfmc8cVP2nQez5DU,6040
3
- notionary/database/database_discovery.py,sha256=qDGFhXG9s-_6CXdRg8tMiwX4dvX7jLjgAUFPSNlYtlI,4506
4
- notionary/database/database_info_service.py,sha256=Ig6gx8jUSPYORJvfgEV5kV6t72pZQsWU8HPMqd43B-o,1336
5
- notionary/database/notion_database.py,sha256=Zm5Ev0n4idKUe3ms8l3B4fyIezNNCCEDWHZ5vDoTknQ,7985
6
- notionary/database/notion_database_factory.py,sha256=Af57yaUHidD8TKJ8uyXOc2nnqHm7on6VGFdDRjxiq9o,6692
7
- notionary/database/models/page_result.py,sha256=Vmm5_oYpYAkIIJVoTd1ZZGloeC3cmFLMYP255mAmtaw,233
8
- notionary/elements/audio_element.py,sha256=XLARz5zlPPW_Qof6uhcYXFmyYzyS1fLdxdfsvh6GMOs,5589
9
- notionary/elements/block_element_registry.py,sha256=2mEbCEIPRY15qk6NYcq9vf7Bq_5vuu1xbiJatoLFf7w,8530
10
- notionary/elements/block_element_registry_builder.py,sha256=xfZWJaamYCyw-aIU8TXTcAncVJaLpN7ioJRLYQxTbCo,11529
11
- notionary/elements/bookmark_element.py,sha256=83ciz2THxjeq7ofn-Xz9sG1Ifzm_gkIDmOo0A-pNsSo,8577
12
- notionary/elements/callout_element.py,sha256=K8yk7nE3WP8nskJKbMunkRDFlhSCXrONmYS6hELN6QE,5932
13
- notionary/elements/code_block_element.py,sha256=wbW_PfH6QBUFVfeELESuLiI5-GmLm2YUFP4xwFHgNV4,5173
14
- notionary/elements/column_element.py,sha256=F_hnaBtQbnfRiKRVfpo9X5aNiw75SxeHfWOiMyMPcBw,10706
15
- notionary/elements/divider_element.py,sha256=RCN87xFizAjKd8c_beywNW5lfXFFtOZPT8tyXgAh2D0,2776
16
- notionary/elements/embed_element.py,sha256=LZjbSfwq0v8NGzwfUXpnGwvJ34IjYDwZzqyxVd2Iqt8,4768
17
- notionary/elements/heading_element.py,sha256=GsfEg5XtohmtO8PBP9giezIg6pRWQ_CdPXjh7jOiytw,2756
18
- notionary/elements/image_element.py,sha256=663H_FzE_bsovps3uCV12trNTmMAWBu5Ko1tSBNu2V4,4845
19
- notionary/elements/list_element.py,sha256=-f4mPRPesqFYYXfiiqGpnADeAY2ZAF1sTDtkLcejvLg,4846
20
- notionary/elements/mention_element.py,sha256=N1AcE8daMs6sDJGidQ8vvtHj30Do3K7x-4lW2aAYthU,8274
21
- notionary/elements/notion_block_element.py,sha256=lLRBDXhBeRaRzkbvdpYpr-U9nbkd62oVtqdSe-svT4c,1746
22
- notionary/elements/paragraph_element.py,sha256=ULSPcwy_JbnKdQkMy-xMs_KtYI8k5uxh6b4EGMNldTk,2734
23
- notionary/elements/qoute_element.py,sha256=3I2a7KboPF5QF6afu99HSIa62YUNfDJ6oaSDgyc9NjA,9041
24
- notionary/elements/table_element.py,sha256=jCq1ZFNCdxYEI6ER21OZ64TYGjW162gH-A6DUbldxY4,11222
25
- notionary/elements/text_inline_formatter.py,sha256=FE_Sq2cozpu5RVtMbnPq21gD06UjH3LMRYr3s16JKYo,10606
26
- notionary/elements/todo_lists.py,sha256=PrLZdp1-q1gx7mBsL6NUQ5U18HxmkUw8yqVh9qJpArE,4233
27
- notionary/elements/toggle_element.py,sha256=5cyWjkBgJcKdhhdrOn4bEM8Dpc5gXWhVbM4qZm9FNYM,7242
28
- notionary/elements/video_element.py,sha256=uYCwFakna7pzpCDjjtxRhUkSkPfzJTttdKUKYSluqyw,6031
29
- notionary/exceptions/database_exceptions.py,sha256=I-Tx6bYRLpi5pjGPtbT-Mqxvz3BFgYTiuZxknJeLxtI,2638
30
- notionary/exceptions/page_creation_exception.py,sha256=4v7IuZD6GsQLrqhDLriGjuG3ML638gAO53zDCrLePuU,281
31
- notionary/page/markdown_to_notion_converter.py,sha256=wTkH7o6367IWBtSqBrldpKx4rxHli176QfWtAenyysQ,15067
32
- notionary/page/notion_page.py,sha256=KIjVeiMJGWWxR6ty1uuNvMoQf2IoRmSUxwMdDIyOu40,17635
33
- notionary/page/notion_page_factory.py,sha256=UUEZ-cyEWL0OMVPrgjc4vJdcplEa1bO2yHCYooACYC8,8189
34
- notionary/page/notion_to_markdown_converter.py,sha256=WHrESgMZPqnp3kufi0YB7Cyy8U1rwhJ0d4HHdBRfRdU,8053
35
- notionary/page/content/notion_page_content_chunker.py,sha256=xRks74Dqec-De6-AVTxMPnXs-MSJBzSm1HfJfaHiKr8,3330
36
- notionary/page/content/page_content_manager.py,sha256=JM4ga-Y6k6mTbyH9YGYWbdrxpSLAdmZa845EwFyADMg,6142
37
- notionary/page/metadata/metadata_editor.py,sha256=61uiw8oB25O8ePhytoJvZDetuof5sjPoM6aoHZGo4wc,4949
38
- notionary/page/metadata/notion_icon_manager.py,sha256=ixZrWsHGVpmF05Ncy9LCt8vZlKAQHYFZW-2yI5JZZDI,1426
39
- notionary/page/metadata/notion_page_cover_manager.py,sha256=qgQxQE-bx4oWjLFUQvpXD5GzO1Mx7w7htz1xC2BOqUg,1717
40
- notionary/page/properites/database_property_service.py,sha256=AJuBGahbb53VQa6IGGHxBMoOgCy6vFZg08uR_eDjNUs,11570
41
- notionary/page/properites/page_property_manager.py,sha256=Xl8Cwn8WVszqpFXT_NvASkmP5igpCTEgRVhG_F45424,6914
42
- notionary/page/properites/property_formatter.py,sha256=d_Nr5XQxgjB6VIS0u3ey14MOUKY416o_BvdXjbkUNAQ,3667
43
- notionary/page/properites/property_operation_result.py,sha256=PhxHJJxxG2BdDl7aswhWnMSmf9RQtoinKkRHDoqxwCs,3913
44
- notionary/page/properites/property_value_extractor.py,sha256=1BfyCYrFzfIUmNTozavrLTjG--6P6Dy2tkewf6rHHwQ,2353
45
- notionary/page/relations/notion_page_relation_manager.py,sha256=xyV92IFjFbizqDLV9UK89JVyDAtxBLZqVDId-orRP0A,13128
46
- notionary/page/relations/notion_page_title_resolver.py,sha256=1751DKRI0o586-78fRDWEtfWyQViMir_08v7YpetxfY,3016
47
- notionary/page/relations/page_database_relation.py,sha256=F9aGXFjjL8ZLNbfTGeGm_QAyXhz2AEOw7GgDLdprEcE,2313
48
- notionary/page/relations/relation_operation_result.py,sha256=NDxBzGntOxc_89ti-HG8xDSqfY6PwyGHKHrrKbCzNjM,5010
49
- notionary/util/logging_mixin.py,sha256=fKsx9t90bwvL74ZX3dU-sXdC4TZCQyO6qU9I8txkw_U,1369
50
- notionary/util/page_id_utils.py,sha256=EYNMxgf-7ghzL5K8lKZBZfW7g5CsdY0Xuj4IYmU8RPk,1381
51
- notionary/util/singleton_decorator.py,sha256=GTNMfIlVNRUVMw_c88xqd12-DcqZJjmyidN54yqiNVw,472
52
- notionary-0.1.19.dist-info/licenses/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
53
- notionary-0.1.19.dist-info/METADATA,sha256=Ws3WI2Yp4HopH7_Jo4eQbzSN0ziOHZOaqieDNZK9kSM,8350
54
- notionary-0.1.19.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
55
- notionary-0.1.19.dist-info/top_level.txt,sha256=fhONa6BMHQXqthx5PanWGbPL0b8rdFqhrJKVLf_adSs,10
56
- notionary-0.1.19.dist-info/RECORD,,