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
@@ -0,0 +1,304 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import StrEnum
4
+ from typing import Any, Self
5
+
6
+ from pydantic import BaseModel, ValidationInfo, field_validator, model_serializer, model_validator
7
+
8
+ from notionary.shared.properties.type import PropertyType
9
+
10
+
11
+ class FieldType(StrEnum):
12
+ STRING = "string"
13
+ NUMBER = "number"
14
+ BOOLEAN = "boolean"
15
+ DATE = "date"
16
+ DATETIME = "datetime"
17
+ ARRAY = "array"
18
+ RELATION = "relation"
19
+ PEOPLE = "people"
20
+
21
+
22
+ class StringOperator(StrEnum):
23
+ EQUALS = "equals"
24
+ DOES_NOT_EQUAL = "does_not_equal"
25
+ CONTAINS = "contains"
26
+ DOES_NOT_CONTAIN = "does_not_contain"
27
+ STARTS_WITH = "starts_with"
28
+ ENDS_WITH = "ends_with"
29
+ IS_EMPTY = "is_empty"
30
+ IS_NOT_EMPTY = "is_not_empty"
31
+
32
+
33
+ class NumberOperator(StrEnum):
34
+ EQUALS = "equals"
35
+ DOES_NOT_EQUAL = "does_not_equal"
36
+ GREATER_THAN = "greater_than"
37
+ GREATER_THAN_OR_EQUAL_TO = "greater_than_or_equal_to"
38
+ LESS_THAN = "less_than"
39
+ LESS_THAN_OR_EQUAL_TO = "less_than_or_equal_to"
40
+ IS_EMPTY = "is_empty"
41
+ IS_NOT_EMPTY = "is_not_empty"
42
+
43
+
44
+ class BooleanOperator(StrEnum):
45
+ IS_TRUE = "is_true"
46
+ IS_FALSE = "is_false"
47
+
48
+
49
+ class StatusOperator(StrEnum):
50
+ EQUALS = "equals"
51
+ DOES_NOT_EQUAL = "does_not_equal"
52
+ IS_EMPTY = "is_empty"
53
+ IS_NOT_EMPTY = "is_not_empty"
54
+
55
+
56
+ class DateOperator(StrEnum):
57
+ EQUALS = "equals"
58
+ BEFORE = "before"
59
+ AFTER = "after"
60
+ ON_OR_BEFORE = "on_or_before"
61
+ ON_OR_AFTER = "on_or_after"
62
+ IS_EMPTY = "is_empty"
63
+ IS_NOT_EMPTY = "is_not_empty"
64
+
65
+
66
+ class ArrayOperator(StrEnum):
67
+ CONTAINS = "contains"
68
+ DOES_NOT_CONTAIN = "does_not_contain"
69
+ IS_EMPTY = "is_empty"
70
+ IS_NOT_EMPTY = "is_not_empty"
71
+
72
+
73
+ RelationOperator = ArrayOperator
74
+ PeopleOperator = ArrayOperator
75
+
76
+
77
+ class LogicalOperator(StrEnum):
78
+ AND = "and"
79
+ OR = "or"
80
+
81
+
82
+ class SortDirection(StrEnum):
83
+ ASCENDING = "ascending"
84
+ DESCENDING = "descending"
85
+
86
+
87
+ class TimestampType(StrEnum):
88
+ CREATED_TIME = "created_time"
89
+ LAST_EDITED_TIME = "last_edited_time"
90
+
91
+
92
+ class TimeUnit(StrEnum):
93
+ DAYS = "days"
94
+ WEEKS = "weeks"
95
+ MONTHS = "months"
96
+ YEARS = "years"
97
+
98
+
99
+ type Operator = StringOperator | NumberOperator | BooleanOperator | DateOperator | ArrayOperator
100
+ type FilterValue = str | int | float | bool | list[str | int | float]
101
+
102
+
103
+ class FilterCondition(BaseModel):
104
+ field: str
105
+ field_type: FieldType
106
+ operator: Operator
107
+ value: FilterValue | None = None
108
+ time_value: int | None = None
109
+ time_unit: TimeUnit | None = None
110
+
111
+ @model_validator(mode="after")
112
+ def validate_operator_and_value(self) -> Self:
113
+ self._validate_no_value_operators()
114
+ self._validate_value_required_operators()
115
+ self._validate_value_type_matches_field_type()
116
+ return self
117
+
118
+ def _validate_no_value_operators(self) -> None:
119
+ no_value_ops = {
120
+ StringOperator.IS_EMPTY,
121
+ StringOperator.IS_NOT_EMPTY,
122
+ NumberOperator.IS_EMPTY,
123
+ NumberOperator.IS_NOT_EMPTY,
124
+ BooleanOperator.IS_TRUE,
125
+ BooleanOperator.IS_FALSE,
126
+ DateOperator.IS_EMPTY,
127
+ DateOperator.IS_NOT_EMPTY,
128
+ ArrayOperator.IS_EMPTY,
129
+ ArrayOperator.IS_NOT_EMPTY,
130
+ }
131
+ if self.operator in no_value_ops and self.value is not None:
132
+ raise ValueError(f"Operator '{self.operator}' does not expect a value")
133
+
134
+ def _validate_value_required_operators(self) -> None:
135
+ operators_to_skip = {
136
+ StringOperator.IS_EMPTY,
137
+ StringOperator.IS_NOT_EMPTY,
138
+ NumberOperator.IS_EMPTY,
139
+ NumberOperator.IS_NOT_EMPTY,
140
+ BooleanOperator.IS_TRUE,
141
+ BooleanOperator.IS_FALSE,
142
+ DateOperator.IS_EMPTY,
143
+ DateOperator.IS_NOT_EMPTY,
144
+ ArrayOperator.IS_EMPTY,
145
+ ArrayOperator.IS_NOT_EMPTY,
146
+ }
147
+
148
+ is_skipped_operator = self.operator in operators_to_skip
149
+ if not is_skipped_operator and self.value is None:
150
+ raise ValueError(f"Operator '{self.operator}' requires a value")
151
+
152
+ def _validate_value_type_matches_field_type(self) -> None:
153
+ if self.value is None:
154
+ return
155
+
156
+ if self.field_type == FieldType.STRING:
157
+ self._ensure_value_is_string()
158
+ elif self.field_type == FieldType.NUMBER:
159
+ self._ensure_value_is_number()
160
+ elif self.field_type == FieldType.BOOLEAN:
161
+ self._ensure_value_is_boolean()
162
+ elif self.field_type in (FieldType.DATE, FieldType.DATETIME) or self.field_type in (
163
+ FieldType.ARRAY,
164
+ FieldType.RELATION,
165
+ FieldType.PEOPLE,
166
+ ):
167
+ self._ensure_value_is_string()
168
+
169
+ def _ensure_value_is_string(self) -> None:
170
+ if not isinstance(self.value, str):
171
+ raise ValueError(
172
+ f"Value for field type '{self.field_type}' must be a string, got {type(self.value).__name__}"
173
+ )
174
+
175
+ def _ensure_value_is_number(self) -> None:
176
+ if not isinstance(self.value, (int, float)):
177
+ raise ValueError(
178
+ f"Value for field type '{self.field_type}' must be a number (int or float), "
179
+ f"got {type(self.value).__name__}"
180
+ )
181
+
182
+ def _ensure_value_is_boolean(self) -> None:
183
+ if not isinstance(self.value, bool):
184
+ raise ValueError(
185
+ f"Value for field type '{self.field_type}' must be a boolean, got {type(self.value).__name__}"
186
+ )
187
+
188
+ @field_validator("operator")
189
+ @classmethod
190
+ def validate_operator_for_field_type(
191
+ cls,
192
+ value: Operator,
193
+ info: ValidationInfo,
194
+ ) -> Operator:
195
+ if "field_type" not in info.data:
196
+ return value
197
+
198
+ field_type: FieldType = info.data["field_type"]
199
+ operator_value = value if isinstance(value, str) else value.value
200
+
201
+ if not cls._is_operator_valid_for_field_type(operator_value, field_type):
202
+ raise ValueError(f"Operator '{operator_value}' is not valid for field type '{field_type}'")
203
+
204
+ return value
205
+
206
+ @staticmethod
207
+ def _is_operator_valid_for_field_type(operator: str, field_type: FieldType) -> bool:
208
+ valid_operators: dict[FieldType, list[str]] = {
209
+ FieldType.STRING: [op.value for op in StringOperator],
210
+ FieldType.NUMBER: [op.value for op in NumberOperator],
211
+ FieldType.BOOLEAN: [op.value for op in BooleanOperator],
212
+ FieldType.DATE: [op.value for op in DateOperator],
213
+ FieldType.DATETIME: [op.value for op in DateOperator],
214
+ FieldType.ARRAY: [op.value for op in ArrayOperator],
215
+ FieldType.RELATION: [op.value for op in ArrayOperator],
216
+ FieldType.PEOPLE: [op.value for op in ArrayOperator],
217
+ }
218
+
219
+ return operator in valid_operators.get(field_type, [])
220
+
221
+
222
+ class OrGroupMarker(BaseModel):
223
+ conditions: list[FilterCondition]
224
+
225
+
226
+ type InternalFilterCondition = FilterCondition | OrGroupMarker
227
+
228
+
229
+ class PropertyFilter(BaseModel):
230
+ property: str
231
+ property_type: PropertyType
232
+ operator: Operator
233
+ value: FilterValue | None = None
234
+
235
+ @model_validator(mode="after")
236
+ def validate_value_type(self) -> Self:
237
+ if self.value is None:
238
+ return self
239
+
240
+ if self.property_type in (PropertyType.PEOPLE, PropertyType.RELATION) and not isinstance(self.value, str):
241
+ raise ValueError(
242
+ f"Value for property type '{self.property_type.value}' must be a string, "
243
+ f"got {type(self.value).__name__}"
244
+ )
245
+
246
+ return self
247
+
248
+ @model_serializer
249
+ def serialize_model(self) -> dict[str, Any]:
250
+ property_type_str = self.property_type.value
251
+ operator_str = self.operator.value
252
+ filter_value = self.value
253
+
254
+ if isinstance(self.operator, BooleanOperator):
255
+ operator_str = "equals"
256
+ filter_value = self.operator == BooleanOperator.IS_TRUE
257
+
258
+ return {
259
+ "property": self.property,
260
+ property_type_str: {operator_str: filter_value if filter_value is not None else True},
261
+ }
262
+
263
+
264
+ class CompoundFilter(BaseModel):
265
+ operator: LogicalOperator
266
+ filters: list[PropertyFilter | CompoundFilter]
267
+
268
+ @model_serializer
269
+ def serialize_model(self) -> dict[str, Any]:
270
+ operator_str = self.operator.value
271
+ return {operator_str: [f.model_dump() for f in self.filters]}
272
+
273
+
274
+ type NotionFilter = PropertyFilter | CompoundFilter
275
+
276
+
277
+ class PropertySort(BaseModel):
278
+ property: str
279
+ direction: SortDirection
280
+
281
+
282
+ class TimestampSort(BaseModel):
283
+ timestamp: TimestampType
284
+ direction: SortDirection
285
+
286
+
287
+ type NotionSort = PropertySort | TimestampSort
288
+
289
+
290
+ class DataSourceQueryParams(BaseModel):
291
+ filter: NotionFilter | None = None
292
+ sorts: list[NotionSort] | None = None
293
+
294
+ @model_serializer
295
+ def serialize_model(self) -> dict[str, Any]:
296
+ result: dict[str, Any] = {}
297
+
298
+ if self.filter is not None:
299
+ result["filter"] = self.filter.model_dump()
300
+
301
+ if self.sorts is not None and len(self.sorts) > 0:
302
+ result["sorts"] = [sort.model_dump() for sort in self.sorts]
303
+
304
+ return result
@@ -0,0 +1,73 @@
1
+ from typing import ClassVar
2
+
3
+ from notionary.data_source.properties.models import DataSourceProperty
4
+ from notionary.data_source.query.schema import (
5
+ ArrayOperator,
6
+ BooleanOperator,
7
+ DateOperator,
8
+ NumberOperator,
9
+ Operator,
10
+ StatusOperator,
11
+ StringOperator,
12
+ )
13
+ from notionary.exceptions.data_source.builder import InvalidOperatorForPropertyType
14
+ from notionary.shared.properties.type import PropertyType
15
+
16
+
17
+ class OperatorValidator:
18
+ _PROPERTY_TYPE_OPERATORS: ClassVar[dict[PropertyType, list[type[Operator]]]] = {
19
+ PropertyType.TITLE: [StringOperator],
20
+ PropertyType.RICH_TEXT: [StringOperator],
21
+ PropertyType.NUMBER: [NumberOperator],
22
+ PropertyType.SELECT: [StringOperator],
23
+ PropertyType.MULTI_SELECT: [ArrayOperator],
24
+ PropertyType.STATUS: [StatusOperator],
25
+ PropertyType.DATE: [DateOperator],
26
+ PropertyType.PEOPLE: [ArrayOperator],
27
+ PropertyType.CHECKBOX: [BooleanOperator],
28
+ PropertyType.URL: [StringOperator],
29
+ PropertyType.EMAIL: [StringOperator],
30
+ PropertyType.PHONE_NUMBER: [StringOperator],
31
+ PropertyType.CREATED_TIME: [DateOperator],
32
+ PropertyType.CREATED_BY: [ArrayOperator],
33
+ PropertyType.LAST_EDITED_TIME: [DateOperator],
34
+ PropertyType.LAST_EDITED_BY: [ArrayOperator],
35
+ PropertyType.RELATION: [ArrayOperator],
36
+ }
37
+
38
+ def validate_operator_for_property(
39
+ self, property_name: str, property_obj: DataSourceProperty, operator: Operator
40
+ ) -> None:
41
+ if not self._is_operator_valid_for_property_type(property_obj.type, operator):
42
+ valid_operators = self._get_valid_operators_for_property_type(property_obj.type)
43
+ raise InvalidOperatorForPropertyType(
44
+ property_name=property_name,
45
+ property_type=property_obj.type,
46
+ operator=operator,
47
+ valid_operators=valid_operators,
48
+ )
49
+
50
+ def _is_operator_valid_for_property_type(self, property_type: PropertyType, operator: Operator) -> bool:
51
+ allowed_operator_types = self._PROPERTY_TYPE_OPERATORS.get(property_type, [])
52
+ valid_operator_values = self._get_operator_values_from_types(allowed_operator_types)
53
+ return operator.value in valid_operator_values
54
+
55
+ def _get_operator_values_from_types(self, operator_types: list[type[Operator]]) -> set[str]:
56
+ values: set[str] = set()
57
+ for operator_type in operator_types:
58
+ for operator in operator_type:
59
+ values.add(operator.value)
60
+ return values
61
+
62
+ def _get_valid_operators_for_property_type(self, property_type: PropertyType) -> list[Operator]:
63
+ allowed_operator_types = self._PROPERTY_TYPE_OPERATORS.get(property_type, [])
64
+ return self._collect_all_operators_from_types(allowed_operator_types)
65
+
66
+ def _collect_all_operators_from_types(self, operator_types: list[type[Operator]]) -> list[Operator]:
67
+ operators: list[Operator] = []
68
+ for operator_type in operator_types:
69
+ operators.extend(self._get_all_enum_values(operator_type))
70
+ return operators
71
+
72
+ def _get_all_enum_values(self, operator_type: type[Operator]) -> list[Operator]:
73
+ return list(operator_type)
@@ -0,0 +1,27 @@
1
+ from pydantic import BaseModel
2
+
3
+ from notionary.blocks.rich_text.models import RichText
4
+ from notionary.data_source.properties.models import DiscriminatedDataSourceProperty
5
+ from notionary.page.schemas import NotionPageDto
6
+ from notionary.shared.entity.schemas import EntityResponseDto, NotionEntityUpdateDto
7
+ from notionary.shared.models.parent import Parent
8
+
9
+
10
+ class UpdateDataSourceDto(NotionEntityUpdateDto):
11
+ title: list[RichText]
12
+ description: list[RichText]
13
+ archived: bool
14
+
15
+
16
+ class QueryDataSourceResponse(BaseModel):
17
+ results: list[NotionPageDto]
18
+ next_cursor: str | None = None
19
+ has_more: bool
20
+
21
+
22
+ class DataSourceDto(EntityResponseDto):
23
+ database_parent: Parent
24
+ title: list[RichText]
25
+ description: list[RichText]
26
+ archived: bool
27
+ properties: dict[str, DiscriminatedDataSourceProperty]