notionary 0.2.26__py3-none-any.whl → 0.2.28__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 (387) hide show
  1. notionary/__init__.py +5 -20
  2. notionary/blocks/client.py +87 -215
  3. notionary/blocks/enums.py +167 -0
  4. notionary/blocks/rich_text/markdown_rich_text_converter.py +266 -0
  5. notionary/blocks/rich_text/models.py +164 -0
  6. notionary/blocks/rich_text/name_id_resolver/__init__.py +11 -0
  7. notionary/blocks/rich_text/name_id_resolver/database.py +31 -0
  8. notionary/blocks/rich_text/name_id_resolver/page.py +34 -0
  9. notionary/blocks/rich_text/name_id_resolver/person.py +37 -0
  10. notionary/blocks/rich_text/name_id_resolver/port.py +11 -0
  11. notionary/blocks/rich_text/rich_text_markdown_converter.py +132 -0
  12. notionary/blocks/rich_text/rich_text_patterns.py +39 -0
  13. notionary/blocks/schemas.py +746 -0
  14. notionary/comments/client.py +52 -187
  15. notionary/comments/factory.py +40 -0
  16. notionary/comments/models.py +5 -127
  17. notionary/comments/schemas.py +240 -0
  18. notionary/comments/service.py +34 -0
  19. notionary/data_source/http/client.py +11 -0
  20. notionary/data_source/http/data_source_instance_client.py +94 -0
  21. notionary/data_source/properties/models.py +406 -0
  22. notionary/data_source/query/builder.py +429 -0
  23. notionary/data_source/query/resolver.py +114 -0
  24. notionary/data_source/query/schema.py +304 -0
  25. notionary/data_source/query/validator.py +73 -0
  26. notionary/data_source/schemas.py +27 -0
  27. notionary/data_source/service.py +353 -0
  28. notionary/database/client.py +30 -135
  29. notionary/database/database_metadata_update_client.py +19 -0
  30. notionary/database/schemas.py +29 -0
  31. notionary/database/service.py +169 -0
  32. notionary/exceptions/__init__.py +33 -0
  33. notionary/exceptions/api.py +41 -0
  34. notionary/exceptions/base.py +2 -0
  35. notionary/exceptions/block_parsing.py +16 -0
  36. notionary/exceptions/data_source/__init__.py +6 -0
  37. notionary/exceptions/data_source/builder.py +182 -0
  38. notionary/exceptions/data_source/properties.py +34 -0
  39. notionary/exceptions/properties.py +58 -0
  40. notionary/exceptions/search.py +33 -0
  41. notionary/file_upload/client.py +18 -30
  42. notionary/file_upload/models.py +7 -8
  43. notionary/file_upload/{notion_file_upload.py → service.py} +29 -64
  44. notionary/http/client.py +205 -0
  45. notionary/http/models.py +49 -0
  46. notionary/page/blocks/client.py +1 -0
  47. notionary/page/content/factory.py +68 -0
  48. notionary/page/content/markdown/__init__.py +5 -0
  49. notionary/page/content/markdown/builder.py +304 -0
  50. notionary/page/content/markdown/nodes/__init__.py +54 -0
  51. notionary/page/content/markdown/nodes/audio.py +23 -0
  52. notionary/page/content/markdown/nodes/base.py +12 -0
  53. notionary/page/content/markdown/nodes/bookmark.py +25 -0
  54. notionary/page/content/markdown/nodes/breadcrumb.py +14 -0
  55. notionary/page/content/markdown/nodes/bulleted_list.py +18 -0
  56. notionary/page/content/markdown/nodes/callout.py +32 -0
  57. notionary/page/content/markdown/nodes/code.py +30 -0
  58. notionary/page/content/markdown/nodes/columns.py +51 -0
  59. notionary/page/content/markdown/nodes/divider.py +14 -0
  60. notionary/page/content/markdown/nodes/embed.py +23 -0
  61. notionary/page/content/markdown/nodes/equation.py +19 -0
  62. notionary/page/content/markdown/nodes/file.py +23 -0
  63. notionary/page/content/markdown/nodes/heading.py +16 -0
  64. notionary/page/content/markdown/nodes/image.py +23 -0
  65. notionary/page/content/markdown/nodes/mixins/caption.py +12 -0
  66. notionary/page/content/markdown/nodes/numbered_list.py +15 -0
  67. notionary/page/content/markdown/nodes/paragraph.py +14 -0
  68. notionary/page/content/markdown/nodes/pdf.py +23 -0
  69. notionary/page/content/markdown/nodes/quote.py +15 -0
  70. notionary/page/content/markdown/nodes/space.py +14 -0
  71. notionary/page/content/markdown/nodes/table.py +45 -0
  72. notionary/page/content/markdown/nodes/table_of_contents.py +14 -0
  73. notionary/page/content/markdown/nodes/todo.py +22 -0
  74. notionary/page/content/markdown/nodes/toggle.py +28 -0
  75. notionary/page/content/markdown/nodes/toggleable_heading.py +35 -0
  76. notionary/page/content/markdown/nodes/video.py +23 -0
  77. notionary/page/content/parser/context.py +49 -0
  78. notionary/page/content/parser/factory.py +219 -0
  79. notionary/page/content/parser/parsers/__init__.py +60 -0
  80. notionary/page/content/parser/parsers/audio.py +40 -0
  81. notionary/page/content/parser/parsers/base.py +30 -0
  82. notionary/page/content/parser/parsers/bookmark.py +33 -0
  83. notionary/page/content/parser/parsers/breadcrumb.py +33 -0
  84. notionary/page/content/parser/parsers/bulleted_list.py +41 -0
  85. notionary/page/content/parser/parsers/callout.py +129 -0
  86. notionary/page/content/parser/parsers/caption.py +55 -0
  87. notionary/page/content/parser/parsers/code.py +81 -0
  88. notionary/page/content/parser/parsers/column.py +117 -0
  89. notionary/page/content/parser/parsers/column_list.py +81 -0
  90. notionary/page/content/parser/parsers/divider.py +33 -0
  91. notionary/page/content/parser/parsers/embed.py +33 -0
  92. notionary/page/content/parser/parsers/equation.py +65 -0
  93. notionary/page/content/parser/parsers/file.py +42 -0
  94. notionary/page/content/parser/parsers/heading.py +58 -0
  95. notionary/page/content/parser/parsers/image.py +42 -0
  96. notionary/page/content/parser/parsers/numbered_list.py +45 -0
  97. notionary/page/content/parser/parsers/paragraph.py +36 -0
  98. notionary/page/content/parser/parsers/pdf.py +42 -0
  99. notionary/page/content/parser/parsers/quote.py +65 -0
  100. notionary/page/content/parser/parsers/space.py +35 -0
  101. notionary/page/content/parser/parsers/table.py +144 -0
  102. notionary/page/content/parser/parsers/table_of_contents.py +32 -0
  103. notionary/page/content/parser/parsers/todo.py +58 -0
  104. notionary/page/content/parser/parsers/toggle.py +127 -0
  105. notionary/page/content/parser/parsers/toggleable_heading.py +150 -0
  106. notionary/page/content/parser/parsers/video.py +42 -0
  107. notionary/page/content/parser/post_processing/handlers/__init__.py +5 -0
  108. notionary/page/content/parser/post_processing/handlers/rich_text_length.py +93 -0
  109. notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +93 -0
  110. notionary/page/content/parser/post_processing/port.py +9 -0
  111. notionary/page/content/parser/post_processing/service.py +16 -0
  112. notionary/page/content/parser/pre_processsing/handlers/__init__.py +9 -0
  113. notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +80 -0
  114. notionary/page/content/parser/pre_processsing/handlers/port.py +7 -0
  115. notionary/page/content/parser/pre_processsing/handlers/whitespace.py +68 -0
  116. notionary/page/content/parser/pre_processsing/service.py +15 -0
  117. notionary/page/content/parser/service.py +69 -0
  118. notionary/page/content/renderer/context.py +48 -0
  119. notionary/page/content/renderer/factory.py +240 -0
  120. notionary/page/content/renderer/post_processing/handlers/__init__.py +5 -0
  121. notionary/page/content/renderer/post_processing/handlers/numbered_list_placeholdere.py +62 -0
  122. notionary/page/content/renderer/post_processing/port.py +7 -0
  123. notionary/page/content/renderer/post_processing/service.py +15 -0
  124. notionary/page/content/renderer/renderers/__init__.py +57 -0
  125. notionary/page/content/renderer/renderers/audio.py +31 -0
  126. notionary/page/content/renderer/renderers/base.py +31 -0
  127. notionary/page/content/renderer/renderers/bookmark.py +25 -0
  128. notionary/page/content/renderer/renderers/breadcrumb.py +21 -0
  129. notionary/page/content/renderer/renderers/bulleted_list.py +48 -0
  130. notionary/page/content/renderer/renderers/callout.py +65 -0
  131. notionary/page/content/renderer/renderers/captioned_block.py +58 -0
  132. notionary/page/content/renderer/renderers/code.py +34 -0
  133. notionary/page/content/renderer/renderers/column.py +44 -0
  134. notionary/page/content/renderer/renderers/column_list.py +31 -0
  135. notionary/page/content/renderer/renderers/divider.py +22 -0
  136. notionary/page/content/renderer/renderers/embed.py +25 -0
  137. notionary/page/content/renderer/renderers/equation.py +37 -0
  138. notionary/page/content/renderer/renderers/fallback.py +24 -0
  139. notionary/page/content/renderer/renderers/file.py +40 -0
  140. notionary/page/content/renderer/renderers/heading.py +69 -0
  141. notionary/page/content/renderer/renderers/image.py +31 -0
  142. notionary/page/content/renderer/renderers/numbered_list.py +41 -0
  143. notionary/page/content/renderer/renderers/paragraph.py +40 -0
  144. notionary/page/content/renderer/renderers/pdf.py +31 -0
  145. notionary/page/content/renderer/renderers/quote.py +49 -0
  146. notionary/page/content/renderer/renderers/table.py +115 -0
  147. notionary/page/content/renderer/renderers/table_of_contents.py +26 -0
  148. notionary/page/content/renderer/renderers/table_row.py +17 -0
  149. notionary/page/content/renderer/renderers/todo.py +56 -0
  150. notionary/page/content/renderer/renderers/toggle.py +53 -0
  151. notionary/page/content/renderer/renderers/toggleable_heading.py +78 -0
  152. notionary/page/content/renderer/renderers/video.py +31 -0
  153. notionary/page/content/renderer/service.py +50 -0
  154. notionary/page/content/service.py +65 -0
  155. notionary/page/content/syntax/models.py +68 -0
  156. notionary/page/content/syntax/service.py +453 -0
  157. notionary/page/page_context.py +7 -16
  158. notionary/page/page_http_client.py +15 -0
  159. notionary/page/page_metadata_update_client.py +19 -0
  160. notionary/page/properties/client.py +144 -0
  161. notionary/page/properties/factory.py +26 -0
  162. notionary/page/properties/models.py +307 -0
  163. notionary/page/properties/service.py +257 -0
  164. notionary/page/schemas.py +13 -0
  165. notionary/page/service.py +222 -0
  166. notionary/shared/entity/client.py +29 -0
  167. notionary/shared/entity/dto_parsers.py +53 -0
  168. notionary/shared/entity/entity_metadata_update_client.py +41 -0
  169. notionary/shared/entity/schemas.py +45 -0
  170. notionary/shared/entity/service.py +171 -0
  171. notionary/shared/models/cover.py +20 -0
  172. notionary/shared/models/file.py +21 -0
  173. notionary/shared/models/icon.py +28 -0
  174. notionary/shared/models/parent.py +41 -0
  175. notionary/shared/properties/type.py +30 -0
  176. notionary/user/__init__.py +4 -8
  177. notionary/user/base.py +89 -0
  178. notionary/user/bot.py +70 -0
  179. notionary/user/client.py +22 -111
  180. notionary/user/person.py +41 -0
  181. notionary/user/schemas.py +67 -0
  182. notionary/user/service.py +65 -0
  183. notionary/utils/async_retry.py +39 -0
  184. notionary/utils/date.py +51 -0
  185. notionary/utils/fuzzy.py +56 -0
  186. notionary/{util/logging_mixin.py → utils/mixins/logging.py} +4 -16
  187. notionary/utils/pagination.py +50 -0
  188. notionary/utils/singleton.py +13 -0
  189. notionary/utils/uuid_utils.py +20 -0
  190. notionary/workspace/__init__.py +3 -0
  191. notionary/workspace/client.py +62 -0
  192. notionary/workspace/query/builder.py +60 -0
  193. notionary/workspace/query/models.py +60 -0
  194. notionary/workspace/query/service.py +93 -0
  195. notionary/workspace/schemas.py +21 -0
  196. notionary/workspace/service.py +116 -0
  197. {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/METADATA +54 -49
  198. notionary-0.2.28.dist-info/RECORD +200 -0
  199. {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/WHEEL +1 -1
  200. {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info/licenses}/LICENSE +9 -9
  201. notionary/base_notion_client.py +0 -219
  202. notionary/blocks/__init__.py +0 -5
  203. notionary/blocks/_bootstrap.py +0 -271
  204. notionary/blocks/audio/__init__.py +0 -11
  205. notionary/blocks/audio/audio_element.py +0 -158
  206. notionary/blocks/audio/audio_markdown_node.py +0 -24
  207. notionary/blocks/audio/audio_models.py +0 -10
  208. notionary/blocks/base_block_element.py +0 -42
  209. notionary/blocks/bookmark/__init__.py +0 -12
  210. notionary/blocks/bookmark/bookmark_element.py +0 -83
  211. notionary/blocks/bookmark/bookmark_markdown_node.py +0 -28
  212. notionary/blocks/bookmark/bookmark_models.py +0 -15
  213. notionary/blocks/breadcrumbs/__init__.py +0 -15
  214. notionary/blocks/breadcrumbs/breadcrumb_element.py +0 -39
  215. notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +0 -13
  216. notionary/blocks/breadcrumbs/breadcrumb_models.py +0 -12
  217. notionary/blocks/bulleted_list/__init__.py +0 -15
  218. notionary/blocks/bulleted_list/bulleted_list_element.py +0 -74
  219. notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +0 -20
  220. notionary/blocks/bulleted_list/bulleted_list_models.py +0 -17
  221. notionary/blocks/callout/__init__.py +0 -12
  222. notionary/blocks/callout/callout_element.py +0 -99
  223. notionary/blocks/callout/callout_markdown_node.py +0 -19
  224. notionary/blocks/callout/callout_models.py +0 -33
  225. notionary/blocks/child_database/__init__.py +0 -14
  226. notionary/blocks/child_database/child_database_element.py +0 -59
  227. notionary/blocks/child_database/child_database_models.py +0 -12
  228. notionary/blocks/child_page/__init__.py +0 -9
  229. notionary/blocks/child_page/child_page_element.py +0 -94
  230. notionary/blocks/child_page/child_page_models.py +0 -12
  231. notionary/blocks/code/__init__.py +0 -11
  232. notionary/blocks/code/code_element.py +0 -149
  233. notionary/blocks/code/code_markdown_node.py +0 -80
  234. notionary/blocks/code/code_models.py +0 -94
  235. notionary/blocks/column/__init__.py +0 -25
  236. notionary/blocks/column/column_element.py +0 -65
  237. notionary/blocks/column/column_list_element.py +0 -52
  238. notionary/blocks/column/column_list_markdown_node.py +0 -34
  239. notionary/blocks/column/column_markdown_node.py +0 -42
  240. notionary/blocks/column/column_models.py +0 -26
  241. notionary/blocks/divider/__init__.py +0 -12
  242. notionary/blocks/divider/divider_element.py +0 -41
  243. notionary/blocks/divider/divider_markdown_node.py +0 -11
  244. notionary/blocks/divider/divider_models.py +0 -12
  245. notionary/blocks/embed/__init__.py +0 -12
  246. notionary/blocks/embed/embed_element.py +0 -98
  247. notionary/blocks/embed/embed_markdown_node.py +0 -19
  248. notionary/blocks/embed/embed_models.py +0 -14
  249. notionary/blocks/equation/__init__.py +0 -13
  250. notionary/blocks/equation/equation_element.py +0 -133
  251. notionary/blocks/equation/equation_element_markdown_node.py +0 -23
  252. notionary/blocks/equation/equation_models.py +0 -11
  253. notionary/blocks/file/__init__.py +0 -23
  254. notionary/blocks/file/file_element.py +0 -133
  255. notionary/blocks/file/file_element_markdown_node.py +0 -24
  256. notionary/blocks/file/file_element_models.py +0 -39
  257. notionary/blocks/heading/__init__.py +0 -19
  258. notionary/blocks/heading/heading_element.py +0 -112
  259. notionary/blocks/heading/heading_markdown_node.py +0 -16
  260. notionary/blocks/heading/heading_models.py +0 -29
  261. notionary/blocks/image_block/__init__.py +0 -11
  262. notionary/blocks/image_block/image_element.py +0 -130
  263. notionary/blocks/image_block/image_markdown_node.py +0 -25
  264. notionary/blocks/image_block/image_models.py +0 -10
  265. notionary/blocks/markdown/markdown_builder.py +0 -525
  266. notionary/blocks/markdown/markdown_document_model.py +0 -0
  267. notionary/blocks/markdown/markdown_node.py +0 -25
  268. notionary/blocks/mixins/captions/__init__.py +0 -4
  269. notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +0 -31
  270. notionary/blocks/mixins/captions/caption_mixin.py +0 -92
  271. notionary/blocks/mixins/file_upload/__init__.py +0 -3
  272. notionary/blocks/mixins/file_upload/file_upload_mixin.py +0 -320
  273. notionary/blocks/models.py +0 -174
  274. notionary/blocks/numbered_list/__init__.py +0 -16
  275. notionary/blocks/numbered_list/numbered_list_element.py +0 -65
  276. notionary/blocks/numbered_list/numbered_list_markdown_node.py +0 -17
  277. notionary/blocks/numbered_list/numbered_list_models.py +0 -17
  278. notionary/blocks/paragraph/__init__.py +0 -15
  279. notionary/blocks/paragraph/paragraph_element.py +0 -58
  280. notionary/blocks/paragraph/paragraph_markdown_node.py +0 -16
  281. notionary/blocks/paragraph/paragraph_models.py +0 -16
  282. notionary/blocks/pdf/__init__.py +0 -11
  283. notionary/blocks/pdf/pdf_element.py +0 -146
  284. notionary/blocks/pdf/pdf_markdown_node.py +0 -24
  285. notionary/blocks/pdf/pdf_models.py +0 -11
  286. notionary/blocks/quote/__init__.py +0 -14
  287. notionary/blocks/quote/quote_element.py +0 -75
  288. notionary/blocks/quote/quote_markdown_node.py +0 -16
  289. notionary/blocks/quote/quote_models.py +0 -18
  290. notionary/blocks/registry/__init__.py +0 -3
  291. notionary/blocks/registry/block_registry.py +0 -150
  292. notionary/blocks/rich_text/__init__.py +0 -33
  293. notionary/blocks/rich_text/rich_text_models.py +0 -221
  294. notionary/blocks/rich_text/text_inline_formatter.py +0 -456
  295. notionary/blocks/syntax_prompt_builder.py +0 -137
  296. notionary/blocks/table/__init__.py +0 -19
  297. notionary/blocks/table/table_element.py +0 -225
  298. notionary/blocks/table/table_markdown_node.py +0 -42
  299. notionary/blocks/table/table_models.py +0 -28
  300. notionary/blocks/table_of_contents/__init__.py +0 -17
  301. notionary/blocks/table_of_contents/table_of_contents_element.py +0 -80
  302. notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +0 -21
  303. notionary/blocks/table_of_contents/table_of_contents_models.py +0 -18
  304. notionary/blocks/todo/__init__.py +0 -12
  305. notionary/blocks/todo/todo_element.py +0 -81
  306. notionary/blocks/todo/todo_markdown_node.py +0 -21
  307. notionary/blocks/todo/todo_models.py +0 -18
  308. notionary/blocks/toggle/__init__.py +0 -12
  309. notionary/blocks/toggle/toggle_element.py +0 -112
  310. notionary/blocks/toggle/toggle_markdown_node.py +0 -31
  311. notionary/blocks/toggle/toggle_models.py +0 -17
  312. notionary/blocks/toggleable_heading/__init__.py +0 -11
  313. notionary/blocks/toggleable_heading/toggleable_heading_element.py +0 -115
  314. notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +0 -34
  315. notionary/blocks/types.py +0 -130
  316. notionary/blocks/video/__init__.py +0 -11
  317. notionary/blocks/video/video_element.py +0 -187
  318. notionary/blocks/video/video_element_models.py +0 -10
  319. notionary/blocks/video/video_markdown_node.py +0 -26
  320. notionary/comments/__init__.py +0 -26
  321. notionary/database/__init__.py +0 -4
  322. notionary/database/database.py +0 -480
  323. notionary/database/database_filter_builder.py +0 -173
  324. notionary/database/database_provider.py +0 -227
  325. notionary/database/exceptions.py +0 -13
  326. notionary/database/factory.py +0 -0
  327. notionary/database/models.py +0 -337
  328. notionary/database/notion_database.py +0 -487
  329. notionary/file_upload/__init__.py +0 -7
  330. notionary/page/client.py +0 -124
  331. notionary/page/markdown_whitespace_processor.py +0 -129
  332. notionary/page/models.py +0 -322
  333. notionary/page/notion_page.py +0 -674
  334. notionary/page/page_content_deleting_service.py +0 -117
  335. notionary/page/page_content_writer.py +0 -80
  336. notionary/page/property_formatter.py +0 -99
  337. notionary/page/reader/handler/__init__.py +0 -19
  338. notionary/page/reader/handler/base_block_renderer.py +0 -44
  339. notionary/page/reader/handler/block_processing_context.py +0 -35
  340. notionary/page/reader/handler/block_rendering_context.py +0 -48
  341. notionary/page/reader/handler/column_list_renderer.py +0 -51
  342. notionary/page/reader/handler/column_renderer.py +0 -60
  343. notionary/page/reader/handler/equation_renderer.py +0 -0
  344. notionary/page/reader/handler/line_renderer.py +0 -73
  345. notionary/page/reader/handler/numbered_list_renderer.py +0 -85
  346. notionary/page/reader/handler/toggle_renderer.py +0 -69
  347. notionary/page/reader/handler/toggleable_heading_renderer.py +0 -89
  348. notionary/page/reader/page_content_retriever.py +0 -81
  349. notionary/page/search_filter_builder.py +0 -132
  350. notionary/page/utils.py +0 -60
  351. notionary/page/writer/handler/__init__.py +0 -24
  352. notionary/page/writer/handler/code_handler.py +0 -72
  353. notionary/page/writer/handler/column_handler.py +0 -141
  354. notionary/page/writer/handler/column_list_handler.py +0 -139
  355. notionary/page/writer/handler/equation_handler.py +0 -74
  356. notionary/page/writer/handler/line_handler.py +0 -35
  357. notionary/page/writer/handler/line_processing_context.py +0 -54
  358. notionary/page/writer/handler/regular_line_handler.py +0 -86
  359. notionary/page/writer/handler/table_handler.py +0 -66
  360. notionary/page/writer/handler/toggle_handler.py +0 -159
  361. notionary/page/writer/handler/toggleable_heading_handler.py +0 -174
  362. notionary/page/writer/markdown_to_notion_converter.py +0 -139
  363. notionary/page/writer/markdown_to_notion_converter_context.py +0 -30
  364. notionary/page/writer/markdown_to_notion_text_length_post_processor.py +0 -0
  365. notionary/page/writer/notion_text_length_processor.py +0 -150
  366. notionary/schemas/__init__.py +0 -3
  367. notionary/schemas/base.py +0 -73
  368. notionary/shared/__init__.py +0 -3
  369. notionary/shared/name_to_id_resolver.py +0 -203
  370. notionary/telemetry/__init__.py +0 -19
  371. notionary/telemetry/service.py +0 -136
  372. notionary/telemetry/views.py +0 -73
  373. notionary/user/base_notion_user.py +0 -53
  374. notionary/user/models.py +0 -84
  375. notionary/user/notion_bot_user.py +0 -226
  376. notionary/user/notion_user.py +0 -255
  377. notionary/user/notion_user_manager.py +0 -101
  378. notionary/util/__init__.py +0 -15
  379. notionary/util/concurrency_limiter.py +0 -0
  380. notionary/util/factory_decorator.py +0 -0
  381. notionary/util/factory_only.py +0 -37
  382. notionary/util/fuzzy.py +0 -75
  383. notionary/util/page_id_utils.py +0 -27
  384. notionary/util/singleton.py +0 -18
  385. notionary/util/singleton_metaclass.py +0 -22
  386. notionary/workspace.py +0 -105
  387. notionary-0.2.26.dist-info/RECORD +0 -202
@@ -1,117 +0,0 @@
1
- from typing import Optional
2
-
3
- from notionary.blocks.client import NotionBlockClient
4
- from notionary.blocks.models import Block
5
- from notionary.blocks.registry.block_registry import BlockRegistry
6
- from notionary.page.reader.page_content_retriever import PageContentRetriever
7
- from notionary.util import LoggingMixin
8
-
9
-
10
- class PageContentDeletingService(LoggingMixin):
11
- """Service responsible for deleting page content and blocks."""
12
-
13
- def __init__(self, page_id: str, block_registry: BlockRegistry):
14
- self.page_id = page_id
15
- self.block_registry = block_registry
16
- self._block_client = NotionBlockClient()
17
- self._content_retriever = PageContentRetriever(block_registry=block_registry)
18
-
19
- async def clear_page_content(self) -> Optional[str]:
20
- """Clear all content of the page and return deleted content as markdown."""
21
- try:
22
- children_response = await self._block_client.get_block_children(
23
- block_id=self.page_id
24
- )
25
-
26
- if not children_response or not children_response.results:
27
- return None
28
-
29
- # Use PageContentRetriever for sophisticated markdown conversion
30
- deleted_content = await self._content_retriever._convert_blocks_to_markdown(
31
- children_response.results, indent_level=0
32
- )
33
-
34
- # Delete blocks
35
- success = True
36
- for block in children_response.results:
37
- block_success = await self._delete_block_with_children(block)
38
- if not block_success:
39
- success = False
40
-
41
- if not success:
42
- self.logger.warning("Some blocks could not be deleted")
43
-
44
- return deleted_content if deleted_content else None
45
-
46
- except Exception:
47
- self.logger.error("Error clearing page content", exc_info=True)
48
- return None
49
-
50
- async def _delete_block_with_children(self, block: Block) -> bool:
51
- """Delete a block and all its children recursively."""
52
- if not block.id:
53
- self.logger.error("Block has no valid ID")
54
- return False
55
-
56
- self.logger.debug("Deleting block: %s (type: %s)", block.id, block.type)
57
-
58
- try:
59
- if block.has_children and not await self._delete_block_children(block):
60
- return False
61
-
62
- return await self._delete_single_block(block)
63
-
64
- except Exception as e:
65
- self.logger.error("Failed to delete block %s: %s", block.id, str(e))
66
- return False
67
-
68
- async def _delete_block_children(self, block: Block) -> bool:
69
- """Delete all children of a block."""
70
- self.logger.debug("Block %s has children, deleting children first", block.id)
71
-
72
- try:
73
- children_blocks = await self._block_client.get_all_block_children(block.id)
74
-
75
- if not children_blocks:
76
- self.logger.debug("No children found for block: %s", block.id)
77
- return True
78
-
79
- self.logger.debug(
80
- "Found %d children to delete for block: %s",
81
- len(children_blocks),
82
- block.id,
83
- )
84
-
85
- # Delete all children recursively
86
- for child_block in children_blocks:
87
- if not await self._delete_block_with_children(child_block):
88
- self.logger.error(
89
- "Failed to delete child block: %s", child_block.id
90
- )
91
- return False
92
-
93
- self.logger.debug(
94
- "Successfully deleted all children of block: %s", block.id
95
- )
96
- return True
97
-
98
- except Exception as e:
99
- self.logger.error(
100
- "Failed to delete children of block %s: %s", block.id, str(e)
101
- )
102
- return False
103
-
104
- async def _delete_single_block(self, block: Block) -> bool:
105
- """Delete a single block."""
106
- deleted_block: Optional[Block] = await self._block_client.delete_block(block.id)
107
-
108
- if deleted_block is None:
109
- self.logger.error("Failed to delete block: %s", block.id)
110
- return False
111
-
112
- if deleted_block.archived or deleted_block.in_trash:
113
- self.logger.debug("Successfully deleted/archived block: %s", block.id)
114
- return True
115
- else:
116
- self.logger.warning("Block %s was not properly archived/deleted", block.id)
117
- return False
@@ -1,80 +0,0 @@
1
- from typing import Callable, Optional, Union
2
-
3
- from notionary.blocks.client import NotionBlockClient
4
- from notionary.blocks.registry.block_registry import BlockRegistry
5
- from notionary.blocks.markdown.markdown_builder import MarkdownBuilder
6
- from notionary.schemas.base import NotionContentSchema
7
- from notionary.page.markdown_whitespace_processor import MarkdownWhitespaceProcessor
8
- from notionary.page.writer.markdown_to_notion_converter import MarkdownToNotionConverter
9
- from notionary.util import LoggingMixin
10
-
11
-
12
- class PageContentWriter(LoggingMixin):
13
- def __init__(self, page_id: str, block_registry: BlockRegistry):
14
- self.page_id = page_id
15
- self.block_registry = block_registry
16
- self._block_client = NotionBlockClient()
17
-
18
- self._markdown_to_notion_converter = MarkdownToNotionConverter(
19
- block_registry=block_registry
20
- )
21
-
22
- async def append_markdown(
23
- self,
24
- content: Union[
25
- str, Callable[[MarkdownBuilder], MarkdownBuilder], NotionContentSchema
26
- ],
27
- ) -> Optional[str]:
28
- """
29
- Append markdown content to a Notion page using text, builder callback, MarkdownDocumentModel, or NotionContentSchema.
30
- """
31
- markdown = self._extract_markdown_from_param(content)
32
-
33
- processed_markdown = MarkdownWhitespaceProcessor.process_markdown_whitespace(
34
- markdown
35
- )
36
-
37
- try:
38
- blocks = await self._markdown_to_notion_converter.convert(
39
- processed_markdown
40
- )
41
-
42
- result = await self._block_client.append_block_children(
43
- block_id=self.page_id, children=blocks
44
- )
45
-
46
- if result:
47
- self.logger.debug("Successfully appended %d blocks", len(blocks))
48
- return processed_markdown
49
- else:
50
- self.logger.error("Failed to append blocks")
51
- return None
52
-
53
- except Exception as e:
54
- self.logger.error("Error appending markdown: %s", str(e), exc_info=True)
55
- return None
56
-
57
- def _extract_markdown_from_param(
58
- self,
59
- content: Union[
60
- str, Callable[[MarkdownBuilder], MarkdownBuilder], NotionContentSchema
61
- ],
62
- ) -> str:
63
- """
64
- Prepare markdown content from string, builder callback, MarkdownDocumentModel, or NotionContentSchema.
65
- """
66
- if isinstance(content, str):
67
- return content
68
- elif isinstance(content, NotionContentSchema):
69
- # Use new injection-based API
70
- builder = MarkdownBuilder()
71
- return content.to_notion_content(builder)
72
-
73
- elif callable(content):
74
- builder = MarkdownBuilder()
75
- content(builder)
76
- return builder.build()
77
- else:
78
- raise ValueError(
79
- "content must be either a string, a NotionContentSchema, a MarkdownDocumentModel, or a callable that takes a MarkdownBuilder"
80
- )
@@ -1,99 +0,0 @@
1
- from typing import Any, Dict, Optional
2
-
3
- from notionary.util import LoggingMixin
4
-
5
-
6
- # TODO: mit dem Utils.py hier im order zusammenfassen
7
- class NotionPropertyFormatter(LoggingMixin):
8
- """Class for formatting Notion properties based on their type."""
9
-
10
- def __init__(self):
11
- self._formatters = {
12
- "title": self.format_title,
13
- "rich_text": self.format_rich_text,
14
- "url": self.format_url,
15
- "email": self.format_email,
16
- "phone_number": self.format_phone_number,
17
- "number": self.format_number,
18
- "checkbox": self.format_checkbox,
19
- "select": self.format_select,
20
- "multi_select": self.format_multi_select,
21
- "date": self.format_date,
22
- "status": self.format_status,
23
- "relation": self.format_relation,
24
- }
25
-
26
- def format_title(self, value: Any) -> Dict[str, Any]:
27
- """Formats a title value."""
28
- return {"title": [{"type": "text", "text": {"content": str(value)}}]}
29
-
30
- def format_rich_text(self, value: Any) -> Dict[str, Any]:
31
- """Formats a rich text value."""
32
- return {"rich_text": [{"type": "text", "text": {"content": str(value)}}]}
33
-
34
- def format_url(self, value: str) -> Dict[str, Any]:
35
- """Formats a URL value."""
36
- return {"url": value}
37
-
38
- def format_email(self, value: str) -> Dict[str, Any]:
39
- """Formats an email address."""
40
- return {"email": value}
41
-
42
- def format_phone_number(self, value: str) -> Dict[str, Any]:
43
- """Formats a phone number."""
44
- return {"phone_number": value}
45
-
46
- def format_number(self, value: Any) -> Dict[str, Any]:
47
- """Formats a numeric value."""
48
- return {"number": float(value)}
49
-
50
- def format_checkbox(self, value: Any) -> Dict[str, Any]:
51
- """Formats a checkbox value."""
52
- return {"checkbox": bool(value)}
53
-
54
- def format_select(self, value: str) -> Dict[str, Any]:
55
- """Formats a select value."""
56
- return {"select": {"name": str(value)}}
57
-
58
- def format_multi_select(self, value: Any) -> Dict[str, Any]:
59
- """Formats a multi-select value."""
60
- if isinstance(value, list):
61
- return {"multi_select": [{"name": item} for item in value]}
62
- return {"multi_select": [{"name": str(value)}]}
63
-
64
- def format_date(self, value: Any) -> Dict[str, Any]:
65
- """Formats a date value."""
66
- if isinstance(value, dict) and "start" in value:
67
- return {"date": value}
68
- return {"date": {"start": str(value)}}
69
-
70
- def format_status(self, value: str) -> Dict[str, Any]:
71
- """Formats a status value."""
72
- return {"status": {"name": str(value)}}
73
-
74
- def format_relation(self, value: Any) -> Dict[str, Any]:
75
- """Formats a relation value."""
76
- if isinstance(value, list):
77
- return {"relation": [{"id": item} for item in value]}
78
- return {"relation": [{"id": str(value)}]}
79
-
80
- def format_value(
81
- self, property_name, property_type: str, value: Any
82
- ) -> Optional[Dict[str, Any]]:
83
- """
84
- Formats a value according to the given Notion property type.
85
-
86
- Args:
87
- property_type: Notion property type (e.g., "title", "rich_text", "status")
88
- value: The value to be formatted
89
-
90
- Returns:
91
- A dictionary with the formatted value, or None if the type is unknown.
92
- """
93
- formatter = self._formatters.get(property_type)
94
- if not formatter:
95
- self.logger.warning("Unknown property type: %s", property_type)
96
- return None
97
-
98
- formatted_property = formatter(value)
99
- return {"properties": {property_name: formatted_property}}
@@ -1,19 +0,0 @@
1
- from .base_block_renderer import BlockHandler
2
- from .block_rendering_context import BlockRenderingContext
3
- from .column_list_renderer import ColumnListRenderer
4
- from .column_renderer import ColumnRenderer
5
- from .line_renderer import LineRenderer
6
- from .numbered_list_renderer import NumberedListRenderer
7
- from .toggle_renderer import ToggleRenderer
8
- from .toggleable_heading_renderer import ToggleableHeadingRenderer
9
-
10
- __all__ = [
11
- "BlockHandler",
12
- "BlockRenderingContext",
13
- "ColumnListRenderer",
14
- "ColumnRenderer",
15
- "LineRenderer",
16
- "NumberedListRenderer",
17
- "ToggleRenderer",
18
- "ToggleableHeadingRenderer",
19
- ]
@@ -1,44 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from abc import ABC, abstractmethod
4
- from typing import Optional
5
-
6
- from notionary.page.reader.handler.block_rendering_context import BlockRenderingContext
7
-
8
-
9
- class BlockHandler(ABC):
10
- """Abstract base class for block handlers."""
11
-
12
- def __init__(self):
13
- self._next_handler: Optional[BlockHandler] = None
14
-
15
- def set_next(self, handler: BlockHandler) -> BlockHandler:
16
- """Set the next handler in the chain."""
17
- self._next_handler = handler
18
- return handler
19
-
20
- async def handle(self, context: BlockRenderingContext) -> None:
21
- """Handle the block or pass to next handler."""
22
- if self._can_handle(context):
23
- await self._process(context)
24
- elif self._next_handler:
25
- await self._next_handler.handle(context)
26
-
27
- @abstractmethod
28
- def _can_handle(self, context: BlockRenderingContext) -> bool:
29
- """Check if this handler can process the current block."""
30
- pass
31
-
32
- @abstractmethod
33
- async def _process(self, context: BlockRenderingContext) -> None:
34
- """Process the block and update context."""
35
- pass
36
-
37
- def _indent_text(self, text: str, spaces: int = 4) -> str:
38
- """Indent each line of text with specified number of spaces."""
39
- if not text:
40
- return text
41
-
42
- indent = " " * spaces
43
- lines = text.split("\n")
44
- return "\n".join(f"{indent}{line}" if line.strip() else line for line in lines)
@@ -1,35 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Optional
5
-
6
- from notionary.blocks.models import Block
7
- from notionary.blocks.registry.block_registry import BlockRegistry
8
-
9
-
10
- @dataclass
11
- class BlockProcessingContext:
12
- """Context for processing blocks during markdown conversion."""
13
-
14
- block: Block
15
- indent_level: int
16
- block_registry: BlockRegistry
17
-
18
- # Result
19
- markdown_result: Optional[str] = None
20
- children_result: Optional[str] = None
21
- was_processed: bool = False
22
-
23
- def has_children(self) -> bool:
24
- """Check if block has children that need processing."""
25
- return (
26
- self.block.has_children
27
- and self.block.children is not None
28
- and len(self.block.children) > 0
29
- )
30
-
31
- def get_children_blocks(self) -> list[Block]:
32
- """Get the children blocks safely."""
33
- if self.has_children():
34
- return self.block.children
35
- return []
@@ -1,48 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Callable, Optional
5
-
6
- from notionary.blocks.models import Block
7
- from notionary.blocks.registry.block_registry import BlockRegistry
8
-
9
-
10
- @dataclass
11
- class BlockRenderingContext:
12
- """Context for processing blocks during markdown conversion."""
13
-
14
- block: Block
15
- indent_level: int
16
- block_registry: BlockRegistry
17
- convert_children_callback: Optional[Callable[[list[Block], int], str]] = None
18
-
19
- # For batch processing
20
- all_blocks: Optional[list[Block]] = None
21
- current_block_index: Optional[int] = None
22
- blocks_consumed: int = 0
23
-
24
- # Result
25
- markdown_result: Optional[str] = None
26
- children_result: Optional[str] = None
27
- was_processed: bool = False
28
-
29
- def has_children(self) -> bool:
30
- """Check if block has children that need processing."""
31
- return (
32
- self.block.has_children
33
- and self.block.children is not None
34
- and len(self.block.children) > 0
35
- )
36
-
37
- def get_children_blocks(self) -> list[Block]:
38
- """Get the children blocks safely."""
39
- if self.has_children():
40
- return self.block.children
41
- return []
42
-
43
- def convert_children_to_markdown(self, indent_level: int = 0) -> str:
44
- """Convert children blocks to markdown using the callback."""
45
- if not self.has_children() or not self.convert_children_callback:
46
- return ""
47
-
48
- return self.convert_children_callback(self.get_children_blocks(), indent_level)
@@ -1,51 +0,0 @@
1
- from notionary.blocks.column.column_list_element import ColumnListElement
2
- from notionary.page.reader.handler import BlockHandler, BlockRenderingContext
3
-
4
-
5
- class ColumnListRenderer(BlockHandler):
6
- """Handles column list blocks with their column children."""
7
-
8
- def _can_handle(self, context: BlockRenderingContext) -> bool:
9
- return ColumnListElement.match_notion(context.block)
10
-
11
- async def _process(self, context: BlockRenderingContext) -> None:
12
- # Create column list start line
13
- column_list_start = "::: columns"
14
-
15
- # Apply indentation if needed
16
- if context.indent_level > 0:
17
- column_list_start = self._indent_text(
18
- column_list_start, spaces=context.indent_level * 4
19
- )
20
-
21
- # Process children if they exist
22
- children_markdown = ""
23
- if context.has_children():
24
- # Import here to avoid circular dependency
25
- from notionary.page.reader.page_content_retriever import (
26
- PageContentRetriever,
27
- )
28
-
29
- # Create a temporary retriever to process children
30
- retriever = PageContentRetriever(context.block_registry)
31
- children_markdown = await retriever._convert_blocks_to_markdown(
32
- context.get_children_blocks(),
33
- indent_level=0, # No indentation for content inside column lists
34
- )
35
-
36
- # Create column list end line
37
- column_list_end = ":::"
38
- if context.indent_level > 0:
39
- column_list_end = self._indent_text(
40
- column_list_end, spaces=context.indent_level * 4
41
- )
42
-
43
- # Combine column list with children content
44
- if children_markdown:
45
- context.markdown_result = (
46
- f"{column_list_start}\n{children_markdown}\n{column_list_end}"
47
- )
48
- else:
49
- context.markdown_result = f"{column_list_start}\n{column_list_end}"
50
-
51
- context.was_processed = True
@@ -1,60 +0,0 @@
1
- from notionary.blocks.column.column_element import ColumnElement
2
- from notionary.page.reader.handler import BlockHandler, BlockRenderingContext
3
-
4
-
5
- class ColumnRenderer(BlockHandler):
6
- """Handles individual column blocks with their children content."""
7
-
8
- def _can_handle(self, context: BlockRenderingContext) -> bool:
9
- return ColumnElement.match_notion(context.block)
10
-
11
- async def _process(self, context: BlockRenderingContext) -> None:
12
- # Get the column start line with potential width ratio
13
- column_start = self._extract_column_start(context.block)
14
-
15
- # Apply indentation if needed
16
- if context.indent_level > 0:
17
- column_start = self._indent_text(
18
- column_start, spaces=context.indent_level * 4
19
- )
20
-
21
- # Process children if they exist
22
- children_markdown = ""
23
- if context.has_children():
24
- # Import here to avoid circular dependency
25
- from notionary.page.reader.page_content_retriever import (
26
- PageContentRetriever,
27
- )
28
-
29
- # Create a temporary retriever to process children
30
- retriever = PageContentRetriever(context.block_registry)
31
- children_markdown = await retriever._convert_blocks_to_markdown(
32
- context.get_children_blocks(),
33
- indent_level=0, # No indentation for content inside columns
34
- )
35
-
36
- # Create column end line
37
- column_end = ":::"
38
- if context.indent_level > 0:
39
- column_end = self._indent_text(column_end, spaces=context.indent_level * 4)
40
-
41
- # Combine column with children content
42
- if children_markdown:
43
- context.markdown_result = (
44
- f"{column_start}\n{children_markdown}\n{column_end}"
45
- )
46
- else:
47
- context.markdown_result = f"{column_start}\n{column_end}"
48
-
49
- context.was_processed = True
50
-
51
- def _extract_column_start(self, block) -> str:
52
- """Extract column start line with potential width ratio."""
53
- if not block.column:
54
- return "::: column"
55
-
56
- width_ratio = block.column.width_ratio
57
- if width_ratio:
58
- return f"::: column {width_ratio}"
59
- else:
60
- return "::: column"
File without changes
@@ -1,73 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Optional
4
-
5
- from notionary.page.reader.handler import BlockHandler, BlockRenderingContext
6
-
7
-
8
- class LineRenderer(BlockHandler):
9
- """Handles all regular blocks that don't need special parent/children processing."""
10
-
11
- def _can_handle(self, context: BlockRenderingContext) -> bool:
12
- # Always can handle - this is the fallback handler
13
- return True
14
-
15
- async def _process(self, context: BlockRenderingContext) -> None:
16
- # Convert the block itself using direct element iteration
17
- block_markdown = await self._convert_block_to_markdown(context)
18
-
19
- # If block has no direct markdown, either return empty or process children
20
- if not block_markdown:
21
- if not context.has_children():
22
- context.markdown_result = ""
23
- context.was_processed = True
24
- return
25
-
26
- # Import here to avoid circular dependency and process children
27
- from notionary.page.reader.page_content_retriever import (
28
- PageContentRetriever,
29
- )
30
-
31
- retriever = PageContentRetriever(context.block_registry)
32
- children_markdown = await retriever._convert_blocks_to_markdown(
33
- context.get_children_blocks(), indent_level=context.indent_level + 1
34
- )
35
- context.markdown_result = children_markdown
36
- context.was_processed = True
37
- return
38
-
39
- # Apply indentation if needed
40
- if context.indent_level > 0:
41
- block_markdown = self._indent_text(
42
- block_markdown, spaces=context.indent_level * 4
43
- )
44
-
45
- # If there are no children, return the block markdown directly
46
- if not context.has_children():
47
- context.markdown_result = block_markdown
48
- context.was_processed = True
49
- return
50
-
51
- # Otherwise process children and combine
52
- from notionary.page.reader.page_content_retriever import PageContentRetriever
53
-
54
- retriever = PageContentRetriever(context.block_registry)
55
- children_markdown = await retriever._convert_blocks_to_markdown(
56
- context.get_children_blocks(), indent_level=context.indent_level + 1
57
- )
58
-
59
- context.markdown_result = (
60
- f"{block_markdown}\n{children_markdown}"
61
- if children_markdown
62
- else block_markdown
63
- )
64
- context.was_processed = True
65
-
66
- async def _convert_block_to_markdown(
67
- self, context: BlockRenderingContext
68
- ) -> Optional[str]:
69
- """Convert a Notion block to markdown using registered elements."""
70
- for element in context.block_registry.get_elements():
71
- if element.match_notion(context.block):
72
- return await element.notion_to_markdown(context.block)
73
- return None