notionary 0.3.0__tar.gz → 0.3.1__tar.gz

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 (217) hide show
  1. {notionary-0.3.0 → notionary-0.3.1}/PKG-INFO +9 -5
  2. {notionary-0.3.0 → notionary-0.3.1}/README.md +7 -3
  3. notionary-0.3.1/notionary/__init__.py +14 -0
  4. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/enums.py +27 -0
  5. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/client.py +6 -9
  6. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/http/data_source_instance_client.py +4 -4
  7. notionary-0.3.1/notionary/data_source/query/__init__.py +9 -0
  8. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/query/builder.py +12 -3
  9. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/query/schema.py +5 -0
  10. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/service.py +14 -112
  11. {notionary-0.3.0 → notionary-0.3.1}/notionary/database/service.py +16 -58
  12. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/__init__.py +4 -0
  13. notionary-0.3.1/notionary/exceptions/block_parsing.py +37 -0
  14. {notionary-0.3.0 → notionary-0.3.1}/notionary/http/client.py +1 -1
  15. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/factory.py +2 -0
  16. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/handlers/__init__.py +2 -0
  17. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +12 -8
  18. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/handlers/indentation.py +2 -0
  19. notionary-0.3.1/notionary/page/content/parser/pre_processsing/handlers/video_syntax.py +66 -0
  20. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/handlers/whitespace.py +2 -0
  21. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/properties/client.py +2 -2
  22. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/properties/service.py +14 -3
  23. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/service.py +17 -78
  24. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/entity/service.py +94 -36
  25. notionary-0.3.1/notionary/utils/pagination.py +104 -0
  26. notionary-0.3.1/notionary/workspace/__init__.py +4 -0
  27. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/client.py +2 -0
  28. notionary-0.3.1/notionary/workspace/query/__init__.py +3 -0
  29. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/query/builder.py +25 -1
  30. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/query/models.py +9 -1
  31. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/query/service.py +29 -11
  32. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/service.py +31 -21
  33. {notionary-0.3.0 → notionary-0.3.1}/pyproject.toml +2 -2
  34. notionary-0.3.0/notionary/__init__.py +0 -7
  35. notionary-0.3.0/notionary/exceptions/block_parsing.py +0 -16
  36. notionary-0.3.0/notionary/utils/pagination.py +0 -100
  37. notionary-0.3.0/notionary/workspace/__init__.py +0 -4
  38. notionary-0.3.0/notionary/workspace/query/__init__.py +0 -3
  39. {notionary-0.3.0 → notionary-0.3.1}/.gitignore +0 -0
  40. {notionary-0.3.0 → notionary-0.3.1}/LICENSE +0 -0
  41. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/__init__.py +0 -0
  42. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/client.py +0 -0
  43. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/markdown_rich_text_converter.py +0 -0
  44. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/models.py +0 -0
  45. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/__init__.py +0 -0
  46. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/data_source.py +0 -0
  47. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/database.py +0 -0
  48. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/page.py +0 -0
  49. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/person.py +0 -0
  50. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/name_id_resolver/port.py +0 -0
  51. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/rich_text_markdown_converter.py +0 -0
  52. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/rich_text/rich_text_patterns.py +0 -0
  53. {notionary-0.3.0 → notionary-0.3.1}/notionary/blocks/schemas.py +0 -0
  54. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/__init__.py +0 -0
  55. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/factory.py +0 -0
  56. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/models.py +0 -0
  57. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/schemas.py +0 -0
  58. {notionary-0.3.0 → notionary-0.3.1}/notionary/comments/service.py +0 -0
  59. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/http/client.py +0 -0
  60. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/properties/schemas.py +0 -0
  61. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/query/resolver.py +0 -0
  62. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/query/validator.py +0 -0
  63. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/schema/registry.py +0 -0
  64. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/schema/service.py +0 -0
  65. {notionary-0.3.0 → notionary-0.3.1}/notionary/data_source/schemas.py +0 -0
  66. {notionary-0.3.0 → notionary-0.3.1}/notionary/database/client.py +0 -0
  67. {notionary-0.3.0 → notionary-0.3.1}/notionary/database/database_metadata_update_client.py +0 -0
  68. {notionary-0.3.0 → notionary-0.3.1}/notionary/database/schemas.py +0 -0
  69. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/api.py +0 -0
  70. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/base.py +0 -0
  71. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/data_source/__init__.py +0 -0
  72. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/data_source/builder.py +0 -0
  73. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/data_source/properties.py +0 -0
  74. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/properties.py +0 -0
  75. {notionary-0.3.0 → notionary-0.3.1}/notionary/exceptions/search.py +0 -0
  76. {notionary-0.3.0 → notionary-0.3.1}/notionary/file_upload/client.py +0 -0
  77. {notionary-0.3.0 → notionary-0.3.1}/notionary/file_upload/models.py +0 -0
  78. {notionary-0.3.0 → notionary-0.3.1}/notionary/file_upload/service.py +0 -0
  79. {notionary-0.3.0 → notionary-0.3.1}/notionary/http/models.py +0 -0
  80. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/blocks/client.py +0 -0
  81. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/__init__.py +0 -0
  82. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/builder.py +0 -0
  83. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/__init__.py +0 -0
  84. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/audio.py +0 -0
  85. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/base.py +0 -0
  86. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/bookmark.py +0 -0
  87. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/breadcrumb.py +0 -0
  88. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/bulleted_list.py +0 -0
  89. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/callout.py +0 -0
  90. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/code.py +0 -0
  91. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/columns.py +0 -0
  92. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/container.py +0 -0
  93. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/divider.py +0 -0
  94. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/embed.py +0 -0
  95. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/equation.py +0 -0
  96. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/file.py +0 -0
  97. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/heading.py +0 -0
  98. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/image.py +0 -0
  99. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/mixins/__init__.py +0 -0
  100. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/mixins/caption.py +0 -0
  101. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/numbered_list.py +0 -0
  102. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/paragraph.py +0 -0
  103. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/pdf.py +0 -0
  104. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/quote.py +0 -0
  105. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/space.py +0 -0
  106. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/table.py +0 -0
  107. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/table_of_contents.py +0 -0
  108. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/todo.py +0 -0
  109. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/toggle.py +0 -0
  110. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/markdown/nodes/video.py +0 -0
  111. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/context.py +0 -0
  112. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/factory.py +0 -0
  113. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/__init__.py +0 -0
  114. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/audio.py +0 -0
  115. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/base.py +0 -0
  116. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/bookmark.py +0 -0
  117. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/breadcrumb.py +0 -0
  118. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/bulleted_list.py +0 -0
  119. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/callout.py +0 -0
  120. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/caption.py +0 -0
  121. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/code.py +0 -0
  122. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/column.py +0 -0
  123. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/column_list.py +0 -0
  124. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/divider.py +0 -0
  125. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/embed.py +0 -0
  126. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/equation.py +0 -0
  127. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/file.py +0 -0
  128. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/heading.py +0 -0
  129. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/image.py +0 -0
  130. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/numbered_list.py +0 -0
  131. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/paragraph.py +0 -0
  132. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/pdf.py +0 -0
  133. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/quote.py +0 -0
  134. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/space.py +0 -0
  135. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/table.py +0 -0
  136. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/table_of_contents.py +0 -0
  137. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/todo.py +0 -0
  138. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/toggle.py +0 -0
  139. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/parsers/video.py +0 -0
  140. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/post_processing/handlers/__init__.py +0 -0
  141. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/post_processing/handlers/rich_text_length.py +0 -0
  142. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +0 -0
  143. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/post_processing/port.py +0 -0
  144. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/post_processing/service.py +0 -0
  145. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/handlers/port.py +0 -0
  146. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/pre_processsing/service.py +0 -0
  147. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/parser/service.py +0 -0
  148. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/context.py +0 -0
  149. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/factory.py +0 -0
  150. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/post_processing/handlers/__init__.py +0 -0
  151. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/post_processing/handlers/numbered_list.py +0 -0
  152. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/post_processing/port.py +0 -0
  153. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/post_processing/service.py +0 -0
  154. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/__init__.py +0 -0
  155. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/audio.py +0 -0
  156. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/base.py +0 -0
  157. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/bookmark.py +0 -0
  158. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/breadcrumb.py +0 -0
  159. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/bulleted_list.py +0 -0
  160. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/callout.py +0 -0
  161. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/captioned_block.py +0 -0
  162. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/code.py +0 -0
  163. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/column.py +0 -0
  164. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/column_list.py +0 -0
  165. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/divider.py +0 -0
  166. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/embed.py +0 -0
  167. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/equation.py +0 -0
  168. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/fallback.py +0 -0
  169. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/file.py +0 -0
  170. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/heading.py +0 -0
  171. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/image.py +0 -0
  172. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/numbered_list.py +0 -0
  173. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/paragraph.py +0 -0
  174. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/pdf.py +0 -0
  175. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/quote.py +0 -0
  176. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/table.py +0 -0
  177. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/table_of_contents.py +0 -0
  178. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/table_row.py +0 -0
  179. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/todo.py +0 -0
  180. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/toggle.py +0 -0
  181. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/renderers/video.py +0 -0
  182. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/renderer/service.py +0 -0
  183. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/service.py +0 -0
  184. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/syntax/__init__.py +0 -0
  185. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/syntax/grammar.py +0 -0
  186. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/syntax/models.py +0 -0
  187. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/content/syntax/registry.py +0 -0
  188. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/page_context.py +0 -0
  189. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/page_http_client.py +0 -0
  190. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/page_metadata_update_client.py +0 -0
  191. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/properties/factory.py +0 -0
  192. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/properties/models.py +0 -0
  193. {notionary-0.3.0 → notionary-0.3.1}/notionary/page/schemas.py +0 -0
  194. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/entity/client.py +0 -0
  195. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/entity/dto_parsers.py +0 -0
  196. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/entity/entity_metadata_update_client.py +0 -0
  197. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/entity/schemas.py +0 -0
  198. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/models/cover.py +0 -0
  199. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/models/file.py +0 -0
  200. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/models/icon.py +0 -0
  201. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/models/parent.py +0 -0
  202. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/properties/type.py +0 -0
  203. {notionary-0.3.0 → notionary-0.3.1}/notionary/shared/typings.py +0 -0
  204. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/__init__.py +0 -0
  205. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/base.py +0 -0
  206. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/bot.py +0 -0
  207. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/client.py +0 -0
  208. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/factory.py +0 -0
  209. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/person.py +0 -0
  210. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/schemas.py +0 -0
  211. {notionary-0.3.0 → notionary-0.3.1}/notionary/user/service.py +0 -0
  212. {notionary-0.3.0 → notionary-0.3.1}/notionary/utils/date.py +0 -0
  213. {notionary-0.3.0 → notionary-0.3.1}/notionary/utils/decorators.py +0 -0
  214. {notionary-0.3.0 → notionary-0.3.1}/notionary/utils/fuzzy.py +0 -0
  215. {notionary-0.3.0 → notionary-0.3.1}/notionary/utils/mixins/logging.py +0 -0
  216. {notionary-0.3.0 → notionary-0.3.1}/notionary/utils/uuid_utils.py +0 -0
  217. {notionary-0.3.0 → notionary-0.3.1}/notionary/workspace/schemas.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: notionary
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
5
5
  Project-URL: Homepage, https://github.com/mathisarends/notionary
6
6
  Author-email: Mathis Arends <mathisarends27@gmail.com>
7
7
  License: MIT
8
8
  License-File: LICENSE
9
- Requires-Python: >=3.11
9
+ Requires-Python: >=3.12
10
10
  Requires-Dist: aiofiles<25.0.0,>=24.1.0
11
11
  Requires-Dist: httpx>=0.28.0
12
12
  Requires-Dist: pydantic>=2.11.4
@@ -23,9 +23,13 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  <div align="center">
25
25
 
26
- [![Python Version](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/downloads/)
27
- [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
28
- [![Documentation](https://img.shields.io/badge/docs-mathisarends.github.io-blue.svg)](https://mathisarends.github.io/notionary/)
26
+ [![PyPI version](https://badge.fury.io/py/notionary.svg)](https://badge.fury.io/py/notionary)
27
+ [![Python Version](https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/downloads/)
28
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
29
+ [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mathisarends/fc0568b66a20fbbaa5018205861c0da9/raw/notionary-coverage.json)](https://github.com/mathisarends/notionary)
30
+ [![Downloads](https://img.shields.io/pypi/dm/notionary?color=blue)](https://pypi.org/project/notionary/)
31
+ [![Documentation](https://img.shields.io/badge/docs-notionary-blue?style=flat&logo=readthedocs)](https://mathisarends.github.io/notionary/)
32
+ [![Notion API](https://img.shields.io/badge/Notion%20API-Official-000000?logo=notion&logoColor=white)](https://developers.notion.com/)
29
33
 
30
34
  **Transform complex Notion API interactions into simple, Pythonic code.**
31
35
  Perfect for developers building AI agents, automation workflows, and dynamic content systems.
@@ -8,9 +8,13 @@
8
8
 
9
9
  <div align="center">
10
10
 
11
- [![Python Version](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/downloads/)
12
- [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
13
- [![Documentation](https://img.shields.io/badge/docs-mathisarends.github.io-blue.svg)](https://mathisarends.github.io/notionary/)
11
+ [![PyPI version](https://badge.fury.io/py/notionary.svg)](https://badge.fury.io/py/notionary)
12
+ [![Python Version](https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/downloads/)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+ [![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mathisarends/fc0568b66a20fbbaa5018205861c0da9/raw/notionary-coverage.json)](https://github.com/mathisarends/notionary)
15
+ [![Downloads](https://img.shields.io/pypi/dm/notionary?color=blue)](https://pypi.org/project/notionary/)
16
+ [![Documentation](https://img.shields.io/badge/docs-notionary-blue?style=flat&logo=readthedocs)](https://mathisarends.github.io/notionary/)
17
+ [![Notion API](https://img.shields.io/badge/Notion%20API-Official-000000?logo=notion&logoColor=white)](https://developers.notion.com/)
14
18
 
15
19
  **Transform complex Notion API interactions into simple, Pythonic code.**
16
20
  Perfect for developers building AI agents, automation workflows, and dynamic content systems.
@@ -0,0 +1,14 @@
1
+ from .data_source.service import NotionDataSource
2
+ from .database.service import NotionDatabase
3
+ from .page.content.markdown.builder import MarkdownBuilder
4
+ from .page.service import NotionPage
5
+ from .workspace import NotionWorkspace, NotionWorkspaceQueryConfigBuilder
6
+
7
+ __all__ = [
8
+ "MarkdownBuilder",
9
+ "NotionDataSource",
10
+ "NotionDatabase",
11
+ "NotionPage",
12
+ "NotionWorkspace",
13
+ "NotionWorkspaceQueryConfigBuilder",
14
+ ]
@@ -165,3 +165,30 @@ class CodingLanguage(StrEnum):
165
165
  return member
166
166
 
167
167
  return default if default is not None else cls.PLAIN_TEXT
168
+
169
+
170
+ class VideoFileType(StrEnum):
171
+ AMV = ".amv"
172
+ ASF = ".asf"
173
+ AVI = ".avi"
174
+ F4V = ".f4v"
175
+ FLV = ".flv"
176
+ GIFV = ".gifv"
177
+ MKV = ".mkv"
178
+ MOV = ".mov"
179
+ MPG = ".mpg"
180
+ MPEG = ".mpeg"
181
+ MPV = ".mpv"
182
+ MP4 = ".mp4"
183
+ M4V = ".m4v"
184
+ QT = ".qt"
185
+ WMV = ".wmv"
186
+
187
+ @classmethod
188
+ def get_all_extensions(cls) -> set[str]:
189
+ return {ext.value for ext in cls}
190
+
191
+ @classmethod
192
+ def is_valid_extension(cls, filename: str) -> bool:
193
+ lower_filename = filename.lower()
194
+ return any(lower_filename.endswith(ext.value) for ext in cls)
@@ -18,20 +18,17 @@ class CommentClient(NotionHttpClient):
18
18
  async def iter_comments(
19
19
  self,
20
20
  block_id: str,
21
- *,
22
- page_size: int = 100,
21
+ total_results_limit: int | None = None,
23
22
  ) -> AsyncGenerator[CommentDto]:
24
- """
25
- Iterates through all comments for a block, yielding each comment individually.
26
- Uses pagination to handle large result sets efficiently without loading everything into memory.
27
- """
28
23
  async for comment in paginate_notion_api_generator(
29
- self._list_comments_page, block_id=block_id, page_size=page_size
24
+ self._list_comments_page, block_id=block_id, total_results_limit=total_results_limit
30
25
  ):
31
26
  yield comment
32
27
 
33
- async def get_all_comments(self, block_id: str, *, page_size: int = 100) -> list[CommentDto]:
34
- all_comments = await paginate_notion_api(self._list_comments_page, block_id=block_id, page_size=page_size)
28
+ async def get_all_comments(self, block_id: str, *, total_results_limit: int | None = None) -> list[CommentDto]:
29
+ all_comments = await paginate_notion_api(
30
+ self._list_comments_page, block_id=block_id, total_results_limit=total_results_limit
31
+ )
35
32
 
36
33
  self.logger.debug("Retrieved %d total comments for block %s", len(all_comments), block_id)
37
34
  return all_comments
@@ -58,10 +58,10 @@ class DataSourceInstanceClient(NotionHttpClient, EntityMetadataUpdateClient):
58
58
 
59
59
  async def query(self, query_params: DataSourceQueryParams | None = None) -> QueryDataSourceResponse:
60
60
  query_params_dict = query_params.to_api_params() if query_params else {}
61
- page_size = query_params.page_size if query_params else None
61
+ total_result_limit = query_params.total_results_limit if query_params else None
62
62
 
63
63
  all_results = await paginate_notion_api(
64
- self._make_query_request, query_data=query_params_dict or {}, page_size=page_size
64
+ self._make_query_request, query_data=query_params_dict or {}, total_result_limit=total_result_limit
65
65
  )
66
66
 
67
67
  return QueryDataSourceResponse(
@@ -72,10 +72,10 @@ class DataSourceInstanceClient(NotionHttpClient, EntityMetadataUpdateClient):
72
72
 
73
73
  async def query_stream(self, query_params: DataSourceQueryParams | None = None) -> AsyncIterator[Any]:
74
74
  query_params_dict = query_params.model_dump() if query_params else {}
75
- page_size = query_params.page_size if query_params else None
75
+ total_result_limit = query_params.total_results_limit if query_params else None
76
76
 
77
77
  async for result in paginate_notion_api_generator(
78
- self._make_query_request, query_data=query_params_dict or {}, page_size=page_size
78
+ self._make_query_request, query_data=query_params_dict or {}, total_results_limit=total_result_limit
79
79
  ):
80
80
  yield result
81
81
 
@@ -0,0 +1,9 @@
1
+ from .builder import DataSourceQueryBuilder
2
+ from .resolver import QueryResolver
3
+ from .schema import DataSourceQueryParams
4
+
5
+ __all__ = [
6
+ "DataSourceQueryBuilder",
7
+ "DataSourceQueryParams",
8
+ "QueryResolver",
9
+ ]
@@ -46,6 +46,7 @@ class DataSourceQueryBuilder:
46
46
  self._negate_next = False
47
47
  self._or_group: list[FilterCondition] | None = None
48
48
  self._page_size: int | None = None
49
+ self._total_results_limit: int | None = None
49
50
 
50
51
  def where(self, property_name: str) -> Self:
51
52
  self._finalize_current_or_group()
@@ -193,9 +194,15 @@ class DataSourceQueryBuilder:
193
194
  self._sorts.append(sort)
194
195
  return self
195
196
 
196
- def limit(self, page_size: int) -> Self:
197
- if page_size < 1:
197
+ def total_results_limit(self, total_result_limit: int) -> Self:
198
+ if total_result_limit < 1:
198
199
  raise ValueError("Limit must be at least 1")
200
+ self._total_results_limit = total_result_limit
201
+ return self
202
+
203
+ def page_size(self, page_size: int) -> Self:
204
+ if page_size < 1:
205
+ raise ValueError("Page size must be at least 1")
199
206
  self._page_size = page_size
200
207
  return self
201
208
 
@@ -203,7 +210,9 @@ class DataSourceQueryBuilder:
203
210
  self._finalize_current_or_group()
204
211
  notion_filter = self._create_notion_filter_if_needed()
205
212
  sorts = self._create_sorts_if_needed()
206
- return DataSourceQueryParams(filter=notion_filter, sorts=sorts, page_size=self._page_size)
213
+ return DataSourceQueryParams(
214
+ filter=notion_filter, sorts=sorts, page_size=self._page_size, total_results_limit=self._total_results_limit
215
+ )
207
216
 
208
217
  def _select_property_without_negation(self, property_name: str) -> None:
209
218
  self._current_property = property_name
@@ -289,6 +289,8 @@ class DataSourceQueryParams(BaseModel):
289
289
  sorts: list[NotionSort] | None = None
290
290
  page_size: int | None = None
291
291
 
292
+ total_results_limit: int | None = None
293
+
292
294
  @model_serializer
293
295
  def to_api_params(self) -> JsonDict:
294
296
  result: JsonDict = {}
@@ -299,4 +301,7 @@ class DataSourceQueryParams(BaseModel):
299
301
  if self.sorts is not None and len(self.sorts) > 0:
300
302
  result["sorts"] = [sort.model_dump() for sort in self.sorts]
301
303
 
304
+ if self.page_size is not None:
305
+ result["page_size"] = self.page_size
306
+
302
307
  return result
@@ -16,27 +16,18 @@ from notionary.data_source.properties.schemas import (
16
16
  DataSourceSelectProperty,
17
17
  DataSourceStatusProperty,
18
18
  )
19
- from notionary.data_source.query.builder import DataSourceQueryBuilder
20
- from notionary.data_source.query.resolver import QueryResolver
21
- from notionary.data_source.query.schema import (
22
- DataSourceQueryParams,
23
- )
19
+ from notionary.data_source.query import DataSourceQueryBuilder, DataSourceQueryParams, QueryResolver
24
20
  from notionary.data_source.schema.service import DataSourcePropertySchemaFormatter
25
21
  from notionary.data_source.schemas import DataSourceDto
26
22
  from notionary.exceptions.data_source.properties import DataSourcePropertyNotFound, DataSourcePropertyTypeError
27
23
  from notionary.page.properties.models import PageTitleProperty
28
24
  from notionary.page.schemas import NotionPageDto
29
25
  from notionary.shared.entity.dto_parsers import (
30
- extract_cover_image_url_from_dto,
31
- extract_database_id,
32
26
  extract_description,
33
- extract_emoji_icon_from_dto,
34
- extract_external_icon_url_from_dto,
35
27
  extract_title,
36
28
  )
37
29
  from notionary.shared.entity.entity_metadata_update_client import EntityMetadataUpdateClient
38
30
  from notionary.shared.entity.service import Entity
39
- from notionary.user.schemas import PartialUserDto
40
31
  from notionary.workspace.query.service import WorkspaceQueryService
41
32
 
42
33
  if TYPE_CHECKING:
@@ -46,45 +37,21 @@ if TYPE_CHECKING:
46
37
  class NotionDataSource(Entity):
47
38
  def __init__(
48
39
  self,
49
- id: str,
40
+ dto: DataSourceDto,
50
41
  title: str,
51
- created_time: str,
52
- created_by: PartialUserDto,
53
- last_edited_time: str,
54
- last_edited_by: PartialUserDto,
55
- archived: bool,
56
- in_trash: bool,
57
- url: str,
42
+ description: str | None,
58
43
  properties: dict[str, DataSourceProperty],
59
- parent_database_id: str | None,
60
- emoji_icon: str | None = None,
61
- external_icon_url: str | None = None,
62
- cover_image_url: str | None = None,
63
- description: str | None = None,
64
- public_url: str | None = None,
65
- data_source_instance_client: DataSourceInstanceClient | None = None,
44
+ data_source_instance_client: DataSourceInstanceClient,
66
45
  query_resolver: QueryResolver | None = None,
67
46
  ) -> None:
68
- super().__init__(
69
- id=id,
70
- created_time=created_time,
71
- created_by=created_by,
72
- last_edited_time=last_edited_time,
73
- last_edited_by=last_edited_by,
74
- in_trash=in_trash,
75
- emoji_icon=emoji_icon,
76
- external_icon_url=external_icon_url,
77
- cover_image_url=cover_image_url,
78
- )
79
- self._parent_database_id = parent_database_id
47
+ super().__init__(dto=dto)
48
+
80
49
  self._parent_database: NotionDatabase | None = None
81
50
  self._title = title
82
- self._archived = archived
83
- self._url = url
84
- self._public_url = public_url
51
+ self._archived = dto.archived
85
52
  self._description = description
86
53
  self._properties = properties or {}
87
- self._data_source_client = data_source_instance_client or DataSourceInstanceClient(data_source_id=id)
54
+ self._data_source_client = data_source_instance_client
88
55
  self.query_resolver = query_resolver or QueryResolver()
89
56
 
90
57
  @classmethod
@@ -111,73 +78,21 @@ class NotionDataSource(Entity):
111
78
  @classmethod
112
79
  async def _create_from_dto(
113
80
  cls,
114
- response: DataSourceDto,
81
+ dto: DataSourceDto,
115
82
  rich_text_converter: RichTextToMarkdownConverter,
116
83
  ) -> Self:
117
84
  title, description = await asyncio.gather(
118
- extract_title(response, rich_text_converter),
119
- extract_description(response, rich_text_converter),
85
+ extract_title(dto, rich_text_converter),
86
+ extract_description(dto, rich_text_converter),
120
87
  )
121
88
 
122
- parent_database_id = extract_database_id(response)
89
+ data_source_instance_client = DataSourceInstanceClient(data_source_id=dto.id)
123
90
 
124
- return cls._create(
125
- id=response.id,
126
- title=title,
127
- description=description,
128
- created_time=response.created_time,
129
- created_by=response.created_by,
130
- last_edited_time=response.last_edited_time,
131
- last_edited_by=response.last_edited_by,
132
- archived=response.archived,
133
- in_trash=response.in_trash,
134
- url=response.url,
135
- properties=response.properties,
136
- parent_database_id=parent_database_id,
137
- emoji_icon=extract_emoji_icon_from_dto(response),
138
- external_icon_url=extract_external_icon_url_from_dto(response),
139
- cover_image_url=extract_cover_image_url_from_dto(response),
140
- public_url=response.url,
141
- )
142
-
143
- @classmethod
144
- def _create(
145
- cls,
146
- id: str,
147
- title: str,
148
- created_time: str,
149
- created_by: PartialUserDto,
150
- last_edited_time: str,
151
- last_edited_by: PartialUserDto,
152
- archived: bool,
153
- in_trash: bool,
154
- url: str,
155
- properties: dict[str, DataSourceProperty],
156
- parent_database_id: str | None,
157
- emoji_icon: str | None = None,
158
- external_icon_url: str | None = None,
159
- cover_image_url: str | None = None,
160
- description: str | None = None,
161
- public_url: str | None = None,
162
- ) -> Self:
163
- data_source_instance_client = DataSourceInstanceClient(data_source_id=id)
164
91
  return cls(
165
- id=id,
92
+ dto=dto,
166
93
  title=title,
167
- created_time=created_time,
168
- created_by=created_by,
169
- last_edited_time=last_edited_time,
170
- last_edited_by=last_edited_by,
171
- archived=archived,
172
- in_trash=in_trash,
173
- url=url,
174
- parent_database_id=parent_database_id,
175
- emoji_icon=emoji_icon,
176
- external_icon_url=external_icon_url,
177
- cover_image_url=cover_image_url,
178
94
  description=description,
179
- public_url=public_url,
180
- properties=properties,
95
+ properties=dto.properties,
181
96
  data_source_instance_client=data_source_instance_client,
182
97
  )
183
98
 
@@ -201,19 +116,6 @@ class NotionDataSource(Entity):
201
116
  def properties(self) -> dict[str, DataSourceProperty]:
202
117
  return self._properties
203
118
 
204
- @property
205
- def url(self) -> str:
206
- return self._url
207
-
208
- @property
209
- def public_url(self) -> str | None:
210
- return self._public_url
211
-
212
- async def get_parent_database(self) -> NotionDatabase | None:
213
- if self._parent_database is None and self._parent_database_id:
214
- self._parent_database = await NotionDatabase.from_id(self._parent_database_id)
215
- return self._parent_database
216
-
217
119
  async def create_blank_page(self, title: str | None = None) -> NotionPage:
218
120
  return await self._data_source_client.create_blank_page(title=title)
219
121
 
@@ -10,14 +10,10 @@ from notionary.database.client import NotionDatabaseHttpClient
10
10
  from notionary.database.database_metadata_update_client import DatabaseMetadataUpdateClient
11
11
  from notionary.database.schemas import NotionDatabaseDto
12
12
  from notionary.shared.entity.dto_parsers import (
13
- extract_cover_image_url_from_dto,
14
13
  extract_description,
15
- extract_emoji_icon_from_dto,
16
- extract_external_icon_url_from_dto,
17
14
  extract_title,
18
15
  )
19
16
  from notionary.shared.entity.service import Entity
20
- from notionary.user.schemas import PartialUserDto
21
17
  from notionary.workspace.query.service import WorkspaceQueryService
22
18
 
23
19
  type DataSourceFactory = Callable[[str], Awaitable[NotionDataSource]]
@@ -26,46 +22,24 @@ type DataSourceFactory = Callable[[str], Awaitable[NotionDataSource]]
26
22
  class NotionDatabase(Entity):
27
23
  def __init__(
28
24
  self,
29
- id: str,
25
+ dto: NotionDatabaseDto,
30
26
  title: str,
31
- created_time: str,
32
- created_by: PartialUserDto,
33
- last_edited_time: str,
34
- last_edited_by: PartialUserDto,
35
- url: str,
36
- in_trash: bool,
37
- is_inline: bool,
27
+ description: str | None,
38
28
  data_source_ids: list[str],
39
- public_url: str | None = None,
40
- emoji_icon: str | None = None,
41
- external_icon_url: str | None = None,
42
- cover_image_url: str | None = None,
43
- description: str | None = None,
44
- client: NotionDatabaseHttpClient | None = None,
45
- metadata_update_client: DatabaseMetadataUpdateClient | None = None,
29
+ client: NotionDatabaseHttpClient,
30
+ metadata_update_client: DatabaseMetadataUpdateClient,
46
31
  ) -> None:
47
- super().__init__(
48
- id=id,
49
- created_time=created_time,
50
- created_by=created_by,
51
- last_edited_time=last_edited_time,
52
- last_edited_by=last_edited_by,
53
- in_trash=in_trash,
54
- emoji_icon=emoji_icon,
55
- external_icon_url=external_icon_url,
56
- cover_image_url=cover_image_url,
57
- )
32
+ super().__init__(dto=dto)
33
+
58
34
  self._title = title
59
- self._url = url
60
- self._public_url = public_url
61
35
  self._description = description
62
- self._is_inline = is_inline
36
+ self._is_inline = dto.is_inline
63
37
 
64
38
  self._data_sources: list[NotionDataSource] | None = None
65
39
  self._data_source_ids = data_source_ids
66
40
 
67
- self.client = client or NotionDatabaseHttpClient(database_id=id)
68
- self._metadata_update_client = metadata_update_client or DatabaseMetadataUpdateClient(database_id=id)
41
+ self.client = client
42
+ self._metadata_update_client = metadata_update_client
69
43
 
70
44
  @classmethod
71
45
  async def from_id(
@@ -94,31 +68,23 @@ class NotionDatabase(Entity):
94
68
  @classmethod
95
69
  async def _create_from_dto(
96
70
  cls,
97
- response: NotionDatabaseDto,
71
+ dto: NotionDatabaseDto,
98
72
  rich_text_converter: RichTextToMarkdownConverter,
99
73
  client: NotionDatabaseHttpClient,
100
74
  ) -> Self:
101
75
  title, description = await asyncio.gather(
102
- extract_title(response, rich_text_converter), extract_description(response, rich_text_converter)
76
+ extract_title(dto, rich_text_converter), extract_description(dto, rich_text_converter)
103
77
  )
104
78
 
79
+ metadata_update_client = DatabaseMetadataUpdateClient(database_id=dto.id)
80
+
105
81
  return cls(
106
- id=response.id,
82
+ dto=dto,
107
83
  title=title,
108
84
  description=description,
109
- created_time=response.created_time,
110
- created_by=response.created_by,
111
- last_edited_time=response.last_edited_time,
112
- last_edited_by=response.last_edited_by,
113
- in_trash=response.in_trash,
114
- is_inline=response.is_inline,
115
- url=response.url,
116
- public_url=response.public_url,
117
- emoji_icon=extract_emoji_icon_from_dto(response),
118
- external_icon_url=extract_external_icon_url_from_dto(response),
119
- cover_image_url=extract_cover_image_url_from_dto(response),
120
- data_source_ids=[ds.id for ds in response.data_sources],
85
+ data_source_ids=[ds.id for ds in dto.data_sources],
121
86
  client=client,
87
+ metadata_update_client=metadata_update_client,
122
88
  )
123
89
 
124
90
  @property
@@ -129,14 +95,6 @@ class NotionDatabase(Entity):
129
95
  def title(self) -> str:
130
96
  return self._title
131
97
 
132
- @property
133
- def url(self) -> str:
134
- return self._url
135
-
136
- @property
137
- def public_url(self) -> str | None:
138
- return self._public_url
139
-
140
98
  @property
141
99
  def is_inline(self) -> bool:
142
100
  return self._is_inline
@@ -8,6 +8,7 @@ from .api import (
8
8
  NotionValidationError,
9
9
  )
10
10
  from .base import NotionaryError
11
+ from .block_parsing import InsufficientColumnsError, InvalidColumnRatioSumError, UnsupportedVideoFormatError
11
12
  from .data_source import DataSourcePropertyNotFound, DataSourcePropertyTypeError
12
13
  from .properties import AccessPagePropertyWithoutDataSourceError, PagePropertyNotFoundError, PagePropertyTypeError
13
14
  from .search import DatabaseNotFound, DataSourceNotFound, EntityNotFound, PageNotFound
@@ -19,6 +20,8 @@ __all__ = [
19
20
  "DataSourcePropertyTypeError",
20
21
  "DatabaseNotFound",
21
22
  "EntityNotFound",
23
+ "InsufficientColumnsError",
24
+ "InvalidColumnRatioSumError",
22
25
  "NotionApiError",
23
26
  "NotionAuthenticationError",
24
27
  "NotionConnectionError",
@@ -30,4 +33,5 @@ __all__ = [
30
33
  "PageNotFound",
31
34
  "PagePropertyNotFoundError",
32
35
  "PagePropertyTypeError",
36
+ "UnsupportedVideoFormatError",
33
37
  ]
@@ -0,0 +1,37 @@
1
+ from notionary.exceptions.base import NotionaryError
2
+
3
+ RATIO_TOLERANCE = 0.0001
4
+
5
+
6
+ class InsufficientColumnsError(NotionaryError):
7
+ def __init__(self, column_count: int) -> None:
8
+ self.column_count = column_count
9
+ super().__init__(f"Columns container must contain at least 2 column blocks, but only {column_count} found")
10
+
11
+
12
+ class InvalidColumnRatioSumError(NotionaryError):
13
+ def __init__(self, total: float, tolerance: float = RATIO_TOLERANCE) -> None:
14
+ self.total = total
15
+ self.tolerance = tolerance
16
+ super().__init__(f"Width ratios must sum to 1.0 (±{tolerance}), but sum is {total}")
17
+
18
+
19
+ class UnsupportedVideoFormatError(ValueError):
20
+ def __init__(self, url: str, supported_formats: list[str]) -> None:
21
+ self.url = url
22
+ self.supported_formats = supported_formats
23
+ super().__init__(self._create_user_friendly_message())
24
+
25
+ def _create_user_friendly_message(self) -> str:
26
+ formats = ", ".join(self.supported_formats[:5])
27
+ remaining = len(self.supported_formats) - 5
28
+
29
+ if remaining > 0:
30
+ formats += f" and {remaining} more"
31
+
32
+ return (
33
+ f"The video URL '{self.url}' uses an unsupported format.\n"
34
+ f"Supported formats include: {formats}.\n"
35
+ f"YouTube embed and watch URLs are also supported."
36
+ f"Also see https://developers.notion.com/reference/block#video for more information."
37
+ )
@@ -158,7 +158,7 @@ class NotionHttpClient(LoggingMixin):
158
158
  )
159
159
  if status_code == 404:
160
160
  raise NotionResourceNotFoundError(
161
- "The requested resource was not found. Please verify the page/database ID.",
161
+ "The requested resource was not found. Please verify the page/database/datasource ID.",
162
162
  status_code=status_code,
163
163
  response_text=response_text,
164
164
  )
@@ -5,6 +5,7 @@ from notionary.page.content.parser.post_processing.service import BlockPostProce
5
5
  from notionary.page.content.parser.pre_processsing.handlers import (
6
6
  ColumnSyntaxPreProcessor,
7
7
  IndentationNormalizer,
8
+ VideoFormatPreProcessor,
8
9
  WhitespacePreProcessor,
9
10
  )
10
11
  from notionary.page.content.parser.pre_processsing.service import MarkdownPreProcessor
@@ -60,6 +61,7 @@ class PageContentServiceFactory:
60
61
  pre_processor.register(ColumnSyntaxPreProcessor())
61
62
  pre_processor.register(WhitespacePreProcessor())
62
63
  pre_processor.register(IndentationNormalizer())
64
+ pre_processor.register(VideoFormatPreProcessor())
63
65
  return pre_processor
64
66
 
65
67
  def _create_post_processor(self) -> BlockPostProcessor:
@@ -1,11 +1,13 @@
1
1
  from .column_syntax import ColumnSyntaxPreProcessor
2
2
  from .indentation import IndentationNormalizer
3
3
  from .port import PreProcessor
4
+ from .video_syntax import VideoFormatPreProcessor
4
5
  from .whitespace import WhitespacePreProcessor
5
6
 
6
7
  __all__ = [
7
8
  "ColumnSyntaxPreProcessor",
8
9
  "IndentationNormalizer",
9
10
  "PreProcessor",
11
+ "VideoFormatPreProcessor",
10
12
  "WhitespacePreProcessor",
11
13
  ]