notionary 0.2.27__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.27.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.27.dist-info → notionary-0.2.28.dist-info}/WHEEL +1 -1
  200. {notionary-0.2.27.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 -712
  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.27.dist-info/RECORD +0 -202
@@ -0,0 +1,81 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.enums import BlockType
4
+ from notionary.blocks.schemas import BlockCreatePayload, CreateColumnListBlock, CreateColumnListData
5
+ from notionary.page.content.parser.context import ParentBlockContext
6
+ from notionary.page.content.parser.parsers.base import (
7
+ BlockParsingContext,
8
+ LineParser,
9
+ )
10
+ from notionary.page.content.syntax.service import SyntaxRegistry
11
+
12
+
13
+ class ColumnListParser(LineParser):
14
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
15
+ super().__init__(syntax_registry)
16
+ self._syntax = syntax_registry.get_column_list_syntax()
17
+
18
+ @override
19
+ def _can_handle(self, context: BlockParsingContext) -> bool:
20
+ return self._is_column_list_start(context) or self._is_column_list_end(context)
21
+
22
+ @override
23
+ async def _process(self, context: BlockParsingContext) -> None:
24
+ if self._is_column_list_start(context):
25
+ await self._start_column_list(context)
26
+ elif self._is_column_list_end(context):
27
+ await self._finalize_column_list(context)
28
+
29
+ def _is_column_list_start(self, context: BlockParsingContext) -> bool:
30
+ return self._syntax.regex_pattern.match(context.line) is not None
31
+
32
+ def _is_column_list_end(self, context: BlockParsingContext) -> bool:
33
+ if not self._syntax.end_regex_pattern.match(context.line):
34
+ return False
35
+
36
+ if not context.parent_stack:
37
+ return False
38
+
39
+ current_parent = context.parent_stack[-1]
40
+ return isinstance(current_parent.block, CreateColumnListBlock)
41
+
42
+ async def _start_column_list(self, context: BlockParsingContext) -> None:
43
+ column_list_data = CreateColumnListData()
44
+ block = CreateColumnListBlock(column_list=column_list_data)
45
+
46
+ parent_context = ParentBlockContext(
47
+ block=block,
48
+ child_lines=[],
49
+ )
50
+ context.parent_stack.append(parent_context)
51
+
52
+ async def _finalize_column_list(self, context: BlockParsingContext) -> None:
53
+ column_list_context = context.parent_stack.pop()
54
+ await self._assign_column_list_children(column_list_context, context)
55
+
56
+ if context.parent_stack:
57
+ parent_context = context.parent_stack[-1]
58
+ parent_context.add_child_block(column_list_context.block)
59
+ else:
60
+ context.result_blocks.append(column_list_context.block)
61
+
62
+ async def _assign_column_list_children(
63
+ self, column_list_context: ParentBlockContext, context: BlockParsingContext
64
+ ) -> None:
65
+ all_children = []
66
+
67
+ if column_list_context.child_lines:
68
+ children_text = "\n".join(column_list_context.child_lines)
69
+ text_blocks = await context.parse_nested_content(children_text)
70
+ all_children.extend(text_blocks)
71
+
72
+ if column_list_context.child_blocks:
73
+ all_children.extend(column_list_context.child_blocks)
74
+
75
+ column_children = self._filter_column_blocks(all_children)
76
+ column_list_context.block.column_list.children = column_children
77
+
78
+ def _filter_column_blocks(self, blocks: list[BlockCreatePayload]) -> list:
79
+ return [
80
+ block for block in blocks if block.type == BlockType.COLUMN and hasattr(block, "column") and block.column
81
+ ]
@@ -0,0 +1,33 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.schemas import CreateDividerBlock, DividerData
4
+ from notionary.page.content.parser.parsers.base import (
5
+ BlockParsingContext,
6
+ LineParser,
7
+ )
8
+ from notionary.page.content.syntax.service import SyntaxRegistry
9
+
10
+
11
+ class DividerParser(LineParser):
12
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
13
+ super().__init__(syntax_registry)
14
+ self._syntax = syntax_registry.get_divider_syntax()
15
+
16
+ @override
17
+ def _can_handle(self, context: BlockParsingContext) -> bool:
18
+ if context.is_inside_parent_context():
19
+ return False
20
+ return self._is_divider(context.line)
21
+
22
+ @override
23
+ async def _process(self, context: BlockParsingContext) -> None:
24
+ block = self._create_divider_block()
25
+ if block:
26
+ context.result_blocks.append(block)
27
+
28
+ def _is_divider(self, line: str) -> bool:
29
+ return self._syntax.regex_pattern.match(line) is not None
30
+
31
+ def _create_divider_block(self) -> CreateDividerBlock:
32
+ divider_data = DividerData()
33
+ return CreateDividerBlock(divider=divider_data)
@@ -0,0 +1,33 @@
1
+ """Parser for embed blocks."""
2
+
3
+ from typing import override
4
+
5
+ from notionary.blocks.schemas import CreateEmbedBlock, EmbedData
6
+ from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
7
+ from notionary.page.content.syntax.service import SyntaxRegistry
8
+
9
+
10
+ class EmbedParser(LineParser):
11
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
12
+ super().__init__(syntax_registry)
13
+ self._syntax = syntax_registry.get_embed_syntax()
14
+
15
+ @override
16
+ def _can_handle(self, context: BlockParsingContext) -> bool:
17
+ if context.is_inside_parent_context():
18
+ return False
19
+ return self._syntax.regex_pattern.search(context.line) is not None
20
+
21
+ @override
22
+ async def _process(self, context: BlockParsingContext) -> None:
23
+ url = self._extract_url(context.line)
24
+ if not url:
25
+ return
26
+
27
+ embed_data = EmbedData(url=url, caption=[])
28
+ block = CreateEmbedBlock(embed=embed_data)
29
+ context.result_blocks.append(block)
30
+
31
+ def _extract_url(self, line: str) -> str | None:
32
+ match = self._syntax.regex_pattern.search(line)
33
+ return match.group(1) if match else None
@@ -0,0 +1,65 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.schemas import CreateEquationBlock, EquationData
4
+ from notionary.page.content.parser.parsers.base import (
5
+ BlockParsingContext,
6
+ LineParser,
7
+ )
8
+ from notionary.page.content.syntax.service import SyntaxRegistry
9
+
10
+
11
+ class EquationParser(LineParser):
12
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
13
+ super().__init__(syntax_registry)
14
+ self._syntax = syntax_registry.get_equation_syntax()
15
+
16
+ @override
17
+ def _can_handle(self, context: BlockParsingContext) -> bool:
18
+ if context.is_inside_parent_context():
19
+ return False
20
+ return self._is_equation_delimiter(context.line)
21
+
22
+ @override
23
+ async def _process(self, context: BlockParsingContext) -> None:
24
+ equation_content = self._collect_equation_content(context)
25
+ lines_consumed = self._count_lines_consumed(context)
26
+
27
+ block = self._create_equation_block(opening_line=context.line, equation_lines=equation_content)
28
+
29
+ if block:
30
+ context.lines_consumed = lines_consumed
31
+ context.result_blocks.append(block)
32
+
33
+ def _is_equation_delimiter(self, line: str) -> bool:
34
+ return self._syntax.regex_pattern.match(line) is not None
35
+
36
+ def _collect_equation_content(self, context: BlockParsingContext) -> list[str]:
37
+ content_lines = []
38
+
39
+ for line in context.get_remaining_lines():
40
+ if self._is_equation_delimiter(line):
41
+ break
42
+ content_lines.append(line)
43
+
44
+ return content_lines
45
+
46
+ def _count_lines_consumed(self, context: BlockParsingContext) -> int:
47
+ for line_index, line in enumerate(context.get_remaining_lines()):
48
+ if self._is_equation_delimiter(line):
49
+ return line_index + 1
50
+
51
+ return len(context.get_remaining_lines())
52
+
53
+ def _create_equation_block(self, opening_line: str, equation_lines: list[str]) -> CreateEquationBlock | None:
54
+ if opening_line.strip() != self._syntax.start_delimiter:
55
+ return None
56
+
57
+ if not equation_lines:
58
+ return None
59
+
60
+ expression = "\n".join(equation_lines).strip()
61
+
62
+ if expression:
63
+ return CreateEquationBlock(equation=EquationData(expression=expression))
64
+
65
+ return None
@@ -0,0 +1,42 @@
1
+ """Parser for file blocks."""
2
+
3
+ from typing import override
4
+
5
+ from notionary.blocks.schemas import (
6
+ CreateFileBlock,
7
+ ExternalFile,
8
+ FileData,
9
+ FileType,
10
+ )
11
+ from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
12
+ from notionary.page.content.syntax.service import SyntaxRegistry
13
+
14
+
15
+ class FileParser(LineParser):
16
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
17
+ super().__init__(syntax_registry)
18
+ self._syntax = syntax_registry.get_file_syntax()
19
+
20
+ @override
21
+ def _can_handle(self, context: BlockParsingContext) -> bool:
22
+ if context.is_inside_parent_context():
23
+ return False
24
+ return self._syntax.regex_pattern.search(context.line) is not None
25
+
26
+ @override
27
+ async def _process(self, context: BlockParsingContext) -> None:
28
+ url = self._extract_url(context.line)
29
+ if not url:
30
+ return
31
+
32
+ file_data = FileData(
33
+ type=FileType.EXTERNAL,
34
+ external=ExternalFile(url=url),
35
+ caption=[],
36
+ )
37
+ block = CreateFileBlock(file=file_data)
38
+ context.result_blocks.append(block)
39
+
40
+ def _extract_url(self, line: str) -> str | None:
41
+ match = self._syntax.regex_pattern.search(line)
42
+ return match.group(1).strip() if match else None
@@ -0,0 +1,58 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.rich_text.markdown_rich_text_converter import MarkdownRichTextConverter
4
+ from notionary.blocks.schemas import (
5
+ BlockColor,
6
+ CreateHeading1Block,
7
+ CreateHeading2Block,
8
+ CreateHeading3Block,
9
+ CreateHeadingBlock,
10
+ CreateHeadingData,
11
+ )
12
+ from notionary.page.content.parser.parsers.base import (
13
+ BlockParsingContext,
14
+ LineParser,
15
+ )
16
+ from notionary.page.content.syntax.service import SyntaxRegistry
17
+
18
+
19
+ class HeadingParser(LineParser):
20
+ def __init__(self, syntax_registry: SyntaxRegistry, rich_text_converter: MarkdownRichTextConverter) -> None:
21
+ super().__init__(syntax_registry)
22
+ self._syntax = syntax_registry.get_heading_syntax()
23
+ self._rich_text_converter = rich_text_converter
24
+
25
+ @override
26
+ def _can_handle(self, context: BlockParsingContext) -> bool:
27
+ if context.is_inside_parent_context():
28
+ return False
29
+ return self._syntax.regex_pattern.match(context.line) is not None
30
+
31
+ @override
32
+ async def _process(self, context: BlockParsingContext) -> None:
33
+ block = await self._create_heading_block(context.line)
34
+ if block:
35
+ context.result_blocks.append(block)
36
+
37
+ async def _create_heading_block(self, line: str) -> CreateHeadingBlock | None:
38
+ match = self._syntax.regex_pattern.match(line)
39
+ if not match:
40
+ return None
41
+
42
+ level = len(match.group(1))
43
+ if level < 1 or level > 3:
44
+ return None
45
+
46
+ content = match.group(2).strip()
47
+ if not content:
48
+ return None
49
+
50
+ rich_text = await self._rich_text_converter.to_rich_text(content)
51
+ heading_data = CreateHeadingData(rich_text=rich_text, color=BlockColor.DEFAULT, is_toggleable=False)
52
+
53
+ if level == 1:
54
+ return CreateHeading1Block(heading_1=heading_data)
55
+ elif level == 2:
56
+ return CreateHeading2Block(heading_2=heading_data)
57
+ else:
58
+ return CreateHeading3Block(heading_3=heading_data)
@@ -0,0 +1,42 @@
1
+ """Parser for image blocks."""
2
+
3
+ from typing import override
4
+
5
+ from notionary.blocks.schemas import (
6
+ CreateImageBlock,
7
+ ExternalFile,
8
+ FileData,
9
+ FileType,
10
+ )
11
+ from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
12
+ from notionary.page.content.syntax.service import SyntaxRegistry
13
+
14
+
15
+ class ImageParser(LineParser):
16
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
17
+ super().__init__(syntax_registry)
18
+ self._syntax = syntax_registry.get_image_syntax()
19
+
20
+ @override
21
+ def _can_handle(self, context: BlockParsingContext) -> bool:
22
+ if context.is_inside_parent_context():
23
+ return False
24
+ return self._syntax.regex_pattern.search(context.line) is not None
25
+
26
+ @override
27
+ async def _process(self, context: BlockParsingContext) -> None:
28
+ url = self._extract_url(context.line)
29
+ if not url:
30
+ return
31
+
32
+ image_data = FileData(
33
+ type=FileType.EXTERNAL,
34
+ external=ExternalFile(url=url),
35
+ caption=[],
36
+ )
37
+ block = CreateImageBlock(image=image_data)
38
+ context.result_blocks.append(block)
39
+
40
+ def _extract_url(self, line: str) -> str | None:
41
+ match = self._syntax.regex_pattern.search(line)
42
+ return match.group(1).strip() if match else None
@@ -0,0 +1,45 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.rich_text.markdown_rich_text_converter import (
4
+ MarkdownRichTextConverter,
5
+ )
6
+ from notionary.blocks.schemas import (
7
+ BlockColor,
8
+ CreateNumberedListItemBlock,
9
+ NumberedListItemData,
10
+ )
11
+ from notionary.page.content.parser.parsers.base import (
12
+ BlockParsingContext,
13
+ LineParser,
14
+ )
15
+ from notionary.page.content.syntax.service import SyntaxRegistry
16
+
17
+
18
+ class NumberedListParser(LineParser):
19
+ def __init__(self, syntax_registry: SyntaxRegistry, rich_text_converter: MarkdownRichTextConverter) -> None:
20
+ super().__init__(syntax_registry)
21
+ self._syntax = syntax_registry.get_numbered_list_syntax()
22
+ self._rich_text_converter = rich_text_converter
23
+
24
+ @override
25
+ def _can_handle(self, context: BlockParsingContext) -> bool:
26
+ if context.is_inside_parent_context():
27
+ return False
28
+ return self._syntax.regex_pattern.match(context.line) is not None
29
+
30
+ @override
31
+ async def _process(self, context: BlockParsingContext) -> None:
32
+ block = await self._create_numbered_list_block(context.line)
33
+ if block:
34
+ context.result_blocks.append(block)
35
+
36
+ async def _create_numbered_list_block(self, text: str) -> CreateNumberedListItemBlock | None:
37
+ match = self._syntax.regex_pattern.match(text)
38
+ if not match:
39
+ return None
40
+
41
+ content = match.group(3)
42
+ rich_text = await self._rich_text_converter.to_rich_text(content)
43
+
44
+ numbered_list_content = NumberedListItemData(rich_text=rich_text, color=BlockColor.DEFAULT)
45
+ return CreateNumberedListItemBlock(numbered_list_item=numbered_list_content)
@@ -0,0 +1,36 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.rich_text.markdown_rich_text_converter import (
4
+ MarkdownRichTextConverter,
5
+ )
6
+ from notionary.blocks.schemas import BlockColor, CreateParagraphBlock, ParagraphData
7
+ from notionary.page.content.parser.parsers.base import (
8
+ BlockParsingContext,
9
+ LineParser,
10
+ )
11
+
12
+
13
+ class ParagraphParser(LineParser):
14
+ def __init__(self, rich_text_converter: MarkdownRichTextConverter) -> None:
15
+ super().__init__()
16
+ self._rich_text_converter = rich_text_converter
17
+
18
+ @override
19
+ def _can_handle(self, context: BlockParsingContext) -> bool:
20
+ if context.is_inside_parent_context():
21
+ return False
22
+ return bool(context.line)
23
+
24
+ @override
25
+ async def _process(self, context: BlockParsingContext) -> None:
26
+ block = await self._create_paragraph_block(context.line)
27
+ if block:
28
+ context.result_blocks.append(block)
29
+
30
+ async def _create_paragraph_block(self, text: str) -> CreateParagraphBlock | None:
31
+ if not text:
32
+ return None
33
+
34
+ rich_text = await self._rich_text_converter.to_rich_text(text)
35
+ paragraph_content = ParagraphData(rich_text=rich_text, color=BlockColor.DEFAULT)
36
+ return CreateParagraphBlock(paragraph=paragraph_content)
@@ -0,0 +1,42 @@
1
+ """Parser for PDF blocks."""
2
+
3
+ from typing import override
4
+
5
+ from notionary.blocks.schemas import (
6
+ CreatePdfBlock,
7
+ ExternalFile,
8
+ FileData,
9
+ FileType,
10
+ )
11
+ from notionary.page.content.parser.parsers.base import BlockParsingContext, LineParser
12
+ from notionary.page.content.syntax.service import SyntaxRegistry
13
+
14
+
15
+ class PdfParser(LineParser):
16
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
17
+ super().__init__(syntax_registry)
18
+ self._syntax = syntax_registry.get_pdf_syntax()
19
+
20
+ @override
21
+ def _can_handle(self, context: BlockParsingContext) -> bool:
22
+ if context.is_inside_parent_context():
23
+ return False
24
+ return self._syntax.regex_pattern.search(context.line) is not None
25
+
26
+ @override
27
+ async def _process(self, context: BlockParsingContext) -> None:
28
+ url = self._extract_url(context.line)
29
+ if not url:
30
+ return
31
+
32
+ pdf_data = FileData(
33
+ type=FileType.EXTERNAL,
34
+ external=ExternalFile(url=url),
35
+ caption=[],
36
+ )
37
+ block = CreatePdfBlock(pdf=pdf_data)
38
+ context.result_blocks.append(block)
39
+
40
+ def _extract_url(self, line: str) -> str | None:
41
+ match = self._syntax.regex_pattern.search(line)
42
+ return match.group(1).strip() if match else None
@@ -0,0 +1,65 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.rich_text.markdown_rich_text_converter import MarkdownRichTextConverter
4
+ from notionary.blocks.schemas import BlockColor, CreateQuoteBlock, CreateQuoteData
5
+ from notionary.page.content.parser.parsers.base import (
6
+ BlockParsingContext,
7
+ LineParser,
8
+ )
9
+ from notionary.page.content.syntax.service import SyntaxRegistry
10
+
11
+
12
+ class QuoteParser(LineParser):
13
+ def __init__(self, syntax_registry: SyntaxRegistry, rich_text_converter: MarkdownRichTextConverter) -> None:
14
+ super().__init__(syntax_registry)
15
+ self._syntax = syntax_registry.get_quote_syntax()
16
+ self._rich_text_converter = rich_text_converter
17
+
18
+ @override
19
+ def _can_handle(self, context: BlockParsingContext) -> bool:
20
+ if context.is_inside_parent_context():
21
+ return False
22
+ return self._is_quote(context.line)
23
+
24
+ @override
25
+ async def _process(self, context: BlockParsingContext) -> None:
26
+ quote_lines = self._collect_quote_lines(context)
27
+ lines_consumed = len(quote_lines)
28
+
29
+ block = await self._create_quote_block(quote_lines)
30
+ if block:
31
+ context.result_blocks.append(block)
32
+ context.lines_consumed = lines_consumed
33
+
34
+ def _collect_quote_lines(self, context: BlockParsingContext) -> list[str]:
35
+ quote_lines = [context.line]
36
+ for line in context.get_remaining_lines():
37
+ if not self._is_quote(line):
38
+ break
39
+ quote_lines.append(line)
40
+ return quote_lines
41
+
42
+ def _is_quote(self, line: str) -> bool:
43
+ return self._syntax.regex_pattern.match(line) is not None
44
+
45
+ async def _create_quote_block(self, quote_lines: list[str]) -> CreateQuoteBlock | None:
46
+ if not quote_lines:
47
+ return None
48
+
49
+ contents = []
50
+ for line in quote_lines:
51
+ match = self._syntax.regex_pattern.match(line)
52
+ if match:
53
+ contents.append(match.group(1).strip())
54
+
55
+ if not contents:
56
+ return None
57
+
58
+ content = self._join_contents_for_multiline_quote(contents)
59
+
60
+ rich_text = await self._rich_text_converter.to_rich_text(content)
61
+ quote_data = CreateQuoteData(rich_text=rich_text, color=BlockColor.DEFAULT)
62
+ return CreateQuoteBlock(quote=quote_data)
63
+
64
+ def _join_contents_for_multiline_quote(self, contents: list[str]) -> str:
65
+ return "\n".join(contents)
@@ -0,0 +1,35 @@
1
+ from typing import override
2
+
3
+ from notionary.blocks.schemas import BlockColor, CreateParagraphBlock, ParagraphData
4
+ from notionary.page.content.parser.parsers.base import (
5
+ BlockParsingContext,
6
+ LineParser,
7
+ )
8
+ from notionary.page.content.syntax.service import SyntaxRegistry
9
+
10
+
11
+ class SpaceParser(LineParser):
12
+ """
13
+ Parser for [space] markers that create empty paragraph blocks.
14
+ Uses SyntaxRegistry for centralized syntax definition.
15
+ """
16
+
17
+ def __init__(self, syntax_registry: SyntaxRegistry) -> None:
18
+ super().__init__(syntax_registry)
19
+ self._syntax = syntax_registry.get_space_syntax()
20
+
21
+ @override
22
+ def _can_handle(self, context: BlockParsingContext) -> bool:
23
+ if context.is_inside_parent_context():
24
+ return False
25
+ return self._syntax.regex_pattern.match(context.line.strip()) is not None
26
+
27
+ @override
28
+ async def _process(self, context: BlockParsingContext) -> None:
29
+ block = self._create_space_block()
30
+ if block:
31
+ context.result_blocks.append(block)
32
+
33
+ def _create_space_block(self) -> CreateParagraphBlock:
34
+ paragraph_data = ParagraphData(rich_text=[], color=BlockColor.DEFAULT)
35
+ return CreateParagraphBlock(paragraph=paragraph_data)