notionary 0.2.27__py3-none-any.whl → 0.3.0__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 (395) hide show
  1. notionary/__init__.py +5 -20
  2. notionary/blocks/__init__.py +4 -4
  3. notionary/blocks/client.py +90 -216
  4. notionary/blocks/enums.py +167 -0
  5. notionary/blocks/rich_text/markdown_rich_text_converter.py +280 -0
  6. notionary/blocks/rich_text/models.py +178 -0
  7. notionary/blocks/rich_text/name_id_resolver/__init__.py +13 -0
  8. notionary/blocks/rich_text/name_id_resolver/data_source.py +32 -0
  9. notionary/blocks/rich_text/name_id_resolver/database.py +31 -0
  10. notionary/blocks/rich_text/name_id_resolver/page.py +34 -0
  11. notionary/blocks/rich_text/name_id_resolver/person.py +37 -0
  12. notionary/blocks/rich_text/name_id_resolver/port.py +11 -0
  13. notionary/blocks/rich_text/rich_text_markdown_converter.py +144 -0
  14. notionary/blocks/rich_text/rich_text_patterns.py +42 -0
  15. notionary/blocks/schemas.py +778 -0
  16. notionary/comments/__init__.py +1 -22
  17. notionary/comments/client.py +52 -187
  18. notionary/comments/factory.py +38 -0
  19. notionary/comments/models.py +5 -127
  20. notionary/comments/schemas.py +240 -0
  21. notionary/comments/service.py +34 -0
  22. notionary/data_source/http/client.py +11 -0
  23. notionary/data_source/http/data_source_instance_client.py +104 -0
  24. notionary/data_source/properties/schemas.py +402 -0
  25. notionary/data_source/query/builder.py +448 -0
  26. notionary/data_source/query/resolver.py +114 -0
  27. notionary/data_source/query/schema.py +302 -0
  28. notionary/data_source/query/validator.py +73 -0
  29. notionary/data_source/schema/registry.py +104 -0
  30. notionary/data_source/schema/service.py +136 -0
  31. notionary/data_source/schemas.py +27 -0
  32. notionary/data_source/service.py +377 -0
  33. notionary/database/client.py +30 -135
  34. notionary/database/database_metadata_update_client.py +19 -0
  35. notionary/database/schemas.py +29 -0
  36. notionary/database/service.py +168 -0
  37. notionary/exceptions/__init__.py +33 -0
  38. notionary/exceptions/api.py +41 -0
  39. notionary/exceptions/base.py +2 -0
  40. notionary/exceptions/block_parsing.py +16 -0
  41. notionary/exceptions/data_source/__init__.py +6 -0
  42. notionary/exceptions/data_source/builder.py +182 -0
  43. notionary/exceptions/data_source/properties.py +34 -0
  44. notionary/exceptions/properties.py +58 -0
  45. notionary/exceptions/search.py +57 -0
  46. notionary/file_upload/client.py +18 -30
  47. notionary/file_upload/models.py +7 -8
  48. notionary/file_upload/{notion_file_upload.py → service.py} +29 -64
  49. notionary/http/client.py +204 -0
  50. notionary/http/models.py +50 -0
  51. notionary/page/blocks/client.py +1 -0
  52. notionary/page/content/factory.py +73 -0
  53. notionary/page/content/markdown/__init__.py +5 -0
  54. notionary/page/content/markdown/builder.py +226 -0
  55. notionary/page/content/markdown/nodes/__init__.py +52 -0
  56. notionary/page/content/markdown/nodes/audio.py +23 -0
  57. notionary/page/content/markdown/nodes/base.py +12 -0
  58. notionary/page/content/markdown/nodes/bookmark.py +25 -0
  59. notionary/page/content/markdown/nodes/breadcrumb.py +14 -0
  60. notionary/page/content/markdown/nodes/bulleted_list.py +41 -0
  61. notionary/page/content/markdown/nodes/callout.py +34 -0
  62. notionary/page/content/markdown/nodes/code.py +28 -0
  63. notionary/page/content/markdown/nodes/columns.py +69 -0
  64. notionary/page/content/markdown/nodes/container.py +64 -0
  65. notionary/page/content/markdown/nodes/divider.py +14 -0
  66. notionary/page/content/markdown/nodes/embed.py +23 -0
  67. notionary/page/content/markdown/nodes/equation.py +19 -0
  68. notionary/page/content/markdown/nodes/file.py +23 -0
  69. notionary/page/content/markdown/nodes/heading.py +36 -0
  70. notionary/page/content/markdown/nodes/image.py +23 -0
  71. notionary/page/content/markdown/nodes/mixins/__init__.py +5 -0
  72. notionary/page/content/markdown/nodes/mixins/caption.py +12 -0
  73. notionary/page/content/markdown/nodes/numbered_list.py +38 -0
  74. notionary/page/content/markdown/nodes/paragraph.py +14 -0
  75. notionary/page/content/markdown/nodes/pdf.py +23 -0
  76. notionary/page/content/markdown/nodes/quote.py +27 -0
  77. notionary/page/content/markdown/nodes/space.py +14 -0
  78. notionary/page/content/markdown/nodes/table.py +45 -0
  79. notionary/page/content/markdown/nodes/table_of_contents.py +14 -0
  80. notionary/page/content/markdown/nodes/todo.py +38 -0
  81. notionary/page/content/markdown/nodes/toggle.py +27 -0
  82. notionary/page/content/markdown/nodes/video.py +23 -0
  83. notionary/page/content/parser/context.py +126 -0
  84. notionary/page/content/parser/factory.py +210 -0
  85. notionary/page/content/parser/parsers/__init__.py +58 -0
  86. notionary/page/content/parser/parsers/audio.py +40 -0
  87. notionary/page/content/parser/parsers/base.py +30 -0
  88. notionary/page/content/parser/parsers/bookmark.py +33 -0
  89. notionary/page/content/parser/parsers/breadcrumb.py +33 -0
  90. notionary/page/content/parser/parsers/bulleted_list.py +85 -0
  91. notionary/page/content/parser/parsers/callout.py +100 -0
  92. notionary/page/content/parser/parsers/caption.py +55 -0
  93. notionary/page/content/parser/parsers/code.py +81 -0
  94. notionary/page/content/parser/parsers/column.py +76 -0
  95. notionary/page/content/parser/parsers/column_list.py +81 -0
  96. notionary/page/content/parser/parsers/divider.py +33 -0
  97. notionary/page/content/parser/parsers/embed.py +33 -0
  98. notionary/page/content/parser/parsers/equation.py +65 -0
  99. notionary/page/content/parser/parsers/file.py +42 -0
  100. notionary/page/content/parser/parsers/heading.py +115 -0
  101. notionary/page/content/parser/parsers/image.py +42 -0
  102. notionary/page/content/parser/parsers/numbered_list.py +89 -0
  103. notionary/page/content/parser/parsers/paragraph.py +37 -0
  104. notionary/page/content/parser/parsers/pdf.py +42 -0
  105. notionary/page/content/parser/parsers/quote.py +125 -0
  106. notionary/page/content/parser/parsers/space.py +41 -0
  107. notionary/page/content/parser/parsers/table.py +144 -0
  108. notionary/page/content/parser/parsers/table_of_contents.py +32 -0
  109. notionary/page/content/parser/parsers/todo.py +96 -0
  110. notionary/page/content/parser/parsers/toggle.py +70 -0
  111. notionary/page/content/parser/parsers/video.py +42 -0
  112. notionary/page/content/parser/post_processing/handlers/__init__.py +5 -0
  113. notionary/page/content/parser/post_processing/handlers/rich_text_length.py +95 -0
  114. notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +114 -0
  115. notionary/page/content/parser/post_processing/port.py +9 -0
  116. notionary/page/content/parser/post_processing/service.py +16 -0
  117. notionary/page/content/parser/pre_processsing/handlers/__init__.py +11 -0
  118. notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +130 -0
  119. notionary/page/content/parser/pre_processsing/handlers/indentation.py +84 -0
  120. notionary/page/content/parser/pre_processsing/handlers/port.py +7 -0
  121. notionary/page/content/parser/pre_processsing/handlers/whitespace.py +73 -0
  122. notionary/page/content/parser/pre_processsing/service.py +15 -0
  123. notionary/page/content/parser/service.py +78 -0
  124. notionary/page/content/renderer/context.py +51 -0
  125. notionary/page/content/renderer/factory.py +231 -0
  126. notionary/page/content/renderer/post_processing/handlers/__init__.py +5 -0
  127. notionary/page/content/renderer/post_processing/handlers/numbered_list.py +156 -0
  128. notionary/page/content/renderer/post_processing/port.py +7 -0
  129. notionary/page/content/renderer/post_processing/service.py +15 -0
  130. notionary/page/content/renderer/renderers/__init__.py +55 -0
  131. notionary/page/content/renderer/renderers/audio.py +31 -0
  132. notionary/page/content/renderer/renderers/base.py +31 -0
  133. notionary/page/content/renderer/renderers/bookmark.py +25 -0
  134. notionary/page/content/renderer/renderers/breadcrumb.py +21 -0
  135. notionary/page/content/renderer/renderers/bulleted_list.py +48 -0
  136. notionary/page/content/renderer/renderers/callout.py +50 -0
  137. notionary/page/content/renderer/renderers/captioned_block.py +58 -0
  138. notionary/page/content/renderer/renderers/code.py +34 -0
  139. notionary/page/content/renderer/renderers/column.py +53 -0
  140. notionary/page/content/renderer/renderers/column_list.py +44 -0
  141. notionary/page/content/renderer/renderers/divider.py +22 -0
  142. notionary/page/content/renderer/renderers/embed.py +25 -0
  143. notionary/page/content/renderer/renderers/equation.py +37 -0
  144. notionary/page/content/renderer/renderers/fallback.py +24 -0
  145. notionary/page/content/renderer/renderers/file.py +40 -0
  146. notionary/page/content/renderer/renderers/heading.py +95 -0
  147. notionary/page/content/renderer/renderers/image.py +31 -0
  148. notionary/page/content/renderer/renderers/numbered_list.py +42 -0
  149. notionary/page/content/renderer/renderers/paragraph.py +40 -0
  150. notionary/page/content/renderer/renderers/pdf.py +31 -0
  151. notionary/page/content/renderer/renderers/quote.py +49 -0
  152. notionary/page/content/renderer/renderers/table.py +115 -0
  153. notionary/page/content/renderer/renderers/table_of_contents.py +26 -0
  154. notionary/page/content/renderer/renderers/table_row.py +17 -0
  155. notionary/page/content/renderer/renderers/todo.py +56 -0
  156. notionary/page/content/renderer/renderers/toggle.py +52 -0
  157. notionary/page/content/renderer/renderers/video.py +31 -0
  158. notionary/page/content/renderer/service.py +50 -0
  159. notionary/page/content/service.py +68 -0
  160. notionary/page/content/syntax/__init__.py +4 -0
  161. notionary/page/content/syntax/grammar.py +10 -0
  162. notionary/page/content/syntax/models.py +66 -0
  163. notionary/page/content/syntax/registry.py +393 -0
  164. notionary/page/page_context.py +7 -16
  165. notionary/page/page_http_client.py +15 -0
  166. notionary/page/page_metadata_update_client.py +19 -0
  167. notionary/page/properties/client.py +144 -0
  168. notionary/page/properties/factory.py +26 -0
  169. notionary/page/properties/models.py +308 -0
  170. notionary/page/properties/service.py +261 -0
  171. notionary/page/schemas.py +13 -0
  172. notionary/page/service.py +225 -0
  173. notionary/shared/entity/client.py +29 -0
  174. notionary/shared/entity/dto_parsers.py +53 -0
  175. notionary/shared/entity/entity_metadata_update_client.py +41 -0
  176. notionary/shared/entity/schemas.py +45 -0
  177. notionary/shared/entity/service.py +171 -0
  178. notionary/shared/models/cover.py +20 -0
  179. notionary/shared/models/file.py +21 -0
  180. notionary/shared/models/icon.py +28 -0
  181. notionary/shared/models/parent.py +41 -0
  182. notionary/shared/properties/type.py +30 -0
  183. notionary/shared/typings.py +3 -0
  184. notionary/user/__init__.py +4 -8
  185. notionary/user/base.py +138 -0
  186. notionary/user/bot.py +70 -0
  187. notionary/user/client.py +22 -111
  188. notionary/user/person.py +41 -0
  189. notionary/user/schemas.py +67 -0
  190. notionary/user/service.py +65 -0
  191. notionary/utils/date.py +51 -0
  192. notionary/utils/decorators.py +122 -0
  193. notionary/utils/fuzzy.py +68 -0
  194. notionary/utils/mixins/logging.py +58 -0
  195. notionary/utils/pagination.py +100 -0
  196. notionary/utils/uuid_utils.py +20 -0
  197. notionary/workspace/__init__.py +4 -0
  198. notionary/workspace/client.py +62 -0
  199. notionary/workspace/query/__init__.py +3 -0
  200. notionary/workspace/query/builder.py +60 -0
  201. notionary/workspace/query/models.py +61 -0
  202. notionary/workspace/query/service.py +100 -0
  203. notionary/workspace/schemas.py +21 -0
  204. notionary/workspace/service.py +116 -0
  205. notionary-0.3.0.dist-info/METADATA +201 -0
  206. notionary-0.3.0.dist-info/RECORD +209 -0
  207. {notionary-0.2.27.dist-info → notionary-0.3.0.dist-info}/WHEEL +1 -1
  208. {notionary-0.2.27.dist-info → notionary-0.3.0.dist-info/licenses}/LICENSE +9 -9
  209. notionary/base_notion_client.py +0 -219
  210. notionary/blocks/_bootstrap.py +0 -271
  211. notionary/blocks/audio/__init__.py +0 -11
  212. notionary/blocks/audio/audio_element.py +0 -158
  213. notionary/blocks/audio/audio_markdown_node.py +0 -24
  214. notionary/blocks/audio/audio_models.py +0 -10
  215. notionary/blocks/base_block_element.py +0 -42
  216. notionary/blocks/bookmark/__init__.py +0 -12
  217. notionary/blocks/bookmark/bookmark_element.py +0 -83
  218. notionary/blocks/bookmark/bookmark_markdown_node.py +0 -28
  219. notionary/blocks/bookmark/bookmark_models.py +0 -15
  220. notionary/blocks/breadcrumbs/__init__.py +0 -15
  221. notionary/blocks/breadcrumbs/breadcrumb_element.py +0 -39
  222. notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +0 -13
  223. notionary/blocks/breadcrumbs/breadcrumb_models.py +0 -12
  224. notionary/blocks/bulleted_list/__init__.py +0 -15
  225. notionary/blocks/bulleted_list/bulleted_list_element.py +0 -74
  226. notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +0 -20
  227. notionary/blocks/bulleted_list/bulleted_list_models.py +0 -17
  228. notionary/blocks/callout/__init__.py +0 -12
  229. notionary/blocks/callout/callout_element.py +0 -99
  230. notionary/blocks/callout/callout_markdown_node.py +0 -19
  231. notionary/blocks/callout/callout_models.py +0 -33
  232. notionary/blocks/child_database/__init__.py +0 -14
  233. notionary/blocks/child_database/child_database_element.py +0 -59
  234. notionary/blocks/child_database/child_database_models.py +0 -12
  235. notionary/blocks/child_page/__init__.py +0 -9
  236. notionary/blocks/child_page/child_page_element.py +0 -94
  237. notionary/blocks/child_page/child_page_models.py +0 -12
  238. notionary/blocks/code/__init__.py +0 -11
  239. notionary/blocks/code/code_element.py +0 -149
  240. notionary/blocks/code/code_markdown_node.py +0 -80
  241. notionary/blocks/code/code_models.py +0 -94
  242. notionary/blocks/column/__init__.py +0 -25
  243. notionary/blocks/column/column_element.py +0 -65
  244. notionary/blocks/column/column_list_element.py +0 -52
  245. notionary/blocks/column/column_list_markdown_node.py +0 -34
  246. notionary/blocks/column/column_markdown_node.py +0 -42
  247. notionary/blocks/column/column_models.py +0 -26
  248. notionary/blocks/divider/__init__.py +0 -12
  249. notionary/blocks/divider/divider_element.py +0 -41
  250. notionary/blocks/divider/divider_markdown_node.py +0 -11
  251. notionary/blocks/divider/divider_models.py +0 -12
  252. notionary/blocks/embed/__init__.py +0 -12
  253. notionary/blocks/embed/embed_element.py +0 -98
  254. notionary/blocks/embed/embed_markdown_node.py +0 -19
  255. notionary/blocks/embed/embed_models.py +0 -14
  256. notionary/blocks/equation/__init__.py +0 -13
  257. notionary/blocks/equation/equation_element.py +0 -133
  258. notionary/blocks/equation/equation_element_markdown_node.py +0 -23
  259. notionary/blocks/equation/equation_models.py +0 -11
  260. notionary/blocks/file/__init__.py +0 -23
  261. notionary/blocks/file/file_element.py +0 -133
  262. notionary/blocks/file/file_element_markdown_node.py +0 -24
  263. notionary/blocks/file/file_element_models.py +0 -39
  264. notionary/blocks/heading/__init__.py +0 -19
  265. notionary/blocks/heading/heading_element.py +0 -112
  266. notionary/blocks/heading/heading_markdown_node.py +0 -16
  267. notionary/blocks/heading/heading_models.py +0 -29
  268. notionary/blocks/image_block/__init__.py +0 -11
  269. notionary/blocks/image_block/image_element.py +0 -130
  270. notionary/blocks/image_block/image_markdown_node.py +0 -25
  271. notionary/blocks/image_block/image_models.py +0 -10
  272. notionary/blocks/markdown/markdown_builder.py +0 -525
  273. notionary/blocks/markdown/markdown_document_model.py +0 -0
  274. notionary/blocks/markdown/markdown_node.py +0 -25
  275. notionary/blocks/mixins/captions/__init__.py +0 -4
  276. notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +0 -31
  277. notionary/blocks/mixins/captions/caption_mixin.py +0 -92
  278. notionary/blocks/mixins/file_upload/__init__.py +0 -3
  279. notionary/blocks/mixins/file_upload/file_upload_mixin.py +0 -320
  280. notionary/blocks/models.py +0 -174
  281. notionary/blocks/numbered_list/__init__.py +0 -16
  282. notionary/blocks/numbered_list/numbered_list_element.py +0 -65
  283. notionary/blocks/numbered_list/numbered_list_markdown_node.py +0 -17
  284. notionary/blocks/numbered_list/numbered_list_models.py +0 -17
  285. notionary/blocks/paragraph/__init__.py +0 -15
  286. notionary/blocks/paragraph/paragraph_element.py +0 -58
  287. notionary/blocks/paragraph/paragraph_markdown_node.py +0 -16
  288. notionary/blocks/paragraph/paragraph_models.py +0 -16
  289. notionary/blocks/pdf/__init__.py +0 -11
  290. notionary/blocks/pdf/pdf_element.py +0 -146
  291. notionary/blocks/pdf/pdf_markdown_node.py +0 -24
  292. notionary/blocks/pdf/pdf_models.py +0 -11
  293. notionary/blocks/quote/__init__.py +0 -14
  294. notionary/blocks/quote/quote_element.py +0 -75
  295. notionary/blocks/quote/quote_markdown_node.py +0 -16
  296. notionary/blocks/quote/quote_models.py +0 -18
  297. notionary/blocks/registry/__init__.py +0 -3
  298. notionary/blocks/registry/block_registry.py +0 -150
  299. notionary/blocks/rich_text/__init__.py +0 -33
  300. notionary/blocks/rich_text/rich_text_models.py +0 -221
  301. notionary/blocks/rich_text/text_inline_formatter.py +0 -456
  302. notionary/blocks/syntax_prompt_builder.py +0 -137
  303. notionary/blocks/table/__init__.py +0 -19
  304. notionary/blocks/table/table_element.py +0 -225
  305. notionary/blocks/table/table_markdown_node.py +0 -42
  306. notionary/blocks/table/table_models.py +0 -28
  307. notionary/blocks/table_of_contents/__init__.py +0 -17
  308. notionary/blocks/table_of_contents/table_of_contents_element.py +0 -80
  309. notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +0 -21
  310. notionary/blocks/table_of_contents/table_of_contents_models.py +0 -18
  311. notionary/blocks/todo/__init__.py +0 -12
  312. notionary/blocks/todo/todo_element.py +0 -81
  313. notionary/blocks/todo/todo_markdown_node.py +0 -21
  314. notionary/blocks/todo/todo_models.py +0 -18
  315. notionary/blocks/toggle/__init__.py +0 -12
  316. notionary/blocks/toggle/toggle_element.py +0 -112
  317. notionary/blocks/toggle/toggle_markdown_node.py +0 -31
  318. notionary/blocks/toggle/toggle_models.py +0 -17
  319. notionary/blocks/toggleable_heading/__init__.py +0 -11
  320. notionary/blocks/toggleable_heading/toggleable_heading_element.py +0 -115
  321. notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +0 -34
  322. notionary/blocks/types.py +0 -130
  323. notionary/blocks/video/__init__.py +0 -11
  324. notionary/blocks/video/video_element.py +0 -187
  325. notionary/blocks/video/video_element_models.py +0 -10
  326. notionary/blocks/video/video_markdown_node.py +0 -26
  327. notionary/database/__init__.py +0 -4
  328. notionary/database/database.py +0 -480
  329. notionary/database/database_filter_builder.py +0 -173
  330. notionary/database/database_provider.py +0 -227
  331. notionary/database/exceptions.py +0 -13
  332. notionary/database/models.py +0 -337
  333. notionary/database/notion_database.py +0 -487
  334. notionary/file_upload/__init__.py +0 -7
  335. notionary/page/client.py +0 -124
  336. notionary/page/markdown_whitespace_processor.py +0 -129
  337. notionary/page/models.py +0 -322
  338. notionary/page/notion_page.py +0 -712
  339. notionary/page/page_content_deleting_service.py +0 -117
  340. notionary/page/page_content_writer.py +0 -80
  341. notionary/page/property_formatter.py +0 -99
  342. notionary/page/reader/handler/__init__.py +0 -19
  343. notionary/page/reader/handler/base_block_renderer.py +0 -44
  344. notionary/page/reader/handler/block_processing_context.py +0 -35
  345. notionary/page/reader/handler/block_rendering_context.py +0 -48
  346. notionary/page/reader/handler/column_list_renderer.py +0 -51
  347. notionary/page/reader/handler/column_renderer.py +0 -60
  348. notionary/page/reader/handler/equation_renderer.py +0 -0
  349. notionary/page/reader/handler/line_renderer.py +0 -73
  350. notionary/page/reader/handler/numbered_list_renderer.py +0 -85
  351. notionary/page/reader/handler/toggle_renderer.py +0 -69
  352. notionary/page/reader/handler/toggleable_heading_renderer.py +0 -89
  353. notionary/page/reader/page_content_retriever.py +0 -81
  354. notionary/page/search_filter_builder.py +0 -132
  355. notionary/page/utils.py +0 -60
  356. notionary/page/writer/handler/__init__.py +0 -24
  357. notionary/page/writer/handler/code_handler.py +0 -72
  358. notionary/page/writer/handler/column_handler.py +0 -141
  359. notionary/page/writer/handler/column_list_handler.py +0 -139
  360. notionary/page/writer/handler/equation_handler.py +0 -74
  361. notionary/page/writer/handler/line_handler.py +0 -35
  362. notionary/page/writer/handler/line_processing_context.py +0 -54
  363. notionary/page/writer/handler/regular_line_handler.py +0 -86
  364. notionary/page/writer/handler/table_handler.py +0 -66
  365. notionary/page/writer/handler/toggle_handler.py +0 -159
  366. notionary/page/writer/handler/toggleable_heading_handler.py +0 -174
  367. notionary/page/writer/markdown_to_notion_converter.py +0 -139
  368. notionary/page/writer/markdown_to_notion_converter_context.py +0 -30
  369. notionary/page/writer/markdown_to_notion_text_length_post_processor.py +0 -0
  370. notionary/page/writer/notion_text_length_processor.py +0 -150
  371. notionary/schemas/__init__.py +0 -3
  372. notionary/schemas/base.py +0 -73
  373. notionary/shared/__init__.py +0 -3
  374. notionary/shared/name_to_id_resolver.py +0 -203
  375. notionary/telemetry/__init__.py +0 -19
  376. notionary/telemetry/service.py +0 -136
  377. notionary/telemetry/views.py +0 -73
  378. notionary/user/base_notion_user.py +0 -53
  379. notionary/user/models.py +0 -84
  380. notionary/user/notion_bot_user.py +0 -226
  381. notionary/user/notion_user.py +0 -255
  382. notionary/user/notion_user_manager.py +0 -101
  383. notionary/util/__init__.py +0 -15
  384. notionary/util/concurrency_limiter.py +0 -0
  385. notionary/util/factory_decorator.py +0 -0
  386. notionary/util/factory_only.py +0 -37
  387. notionary/util/fuzzy.py +0 -75
  388. notionary/util/logging_mixin.py +0 -59
  389. notionary/util/page_id_utils.py +0 -27
  390. notionary/util/singleton.py +0 -18
  391. notionary/util/singleton_metaclass.py +0 -22
  392. notionary/workspace.py +0 -105
  393. notionary-0.2.27.dist-info/METADATA +0 -270
  394. notionary-0.2.27.dist-info/RECORD +0 -202
  395. /notionary/{database → user}/factory.py +0 -0
@@ -1,219 +0,0 @@
1
- import asyncio
2
- import os
3
- from abc import ABC
4
- from enum import Enum
5
- from typing import Any, Dict, Optional, Union
6
-
7
- import httpx
8
- from dotenv import load_dotenv
9
-
10
- from notionary.util import LoggingMixin
11
-
12
- load_dotenv()
13
-
14
-
15
- class HttpMethod(Enum):
16
- """
17
- Enumeration of supported HTTP methods for API requests.
18
- """
19
-
20
- GET = "get"
21
- POST = "post"
22
- PATCH = "patch"
23
- DELETE = "delete"
24
-
25
-
26
- class BaseNotionClient(LoggingMixin, ABC):
27
- """
28
- Base client for Notion API operations.
29
- Handles connection management and generic HTTP requests.
30
- """
31
-
32
- BASE_URL = "https://api.notion.com/v1"
33
- NOTION_VERSION = "2022-06-28"
34
-
35
- def __init__(self, token: Optional[str] = None, timeout: int = 30):
36
- self.token = token or self._find_token()
37
- if not self.token:
38
- raise ValueError("Notion API token is required")
39
-
40
- self.headers = {
41
- "Authorization": f"Bearer {self.token}",
42
- "Content-Type": "application/json",
43
- "Notion-Version": self.NOTION_VERSION,
44
- }
45
-
46
- self.client: Optional[httpx.AsyncClient] = None
47
- self.timeout = timeout
48
- self._is_initialized = False
49
-
50
- def __del__(self):
51
- """Auto-cleanup when client is destroyed."""
52
- if not hasattr(self, "client") or not self.client:
53
- return
54
-
55
- try:
56
- loop = asyncio.get_event_loop()
57
- if not loop.is_running():
58
- self.logger.warning(
59
- "Event loop not running, could not auto-close NotionClient"
60
- )
61
- return
62
-
63
- loop.create_task(self.close())
64
- self.logger.debug("Created cleanup task for NotionClient")
65
- except RuntimeError:
66
- self.logger.warning("No event loop available for auto-closing NotionClient")
67
-
68
- async def __aenter__(self):
69
- """Async context manager entry."""
70
- await self.ensure_initialized()
71
- return self
72
-
73
- async def __aexit__(self, exc_type, exc_val, exc_tb):
74
- """Async context manager exit."""
75
- await self.close()
76
-
77
- async def ensure_initialized(self) -> None:
78
- """
79
- Ensures the HTTP client is initialized.
80
- """
81
- if not self._is_initialized or not self.client:
82
- self.client = httpx.AsyncClient(headers=self.headers, timeout=self.timeout)
83
- self._is_initialized = True
84
- self.logger.debug("NotionClient initialized")
85
-
86
- async def close(self) -> None:
87
- """
88
- Closes the HTTP client and releases resources.
89
- """
90
- if not hasattr(self, "client") or not self.client:
91
- return
92
-
93
- await self.client.aclose()
94
- self.client = None
95
- self._is_initialized = False
96
- self.logger.debug("NotionClient closed")
97
-
98
- async def get(
99
- self, endpoint: str, params: Optional[Dict[str, Any]] = None
100
- ) -> Optional[Dict[str, Any]]:
101
- """
102
- Sends a GET request to the specified Notion API endpoint.
103
-
104
- Args:
105
- endpoint: The API endpoint (without base URL)
106
- params: Query parameters to include in the request
107
- """
108
- return await self._make_request(HttpMethod.GET, endpoint, params=params)
109
-
110
- async def post(
111
- self, endpoint: str, data: Optional[Dict[str, Any]] = None
112
- ) -> Optional[Dict[str, Any]]:
113
- """
114
- Sends a POST request to the specified Notion API endpoint.
115
-
116
- Args:
117
- endpoint: The API endpoint (without base URL)
118
- data: Request body data
119
- """
120
- return await self._make_request(HttpMethod.POST, endpoint, data)
121
-
122
- async def patch(
123
- self, endpoint: str, data: Optional[Dict[str, Any]] = None
124
- ) -> Optional[Dict[str, Any]]:
125
- """
126
- Sends a PATCH request to the specified Notion API endpoint.
127
-
128
- Args:
129
- endpoint: The API endpoint (without base URL)
130
- data: Request body data
131
- """
132
- return await self._make_request(HttpMethod.PATCH, endpoint, data)
133
-
134
- async def delete(self, endpoint: str) -> bool:
135
- """
136
- Sends a DELETE request to the specified Notion API endpoint.
137
-
138
- Args:
139
- endpoint: The API endpoint (without base URL)
140
- """
141
- result = await self._make_request(HttpMethod.DELETE, endpoint)
142
- return result is not None
143
-
144
- async def _make_request(
145
- self,
146
- method: Union[HttpMethod, str],
147
- endpoint: str,
148
- data: Optional[Dict[str, Any]] = None,
149
- params: Optional[Dict[str, Any]] = None,
150
- ) -> Optional[Dict[str, Any]]:
151
- """
152
- Executes an HTTP request and returns the data or None on error.
153
-
154
- Args:
155
- method: HTTP method to use
156
- endpoint: API endpoint
157
- data: Request body data (for POST/PATCH)
158
- params: Query parameters (for GET requests)
159
- """
160
- await self.ensure_initialized()
161
-
162
- url = f"{self.BASE_URL}/{endpoint.lstrip('/')}"
163
- method_str = (
164
- method.value if isinstance(method, HttpMethod) else str(method).lower()
165
- )
166
-
167
- try:
168
- self.logger.debug("Sending %s request to %s", method_str.upper(), url)
169
-
170
- request_kwargs = {}
171
-
172
- # Add query parameters for GET requests
173
- if params:
174
- request_kwargs["params"] = params
175
-
176
- if (
177
- method_str in [HttpMethod.POST.value, HttpMethod.PATCH.value]
178
- and data is not None
179
- ):
180
- request_kwargs["json"] = data
181
-
182
- response: httpx.Response = await getattr(self.client, method_str)(
183
- url, **request_kwargs
184
- )
185
-
186
- response.raise_for_status()
187
- result_data = response.json()
188
- self.logger.debug("Request successful: %s", url)
189
- return result_data
190
-
191
- except httpx.HTTPStatusError as e:
192
- error_msg = (
193
- f"HTTP status error: {e.response.status_code} - {e.response.text}"
194
- )
195
- self.logger.error("Request failed (%s): %s", url, error_msg)
196
- return None
197
-
198
- except httpx.RequestError as e:
199
- error_msg = f"Request error: {str(e)}"
200
- self.logger.error("Request error (%s): %s", url, error_msg)
201
- return None
202
-
203
- def _find_token(self) -> Optional[str]:
204
- """
205
- Finds the Notion API token from environment variables.
206
- """
207
- token = next(
208
- (
209
- os.getenv(var)
210
- for var in ("NOTION_SECRET", "NOTION_INTEGRATION_KEY", "NOTION_TOKEN")
211
- if os.getenv(var)
212
- ),
213
- None,
214
- )
215
- if token:
216
- self.logger.debug("Found token in environment variable.")
217
- return token
218
- self.logger.warning("No Notion API token found in environment variables")
219
- return None
@@ -1,271 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Optional, Union
4
-
5
- _bootstrapped = False
6
-
7
-
8
- def bootstrap_blocks() -> None:
9
- global _bootstrapped
10
- if _bootstrapped:
11
- return
12
-
13
- from notionary.blocks import (
14
- bookmark,
15
- breadcrumbs,
16
- bulleted_list,
17
- callout,
18
- child_page,
19
- code,
20
- column,
21
- divider,
22
- embed,
23
- equation,
24
- file,
25
- heading,
26
- image_block,
27
- models,
28
- numbered_list,
29
- paragraph,
30
- quote,
31
- table,
32
- table_of_contents,
33
- todo,
34
- toggle,
35
- toggleable_heading,
36
- video,
37
- child_database,
38
- )
39
-
40
- # Collect all exports from modules
41
- ns = {}
42
- for m in (
43
- bookmark,
44
- breadcrumbs,
45
- bulleted_list,
46
- callout,
47
- child_page,
48
- code,
49
- column,
50
- divider,
51
- embed,
52
- equation,
53
- file,
54
- heading,
55
- image_block,
56
- numbered_list,
57
- paragraph,
58
- quote,
59
- table,
60
- todo,
61
- toggle,
62
- video,
63
- toggleable_heading,
64
- table_of_contents,
65
- child_database,
66
- ):
67
- ns.update(vars(m))
68
-
69
- # Add missing types that are needed for model rebuilding
70
- # These are the types that are only defined in TYPE_CHECKING in block_models
71
- from notionary.blocks.bookmark.bookmark_models import (
72
- BookmarkBlock,
73
- CreateBookmarkBlock,
74
- )
75
- from notionary.blocks.breadcrumbs.breadcrumb_models import (
76
- BreadcrumbBlock,
77
- CreateBreadcrumbBlock,
78
- )
79
- from notionary.blocks.bulleted_list.bulleted_list_models import (
80
- BulletedListItemBlock,
81
- CreateBulletedListItemBlock,
82
- )
83
- from notionary.blocks.callout.callout_models import CalloutBlock, CreateCalloutBlock
84
- from notionary.blocks.child_page.child_page_models import (
85
- ChildPageBlock,
86
- CreateChildPageBlock,
87
- )
88
- from notionary.blocks.code.code_models import CodeBlock, CreateCodeBlock
89
- from notionary.blocks.column.column_models import (
90
- ColumnBlock,
91
- ColumnListBlock,
92
- CreateColumnBlock,
93
- CreateColumnListBlock,
94
- )
95
- from notionary.blocks.divider.divider_models import CreateDividerBlock, DividerBlock
96
- from notionary.blocks.embed.embed_models import CreateEmbedBlock, EmbedBlock
97
- from notionary.blocks.equation.equation_models import (
98
- CreateEquationBlock,
99
- EquationBlock,
100
- )
101
- from notionary.blocks.file.file_element_models import CreateFileBlock, FileBlock
102
- from notionary.blocks.heading.heading_models import (
103
- CreateHeading1Block,
104
- CreateHeading2Block,
105
- CreateHeading3Block,
106
- HeadingBlock,
107
- )
108
- from notionary.blocks.image_block.image_models import CreateImageBlock
109
- from notionary.blocks.numbered_list.numbered_list_models import (
110
- CreateNumberedListItemBlock,
111
- NumberedListItemBlock,
112
- )
113
- from notionary.blocks.paragraph.paragraph_models import (
114
- CreateParagraphBlock,
115
- ParagraphBlock,
116
- )
117
- from notionary.blocks.pdf.pdf_models import CreatePdfBlock
118
- from notionary.blocks.quote.quote_models import CreateQuoteBlock, QuoteBlock
119
- from notionary.blocks.table.table_models import TableBlock, TableRowBlock
120
- from notionary.blocks.table_of_contents.table_of_contents_models import (
121
- CreateTableOfContentsBlock,
122
- TableOfContentsBlock,
123
- )
124
- from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
125
- from notionary.blocks.toggle.toggle_models import CreateToggleBlock, ToggleBlock
126
- from notionary.blocks.types import BlockType
127
- from notionary.blocks.video.video_element_models import CreateVideoBlock
128
- from notionary.blocks.child_database.child_database_models import (
129
- CreateChildDatabaseBlock,
130
- ChildDatabaseBlock,
131
- )
132
-
133
- # Define the Union types that are needed for model rebuilding
134
- BlockCreateRequest = Union[
135
- CreateBookmarkBlock,
136
- CreateBreadcrumbBlock,
137
- CreateBulletedListItemBlock,
138
- CreateCalloutBlock,
139
- CreateChildPageBlock,
140
- CreateCodeBlock,
141
- CreateColumnListBlock,
142
- CreateColumnBlock,
143
- CreateDividerBlock,
144
- CreateEmbedBlock,
145
- CreateEquationBlock,
146
- CreateFileBlock,
147
- CreateHeading1Block,
148
- CreateHeading2Block,
149
- CreateHeading3Block,
150
- CreateImageBlock,
151
- CreateNumberedListItemBlock,
152
- CreateParagraphBlock,
153
- CreateQuoteBlock,
154
- CreateToDoBlock,
155
- CreateToggleBlock,
156
- CreateVideoBlock,
157
- CreateTableOfContentsBlock,
158
- CreatePdfBlock,
159
- CreateChildDatabaseBlock,
160
- ]
161
-
162
- BlockCreateResult = Optional[BlockCreateRequest]
163
-
164
- # Add all block types to namespace
165
- ns.update(
166
- {
167
- "BlockType": BlockType,
168
- "BookmarkBlock": BookmarkBlock,
169
- "CreateBookmarkBlock": CreateBookmarkBlock,
170
- "BreadcrumbBlock": BreadcrumbBlock,
171
- "CreateBreadcrumbBlock": CreateBreadcrumbBlock,
172
- "BulletedListItemBlock": BulletedListItemBlock,
173
- "CreateBulletedListItemBlock": CreateBulletedListItemBlock,
174
- "CalloutBlock": CalloutBlock,
175
- "CreateCalloutBlock": CreateCalloutBlock,
176
- "ChildPageBlock": ChildPageBlock,
177
- "CreateChildPageBlock": CreateChildPageBlock,
178
- "CodeBlock": CodeBlock,
179
- "CreateCodeBlock": CreateCodeBlock,
180
- "ColumnBlock": ColumnBlock,
181
- "ColumnListBlock": ColumnListBlock,
182
- "CreateColumnBlock": CreateColumnBlock,
183
- "CreateColumnListBlock": CreateColumnListBlock,
184
- "DividerBlock": DividerBlock,
185
- "CreateDividerBlock": CreateDividerBlock,
186
- "EmbedBlock": EmbedBlock,
187
- "CreateEmbedBlock": CreateEmbedBlock,
188
- "EquationBlock": EquationBlock,
189
- "CreateEquationBlock": CreateEquationBlock,
190
- "FileBlock": FileBlock,
191
- "CreateFileBlock": CreateFileBlock,
192
- "HeadingBlock": HeadingBlock,
193
- "CreateHeading1Block": CreateHeading1Block,
194
- "CreateHeading2Block": CreateHeading2Block,
195
- "CreateHeading3Block": CreateHeading3Block,
196
- "CreateImageBlock": CreateImageBlock,
197
- "NumberedListItemBlock": NumberedListItemBlock,
198
- "CreateNumberedListItemBlock": CreateNumberedListItemBlock,
199
- "ParagraphBlock": ParagraphBlock,
200
- "CreateParagraphBlock": CreateParagraphBlock,
201
- "QuoteBlock": QuoteBlock,
202
- "CreateQuoteBlock": CreateQuoteBlock,
203
- "TableBlock": TableBlock,
204
- "TableRowBlock": TableRowBlock,
205
- "ToDoBlock": ToDoBlock,
206
- "CreateToDoBlock": CreateToDoBlock,
207
- "ToggleBlock": ToggleBlock,
208
- "CreateToggleBlock": CreateToggleBlock,
209
- "CreateVideoBlock": CreateVideoBlock,
210
- "TableOfContentsBlock": TableOfContentsBlock,
211
- "CreateTableOfContentsBlock": CreateTableOfContentsBlock,
212
- "ChildDatabaseBlock": ChildDatabaseBlock,
213
- # Add the Union types
214
- "BlockCreateRequest": BlockCreateRequest,
215
- "BlockCreateResult": BlockCreateResult,
216
- }
217
- )
218
-
219
- # Now rebuild with complete namespace
220
- models.Block.model_rebuild(_types_namespace=ns)
221
- models.BlockChildrenResponse.model_rebuild(_types_namespace=ns)
222
-
223
- # Rebuild all individual block models
224
- BookmarkBlock.model_rebuild()
225
- BreadcrumbBlock.model_rebuild()
226
- BulletedListItemBlock.model_rebuild()
227
- CalloutBlock.model_rebuild()
228
- ChildPageBlock.model_rebuild()
229
- CodeBlock.model_rebuild()
230
- ColumnBlock.model_rebuild()
231
- ColumnListBlock.model_rebuild()
232
- DividerBlock.model_rebuild()
233
- EmbedBlock.model_rebuild()
234
- EquationBlock.model_rebuild()
235
- FileBlock.model_rebuild()
236
- HeadingBlock.model_rebuild()
237
- NumberedListItemBlock.model_rebuild()
238
- ParagraphBlock.model_rebuild()
239
- QuoteBlock.model_rebuild()
240
- TableBlock.model_rebuild()
241
- TableRowBlock.model_rebuild()
242
- ToDoBlock.model_rebuild()
243
- ToggleBlock.model_rebuild()
244
- TableOfContentsBlock.model_rebuild()
245
-
246
- # Rebuild create models
247
- CreateBookmarkBlock.model_rebuild()
248
- CreateBreadcrumbBlock.model_rebuild()
249
- CreateBulletedListItemBlock.model_rebuild()
250
- CreateCalloutBlock.model_rebuild()
251
- CreateChildPageBlock.model_rebuild()
252
- CreateCodeBlock.model_rebuild()
253
- CreateColumnListBlock.model_rebuild()
254
- CreateColumnBlock.model_rebuild()
255
- CreateDividerBlock.model_rebuild()
256
- CreateEmbedBlock.model_rebuild()
257
- CreateEquationBlock.model_rebuild()
258
- CreateFileBlock.model_rebuild()
259
- CreateHeading1Block.model_rebuild()
260
- CreateHeading2Block.model_rebuild()
261
- CreateHeading3Block.model_rebuild()
262
- CreateImageBlock.model_rebuild()
263
- CreateNumberedListItemBlock.model_rebuild()
264
- CreateParagraphBlock.model_rebuild()
265
- CreateQuoteBlock.model_rebuild()
266
- CreateToDoBlock.model_rebuild()
267
- CreateToggleBlock.model_rebuild()
268
- CreateVideoBlock.model_rebuild()
269
- CreateTableOfContentsBlock.model_rebuild()
270
-
271
- _bootstrapped = True
@@ -1,11 +0,0 @@
1
- from notionary.blocks.audio.audio_element import AudioElement
2
- from notionary.blocks.audio.audio_markdown_node import (
3
- AudioMarkdownNode,
4
- )
5
- from notionary.blocks.audio.audio_models import CreateAudioBlock
6
-
7
- __all__ = [
8
- "AudioElement",
9
- "CreateAudioBlock",
10
- "AudioMarkdownNode",
11
- ]
@@ -1,158 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import re
4
- from pathlib import Path
5
- from typing import Optional
6
-
7
- from notionary.blocks.audio.audio_models import CreateAudioBlock
8
- from notionary.blocks.base_block_element import BaseBlockElement
9
- from notionary.blocks.file.file_element_models import (
10
- ExternalFile,
11
- FileBlock,
12
- FileType,
13
- FileUploadFile,
14
- )
15
- from notionary.blocks.mixins.captions import CaptionMixin
16
- from notionary.blocks.mixins.file_upload.file_upload_mixin import FileUploadMixin
17
- from notionary.blocks.syntax_prompt_builder import BlockElementMarkdownInformation
18
- from notionary.blocks.models import Block, BlockCreateResult, BlockType
19
- from notionary.util.logging_mixin import LoggingMixin
20
-
21
-
22
- class AudioElement(BaseBlockElement, FileUploadMixin, LoggingMixin, CaptionMixin):
23
- r"""
24
- Handles conversion between Markdown audio embeds and Notion audio blocks.
25
-
26
- Supports both external URLs and local audio file uploads.
27
-
28
- Markdown audio syntax:
29
- - [audio](https://example.com/audio.mp3) - External URL
30
- - [audio](./local/song.mp3) - Local audio file (will be uploaded)
31
- - [audio](C:\Music\podcast.wav) - Absolute local path (will be uploaded)
32
- - [audio](https://example.com/audio.mp3)(caption:Episode 1) - URL with caption
33
- """
34
-
35
- AUDIO_PATTERN = re.compile(r"\[audio\]\(([^)]+)\)")
36
- SUPPORTED_EXTENSIONS = {".mp3", ".wav", ".ogg", ".oga", ".m4a"}
37
-
38
- @classmethod
39
- def match_notion(cls, block: Block) -> bool:
40
- """Check if this element can handle the given Notion block."""
41
- return block.type == BlockType.AUDIO
42
-
43
- @classmethod
44
- async def markdown_to_notion(cls, text: str) -> Optional[BlockCreateResult]:
45
- """Convert markdown audio embed to Notion audio block."""
46
- # Extract the path/URL
47
- path = cls._extract_audio_path(text.strip())
48
- if not path:
49
- return None
50
-
51
- # Check if it's a local file path
52
- if cls._is_local_file_path(path):
53
- # Verify file exists and has supported extension
54
- audio_path = Path(path)
55
- if not audio_path.exists():
56
- cls.logger.warning(f"Audio file not found: {path}")
57
- return None
58
-
59
- if audio_path.suffix.lower() not in cls.SUPPORTED_EXTENSIONS:
60
- cls.logger.warning(f"Unsupported audio format: {audio_path.suffix}")
61
- return None
62
-
63
- cls.logger.info(f"Uploading local audio file: {path}")
64
-
65
- # Upload the local audio file
66
- file_upload_id = await cls._upload_local_file(path, "audio")
67
- if not file_upload_id:
68
- cls.logger.error(f"Failed to upload audio file: {path}")
69
- return None
70
-
71
- cls.logger.info(
72
- f"Successfully uploaded audio file with ID: {file_upload_id}"
73
- )
74
-
75
- # Use mixin to extract caption (if present anywhere in text)
76
- caption_text = cls.extract_caption(text.strip())
77
- caption_rich_text = cls.build_caption_rich_text(caption_text or "")
78
-
79
- audio_content = FileBlock(
80
- type=FileType.FILE_UPLOAD,
81
- file_upload=FileUploadFile(id=file_upload_id),
82
- caption=caption_rich_text,
83
- )
84
-
85
- return CreateAudioBlock(audio=audio_content)
86
-
87
- else:
88
- # Handle external URL - accept any URL (validation happens at API level)
89
- # Use mixin to extract caption (if present anywhere in text)
90
- caption_text = cls.extract_caption(text.strip())
91
- caption_rich_text = cls.build_caption_rich_text(caption_text or "")
92
-
93
- audio_content = FileBlock(
94
- type=FileType.EXTERNAL,
95
- external=ExternalFile(url=path),
96
- caption=caption_rich_text,
97
- )
98
-
99
- return CreateAudioBlock(audio=audio_content)
100
-
101
- @classmethod
102
- async def notion_to_markdown(cls, block: Block) -> Optional[str]:
103
- """Convert Notion audio block to markdown audio embed."""
104
- if block.type != BlockType.AUDIO or block.audio is None:
105
- return None
106
-
107
- audio = block.audio
108
- url = None
109
-
110
- # Handle both external URLs and uploaded files
111
- if audio.type == FileType.EXTERNAL and audio.external is not None:
112
- url = audio.external.url
113
- elif audio.type == FileType.FILE_UPLOAD and audio.file_upload is not None:
114
- url = audio.file_upload.url
115
-
116
- if not url:
117
- return None
118
-
119
- result = f"[audio]({url})"
120
-
121
- # Add caption if present
122
- caption_markdown = await cls.format_caption_for_markdown(audio.caption or [])
123
- if caption_markdown:
124
- result += caption_markdown
125
-
126
- return result
127
-
128
- @classmethod
129
- def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
130
- """Get system prompt information for audio blocks."""
131
- return BlockElementMarkdownInformation(
132
- block_type=cls.__name__,
133
- description="Audio blocks embed audio files from external URLs or local files with optional captions",
134
- syntax_examples=[
135
- "[audio](https://example.com/song.mp3)",
136
- "[audio](./local/podcast.wav)",
137
- "[audio](C:\\Music\\interview.mp3)",
138
- "[audio](https://example.com/podcast.wav)(caption:Episode 1)",
139
- "(caption:Background music)[audio](./song.mp3)",
140
- "[audio](./interview.mp3)(caption:**Live** interview)",
141
- ],
142
- usage_guidelines="Use for embedding audio files like music, podcasts, or sound effects. Supports both external URLs and local file uploads. Supports common audio formats (mp3, wav, ogg, m4a). Caption supports rich text formatting and is optional.",
143
- )
144
-
145
- @classmethod
146
- def _is_likely_audio_url(cls, url: str) -> bool:
147
- return any(url.lower().endswith(ext) for ext in cls.SUPPORTED_EXTENSIONS)
148
-
149
- @classmethod
150
- def _extract_audio_path(cls, text: str) -> Optional[str]:
151
- """Extract audio path/URL from text, handling caption patterns."""
152
- clean_text = cls.remove_caption(text)
153
-
154
- match = cls.AUDIO_PATTERN.search(clean_text)
155
- if match:
156
- return match.group(1).strip()
157
-
158
- return None
@@ -1,24 +0,0 @@
1
- from typing import Optional
2
-
3
- from notionary.blocks.markdown.markdown_node import MarkdownNode
4
- from notionary.blocks.mixins.captions import CaptionMarkdownNodeMixin
5
-
6
-
7
- class AudioMarkdownNode(MarkdownNode, CaptionMarkdownNodeMixin):
8
- """
9
- Enhanced Audio node with Pydantic integration.
10
- Programmatic interface for creating Notion-style audio blocks.
11
- """
12
-
13
- url: str
14
- caption: Optional[str] = None
15
-
16
- def to_markdown(self) -> str:
17
- """Return the Markdown representation.
18
-
19
- Examples:
20
- - [audio](https://example.com/song.mp3)
21
- - [audio](https://example.com/song.mp3)(caption:Background music)
22
- """
23
- base_markdown = f"[audio]({self.url})"
24
- return self.append_caption_to_markdown(base_markdown, self.caption)
@@ -1,10 +0,0 @@
1
- from typing import Literal
2
-
3
- from pydantic import BaseModel
4
-
5
- from notionary.blocks.file.file_element_models import FileBlock
6
-
7
-
8
- class CreateAudioBlock(BaseModel):
9
- type: Literal["audio"] = "audio"
10
- audio: FileBlock