better-notion 2.1.0__tar.gz → 2.1.2__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 (203) hide show
  1. {better_notion-2.1.0 → better_notion-2.1.2}/PKG-INFO +1 -1
  2. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/schemas.py +10 -2
  3. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/workspace.py +158 -23
  4. {better_notion-2.1.0 → better_notion-2.1.2}/pyproject.toml +1 -1
  5. {better_notion-2.1.0 → better_notion-2.1.2}/.gitignore +0 -0
  6. {better_notion-2.1.0 → better_notion-2.1.2}/LICENSE +0 -0
  7. {better_notion-2.1.0 → better_notion-2.1.2}/README.md +0 -0
  8. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/__init__.py +0 -0
  9. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/__init__.py +0 -0
  10. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/client.py +0 -0
  11. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/__init__.py +0 -0
  12. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/blocks.py +0 -0
  13. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/comments.py +0 -0
  14. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/databases.py +0 -0
  15. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/pages.py +0 -0
  16. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/collections/users.py +0 -0
  17. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/__init__.py +0 -0
  18. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/block.py +0 -0
  19. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/comment.py +0 -0
  20. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/database.py +0 -0
  21. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/page.py +0 -0
  22. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/entities/user.py +0 -0
  23. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/errors.py +0 -0
  24. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/oauth.py +0 -0
  25. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/__init__.py +0 -0
  26. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/base.py +0 -0
  27. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/checkbox.py +0 -0
  28. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/date.py +0 -0
  29. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/email.py +0 -0
  30. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/number.py +0 -0
  31. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/phone.py +0 -0
  32. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/relation.py +0 -0
  33. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/rich_text.py +0 -0
  34. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/select.py +0 -0
  35. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/title.py +0 -0
  36. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/properties/url.py +0 -0
  37. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/utils/__init__.py +0 -0
  38. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_api/utils/pagination.py +0 -0
  39. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/__init__.py +0 -0
  40. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/async_typer.py +0 -0
  41. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/__init__.py +0 -0
  42. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/auth.py +0 -0
  43. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/blocks.py +0 -0
  44. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/comments.py +0 -0
  45. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/config.py +0 -0
  46. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/databases.py +0 -0
  47. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/pages.py +0 -0
  48. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/plugins.py +0 -0
  49. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/search.py +0 -0
  50. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/update.py +0 -0
  51. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/users.py +0 -0
  52. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/commands/workspace.py +0 -0
  53. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/config.py +0 -0
  54. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/display.py +0 -0
  55. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/docs/__init__.py +0 -0
  56. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/docs/base.py +0 -0
  57. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/docs/formatters.py +0 -0
  58. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/docs/registry.py +0 -0
  59. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/errors.py +0 -0
  60. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/main.py +0 -0
  61. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/markdown.py +0 -0
  62. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/response.py +0 -0
  63. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_cli/utils/__init__.py +0 -0
  64. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/__init__.py +0 -0
  65. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/base/__init__.py +0 -0
  66. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/base/entity.py +0 -0
  67. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/cache/__init__.py +0 -0
  68. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/cache/cache.py +0 -0
  69. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/client.py +0 -0
  70. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/__init__.py +0 -0
  71. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/block_manager.py +0 -0
  72. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/comment_manager.py +0 -0
  73. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/database_manager.py +0 -0
  74. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/page_manager.py +0 -0
  75. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/managers/user_manager.py +0 -0
  76. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/__init__.py +0 -0
  77. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/block.py +0 -0
  78. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/__init__.py +0 -0
  79. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/audio.py +0 -0
  80. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/bookmark.py +0 -0
  81. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/breadcrumb.py +0 -0
  82. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/bullet.py +0 -0
  83. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/callout.py +0 -0
  84. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/code.py +0 -0
  85. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/column.py +0 -0
  86. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/column_list.py +0 -0
  87. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/divider.py +0 -0
  88. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/embed.py +0 -0
  89. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/equation.py +0 -0
  90. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/file.py +0 -0
  91. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/heading.py +0 -0
  92. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/image.py +0 -0
  93. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/numbered.py +0 -0
  94. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/paragraph.py +0 -0
  95. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/pdf.py +0 -0
  96. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/quote.py +0 -0
  97. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/synced_block.py +0 -0
  98. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/table.py +0 -0
  99. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/table_row.py +0 -0
  100. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/template.py +0 -0
  101. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/todo.py +0 -0
  102. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/toggle.py +0 -0
  103. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/blocks/video.py +0 -0
  104. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/comment.py +0 -0
  105. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/database.py +0 -0
  106. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/page.py +0 -0
  107. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/models/user.py +0 -0
  108. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/parents/__init__.py +0 -0
  109. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/plugins.py +0 -0
  110. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/properties/__init__.py +0 -0
  111. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/properties/formula.py +0 -0
  112. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/properties/parsers.py +0 -0
  113. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/properties/relation.py +0 -0
  114. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/query/__init__.py +0 -0
  115. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/query/database_query.py +0 -0
  116. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/_sdk/query/filter_translator.py +0 -0
  117. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/__init__.py +0 -0
  118. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/base.py +0 -0
  119. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/loader.py +0 -0
  120. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/__init__.py +0 -0
  121. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents.py +0 -0
  122. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_cli.py +0 -0
  123. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_schema.py +0 -0
  124. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_sdk/__init__.py +0 -0
  125. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_sdk/managers.py +0 -0
  126. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_sdk/models.py +0 -0
  127. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/agents_sdk/plugin.py +0 -0
  128. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/official/productivity.py +0 -0
  129. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/plugins/state.py +0 -0
  130. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/__init__.py +0 -0
  131. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/__init__.py +0 -0
  132. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/auth.py +0 -0
  133. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/dependency_resolver.py +0 -0
  134. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/metadata.py +0 -0
  135. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/project_context.py +0 -0
  136. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/rbac.py +0 -0
  137. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/agents/state_machine.py +0 -0
  138. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/helpers.py +0 -0
  139. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/retry.py +0 -0
  140. {better_notion-2.1.0 → better_notion-2.1.2}/better_notion/utils/validators.py +0 -0
  141. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/base/test_entity.py +0 -0
  142. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/cache/test_cache.py +0 -0
  143. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/__init__.py +0 -0
  144. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/blocks/test_advanced_blocks.py +0 -0
  145. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/test_block.py +0 -0
  146. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/test_database.py +0 -0
  147. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/test_database_bug.py +0 -0
  148. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/test_page.py +0 -0
  149. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/models/test_user.py +0 -0
  150. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/properties/test_formula.py +0 -0
  151. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/properties/test_parsers.py +0 -0
  152. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/properties/test_relation.py +0 -0
  153. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/query/test_database_query.py +0 -0
  154. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/query/test_filter_translator.py +0 -0
  155. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/test_client.py +0 -0
  156. {better_notion-2.1.0 → better_notion-2.1.2}/tests/_sdk/test_comment.py +0 -0
  157. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/__init__.py +0 -0
  158. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_auth.py +0 -0
  159. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_dependency_resolver.py +0 -0
  160. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_plugin.py +0 -0
  161. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_project_context.py +0 -0
  162. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_rbac.py +0 -0
  163. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_schemas.py +0 -0
  164. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_state_machine.py +0 -0
  165. {better_notion-2.1.0 → better_notion-2.1.2}/tests/agents/test_workspace.py +0 -0
  166. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/__init__.py +0 -0
  167. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_async_typer.py +0 -0
  168. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_config.py +0 -0
  169. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_display.py +0 -0
  170. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_errors.py +0 -0
  171. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_main.py +0 -0
  172. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_pages_commands.py +0 -0
  173. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_response.py +0 -0
  174. {better_notion-2.1.0 → better_notion-2.1.2}/tests/cli/test_update.py +0 -0
  175. {better_notion-2.1.0 → better_notion-2.1.2}/tests/conftest.py +0 -0
  176. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/conftest.py +0 -0
  177. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/test_blocks.py +0 -0
  178. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/test_databases.py +0 -0
  179. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/test_pages.py +0 -0
  180. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/test_search.py +0 -0
  181. {better_notion-2.1.0 → better_notion-2.1.2}/tests/integration/test_users.py +0 -0
  182. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/__init__.py +0 -0
  183. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_agents_cli.py +0 -0
  184. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_agents_sdk_integration.py +0 -0
  185. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_agents_sdk_managers.py +0 -0
  186. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_agents_sdk_models.py +0 -0
  187. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_base.py +0 -0
  188. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_loader.py +0 -0
  189. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_marketplace.py +0 -0
  190. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_plugin_commands_state.py +0 -0
  191. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_productivity_plugin.py +0 -0
  192. {better_notion-2.1.0 → better_notion-2.1.2}/tests/plugins/test_state.py +0 -0
  193. {better_notion-2.1.0 → better_notion-2.1.2}/tests/sdk/__init__.py +0 -0
  194. {better_notion-2.1.0 → better_notion-2.1.2}/tests/sdk/test_plugin_system.py +0 -0
  195. {better_notion-2.1.0 → better_notion-2.1.2}/tests/test_metadata.py +0 -0
  196. {better_notion-2.1.0 → better_notion-2.1.2}/tests/test_schema_command.py +0 -0
  197. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_client.py +0 -0
  198. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_collections.py +0 -0
  199. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_entities.py +0 -0
  200. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_errors.py +0 -0
  201. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_helpers.py +0 -0
  202. {better_notion-2.1.0 → better_notion-2.1.2}/tests/unit/test_properties.py +0 -0
  203. {better_notion-2.1.0 → better_notion-2.1.2}/tests/utils/test_retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: better-notion
3
- Version: 2.1.0
3
+ Version: 2.1.2
4
4
  Summary: A high-level Python SDK for the Notion API with developer experience in mind.
5
5
  Project-URL: Homepage, https://github.com/nesalia-inc/better-notion
6
6
  Project-URL: Documentation, https://github.com/nesalia-inc/better-notion#readme
@@ -458,8 +458,10 @@ class TaskSchema:
458
458
  SelectOption.option("Low", "blue"),
459
459
  ],
460
460
  ),
461
- # Note: Self-referential relations (Dependencies, Dependent Tasks) removed because
462
- # they can't be created during initial database creation (need the database's own ID)
461
+ # Dependencies: Self-referential relation (will be updated after database creation)
462
+ "Dependencies": PropertyBuilder.relation("Dependencies", dual_property=False),
463
+ # Related Work Issue: Relation to Work Issues (will be updated after database creation)
464
+ "Related Work Issue": PropertyBuilder.relation("Related Work Issue", dual_property=False),
463
465
  "Estimated Hours": PropertyBuilder.number("Estimated Hours"),
464
466
  "Actual Hours": PropertyBuilder.number("Actual Hours"),
465
467
  "Assignee": PropertyBuilder.people("Assignee"),
@@ -557,6 +559,10 @@ class WorkIssueSchema:
557
559
  "Proposed Solution": PropertyBuilder.text("Proposed Solution"),
558
560
  "Related Idea": PropertyBuilder.relation("Related Idea", dual_property=False),
559
561
  "Fix Tasks": PropertyBuilder.relation("Fix Tasks", dual_property=False),
562
+ # Blocking Tasks: Tasks blocked by this work issue (will be updated after database creation)
563
+ "Blocking Tasks": PropertyBuilder.relation("Blocking Tasks", dual_property=False),
564
+ # Caused Incidents: Incidents caused by this work issue (will be updated after database creation)
565
+ "Caused Incidents": PropertyBuilder.relation("Caused Incidents", dual_property=False),
560
566
  }
561
567
 
562
568
 
@@ -599,6 +605,8 @@ class IncidentSchema:
599
605
  ],
600
606
  ),
601
607
  "Fix Task": PropertyBuilder.relation("Fix Task", dual_property=False),
608
+ # Root Cause Work Issue: Relation to Work Issues (will be updated after database creation)
609
+ "Root Cause Work Issue": PropertyBuilder.relation("Root Cause Work Issue", dual_property=False),
602
610
  "Root Cause": PropertyBuilder.text("Root Cause"),
603
611
  "Detected Date": PropertyBuilder.date("Detected Date"),
604
612
  "Resolved Date": PropertyBuilder.date("Resolved Date"),
@@ -93,10 +93,17 @@ class WorkspaceInitializer:
93
93
  logger.error(error_msg)
94
94
  raise Exception(error_msg) from e
95
95
 
96
- # Check for existing workspace unless skipped
97
- if not skip_detection:
98
- existing = await WorkspaceMetadata.detect_workspace(parent, self._client)
99
- if existing:
96
+ # Check for existing workspace
97
+ existing = await WorkspaceMetadata.detect_workspace(parent, self._client)
98
+
99
+ if existing:
100
+ if skip_detection:
101
+ # --reset flag: Delete all existing databases first
102
+ logger.warning(f"Reset mode: Deleting {len(existing.get('database_ids', {}))} existing databases...")
103
+ await self._delete_existing_databases(parent, existing.get("database_ids", {}))
104
+ logger.info("All existing databases deleted")
105
+ else:
106
+ # Normal mode: Raise error if workspace exists
100
107
  workspace_info = {
101
108
  "workspace_id": existing.get("workspace_id", "unknown"),
102
109
  "workspace_name": existing.get("workspace_name", workspace_name),
@@ -126,20 +133,31 @@ class WorkspaceInitializer:
126
133
  ("Incidents", "incidents", self._create_incidents_db),
127
134
  ]
128
135
 
129
- for display_name, key, create_func in databases_order:
130
- try:
131
- logger.info(f"Creating {display_name} database...")
132
- await create_func(parent)
133
- logger.info(f"✓ {display_name} database created: {self._database_ids[key]}")
134
- except Exception as e:
135
- error_msg = (
136
- f"Failed to create {display_name} database: {str(e)}\n"
137
- f"Databases created so far: {list(self._database_ids.keys())}\n"
138
- f"Parent page: {parent_page_id}\n"
139
- f"Workspace name: {workspace_name}"
140
- )
141
- logger.error(error_msg)
142
- raise Exception(error_msg) from e
136
+ try:
137
+ for display_name, key, create_func in databases_order:
138
+ try:
139
+ logger.info(f"Creating {display_name} database...")
140
+ await create_func(parent)
141
+ logger.info(f"✓ {display_name} database created: {self._database_ids[key]}")
142
+ except Exception as e:
143
+ # Clean up databases created so far
144
+ logger.error(f"Failed to create {display_name} database: {str(e)}")
145
+ logger.warning(f"Cleaning up {len(self._database_ids)} databases that were created...")
146
+ await self._delete_existing_databases(parent, self._database_ids)
147
+ error_msg = (
148
+ f"Failed to create {display_name} database: {str(e)}\n"
149
+ f"All partially created databases have been deleted.\n"
150
+ f"Parent page: {parent_page_id}\n"
151
+ f"Workspace name: {workspace_name}"
152
+ )
153
+ logger.error(error_msg)
154
+ raise Exception(error_msg) from e
155
+ except Exception as e:
156
+ # Re-raise the exception
157
+ raise e
158
+
159
+ # Update cross-database relations that require both databases to exist
160
+ await self._update_cross_database_relations()
143
161
 
144
162
  # Save workspace metadata
145
163
  self.save_database_ids()
@@ -334,19 +352,136 @@ class WorkspaceInitializer:
334
352
  # This is a no-op but documents the intent
335
353
  pass
336
354
 
355
+ async def _delete_existing_databases(self, parent: Page, database_ids: dict) -> None:
356
+ """Delete all existing databases in the parent page.
357
+
358
+ Args:
359
+ parent: Parent page
360
+ database_ids: Dict of database IDs to delete
361
+ """
362
+ import asyncio
363
+
364
+ deletion_tasks = []
365
+ for db_name, db_id in database_ids.items():
366
+ if db_id:
367
+ logger.info(f"Deleting {db_name} database ({db_id})...")
368
+ deletion_tasks.append(self._delete_database(db_id))
369
+
370
+ # Delete all databases concurrently
371
+ if deletion_tasks:
372
+ await asyncio.gather(*deletion_tasks, return_exceptions=True)
373
+
374
+ async def _delete_database(self, database_id: str) -> None:
375
+ """Delete a single database.
376
+
377
+ Args:
378
+ database_id: ID of the database to delete
379
+ """
380
+ try:
381
+ await self._client._api._request(
382
+ "DELETE",
383
+ f"/blocks/{database_id}"
384
+ )
385
+ logger.info(f"Deleted database {database_id}")
386
+ except Exception as e:
387
+ logger.warning(f"Failed to delete database {database_id}: {str(e)}")
388
+ # Continue with other deletions even if this one fails
389
+
337
390
  async def _update_self_relations(self, database_id: str) -> None:
338
391
  """Update self-referential relations in Tasks database.
339
392
 
340
393
  Note: The database was created with placeholder relations.
341
394
  This method updates them to point to themselves.
342
395
  """
343
- # Get the database
396
+ # Get the current database schema
344
397
  db = await self._client.databases.get(database_id)
345
398
 
346
- # Update Dependencies and Dependent Tasks to point to self
347
- # Note: This would require updating the database schema
348
- # via the Notion API, which may not support all updates
349
- pass
399
+ # Update the Dependencies relation to point to itself
400
+ schema = db.schema
401
+ if "Dependencies" in schema:
402
+ schema["Dependencies"]["relation"]["database_id"] = database_id
403
+
404
+ # Update the database schema via API
405
+ await self._client._api._request(
406
+ "PATCH",
407
+ f"/databases/{database_id}",
408
+ json={"properties": schema}
409
+ )
410
+
411
+ logger.info(f"Updated self-referential relations for Tasks database {database_id}")
412
+
413
+ async def _update_cross_database_relations(self) -> None:
414
+ """Update cross-database relations after all databases are created.
415
+
416
+ This updates:
417
+ - Tasks: Related Work Issue -> Work Issues
418
+ - Work Issues: Blocking Tasks -> Tasks
419
+ - Work Issues: Caused Incidents -> Incidents
420
+ - Incidents: Root Cause Work Issue -> Work Issues
421
+ """
422
+ if "tasks" in self._database_ids:
423
+ await self._update_relation(
424
+ self._database_ids["tasks"],
425
+ "Related Work Issue",
426
+ self._database_ids.get("work_issues")
427
+ )
428
+
429
+ if "work_issues" in self._database_ids:
430
+ await self._update_relation(
431
+ self._database_ids["work_issues"],
432
+ "Blocking Tasks",
433
+ self._database_ids.get("tasks")
434
+ )
435
+ await self._update_relation(
436
+ self._database_ids["work_issues"],
437
+ "Caused Incidents",
438
+ self._database_ids.get("incidents")
439
+ )
440
+
441
+ if "incidents" in self._database_ids:
442
+ await self._update_relation(
443
+ self._database_ids["incidents"],
444
+ "Root Cause Work Issue",
445
+ self._database_ids.get("work_issues")
446
+ )
447
+
448
+ logger.info("Updated all cross-database relations")
449
+
450
+ async def _update_relation(
451
+ self,
452
+ database_id: str,
453
+ property_name: str,
454
+ target_database_id: Optional[str],
455
+ ) -> None:
456
+ """Update a relation property to point to the target database.
457
+
458
+ Args:
459
+ database_id: Database to update
460
+ property_name: Name of the relation property
461
+ target_database_id: Target database ID (if None, skip update)
462
+ """
463
+ if not target_database_id:
464
+ logger.warning(f"Skipping {property_name} update: target database not found")
465
+ return
466
+
467
+ # Get the current database schema
468
+ db = await self._client.databases.get(database_id)
469
+ schema = db.schema
470
+
471
+ # Update the relation property
472
+ if property_name in schema:
473
+ schema[property_name]["relation"]["database_id"] = target_database_id
474
+
475
+ # Update the database schema via API
476
+ await self._client._api._request(
477
+ "PATCH",
478
+ f"/databases/{database_id}",
479
+ json={"properties": schema}
480
+ )
481
+
482
+ logger.info(f"Updated {property_name} relation to {target_database_id}")
483
+ else:
484
+ logger.warning(f"Property {property_name} not found in database {database_id}")
350
485
 
351
486
  def save_database_ids(self, path: Optional[Path] = None) -> None:
352
487
  """Save workspace metadata (database IDs and workspace info) to config file.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "better-notion"
3
- version = "2.1.0"
3
+ version = "2.1.2"
4
4
  description = "A high-level Python SDK for the Notion API with developer experience in mind."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
File without changes
File without changes
File without changes