holder-python 0.2.5__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 (409) hide show
  1. holder_python-0.2.5/.gitignore +8 -0
  2. holder_python-0.2.5/PKG-INFO +120 -0
  3. holder_python-0.2.5/README.md +102 -0
  4. holder_python-0.2.5/docs/development.md +62 -0
  5. holder_python-0.2.5/docs/low-level-client.md +35 -0
  6. holder_python-0.2.5/docs/publishing.md +79 -0
  7. holder_python-0.2.5/docs/scripting.md +139 -0
  8. holder_python-0.2.5/openapi/generator.yaml +4 -0
  9. holder_python-0.2.5/openapi/provenance.json +8 -0
  10. holder_python-0.2.5/pyproject.toml +33 -0
  11. holder_python-0.2.5/scripts/generate.py +119 -0
  12. holder_python-0.2.5/scripts/pypi_readme.py +64 -0
  13. holder_python-0.2.5/src/holder/__init__.py +21 -0
  14. holder_python-0.2.5/src/holder/client.py +182 -0
  15. holder_python-0.2.5/src/holder/collections.py +70 -0
  16. holder_python-0.2.5/src/holder/events.py +238 -0
  17. holder_python-0.2.5/src/holder/exceptions.py +35 -0
  18. holder_python-0.2.5/src/holder/generated/__init__.py +8 -0
  19. holder_python-0.2.5/src/holder/generated/api/__init__.py +1 -0
  20. holder_python-0.2.5/src/holder/generated/api/default/__init__.py +1 -0
  21. holder_python-0.2.5/src/holder/generated/api/default/delete_ai_messages_message_id.py +166 -0
  22. holder_python-0.2.5/src/holder/generated/api/default/delete_ai_messages_message_id_links.py +205 -0
  23. holder_python-0.2.5/src/holder/generated/api/default/delete_ai_providers_credentials_provider.py +168 -0
  24. holder_python-0.2.5/src/holder/generated/api/default/delete_ai_threads_thread_id.py +166 -0
  25. holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id.py +225 -0
  26. holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_links.py +205 -0
  27. holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_milestones_milestone_id.py +175 -0
  28. holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_resources.py +197 -0
  29. holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_tags.py +197 -0
  30. holder_python-0.2.5/src/holder/generated/api/default/delete_locations_location_id.py +105 -0
  31. holder_python-0.2.5/src/holder/generated/api/default/delete_locations_location_id_binding.py +102 -0
  32. holder_python-0.2.5/src/holder/generated/api/default/delete_projects_project_id.py +187 -0
  33. holder_python-0.2.5/src/holder/generated/api/default/delete_resources_resource_id.py +161 -0
  34. holder_python-0.2.5/src/holder/generated/api/default/delete_trash.py +181 -0
  35. holder_python-0.2.5/src/holder/generated/api/default/delete_trash_type_id.py +175 -0
  36. holder_python-0.2.5/src/holder/generated/api/default/get_ai_capabilities.py +166 -0
  37. holder_python-0.2.5/src/holder/generated/api/default/get_ai_catalog_json.py +134 -0
  38. holder_python-0.2.5/src/holder/generated/api/default/get_ai_catalog_yaml.py +132 -0
  39. holder_python-0.2.5/src/holder/generated/api/default/get_ai_local_models_config.py +134 -0
  40. holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages.py +186 -0
  41. holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id.py +166 -0
  42. holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id_backlinks.py +194 -0
  43. holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id_links.py +194 -0
  44. holder_python-0.2.5/src/holder/generated/api/default/get_ai_providers_catalog.py +139 -0
  45. holder_python-0.2.5/src/holder/generated/api/default/get_ai_providers_credentials.py +136 -0
  46. holder_python-0.2.5/src/holder/generated/api/default/get_ai_runner_pull_job_id.py +171 -0
  47. holder_python-0.2.5/src/holder/generated/api/default/get_ai_runner_pull_job_id_events.py +218 -0
  48. holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs.py +186 -0
  49. holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs_run_id.py +166 -0
  50. holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs_run_id_events.py +213 -0
  51. holder_python-0.2.5/src/holder/generated/api/default/get_ai_status.py +134 -0
  52. holder_python-0.2.5/src/holder/generated/api/default/get_ai_threads.py +171 -0
  53. holder_python-0.2.5/src/holder/generated/api/default/get_ai_threads_thread_id.py +166 -0
  54. holder_python-0.2.5/src/holder/generated/api/default/get_calendar.py +221 -0
  55. holder_python-0.2.5/src/holder/generated/api/default/get_cards.py +286 -0
  56. holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id.py +166 -0
  57. holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_backlinks.py +194 -0
  58. holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_links.py +194 -0
  59. holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_milestones.py +173 -0
  60. holder_python-0.2.5/src/holder/generated/api/default/get_cards_context.py +226 -0
  61. holder_python-0.2.5/src/holder/generated/api/default/get_event_cursor.py +198 -0
  62. holder_python-0.2.5/src/holder/generated/api/default/get_git_providers_json.py +134 -0
  63. holder_python-0.2.5/src/holder/generated/api/default/get_git_providers_yaml.py +132 -0
  64. holder_python-0.2.5/src/holder/generated/api/default/get_health.py +134 -0
  65. holder_python-0.2.5/src/holder/generated/api/default/get_imports_job_id.py +159 -0
  66. holder_python-0.2.5/src/holder/generated/api/default/get_locations.py +160 -0
  67. holder_python-0.2.5/src/holder/generated/api/default/get_locations_location_id.py +157 -0
  68. holder_python-0.2.5/src/holder/generated/api/default/get_openapi_yaml.py +132 -0
  69. holder_python-0.2.5/src/holder/generated/api/default/get_ping.py +128 -0
  70. holder_python-0.2.5/src/holder/generated/api/default/get_projects.py +261 -0
  71. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id.py +166 -0
  72. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_cards.py +321 -0
  73. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_encryption_check.py +166 -0
  74. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_git_sync_status.py +171 -0
  75. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history.py +246 -0
  76. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id.py +243 -0
  77. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id_compare.py +286 -0
  78. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id_snapshot.py +225 -0
  79. holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_tags.py +171 -0
  80. holder_python-0.2.5/src/holder/generated/api/default/get_resources.py +242 -0
  81. holder_python-0.2.5/src/holder/generated/api/default/get_resources_resource_id.py +161 -0
  82. holder_python-0.2.5/src/holder/generated/api/default/get_resources_resource_id_assets_asset_id_content.py +247 -0
  83. holder_python-0.2.5/src/holder/generated/api/default/get_search_ai.py +216 -0
  84. holder_python-0.2.5/src/holder/generated/api/default/get_search_cards.py +216 -0
  85. holder_python-0.2.5/src/holder/generated/api/default/get_trash.py +181 -0
  86. holder_python-0.2.5/src/holder/generated/api/default/patch_ai_messages_message_id.py +192 -0
  87. holder_python-0.2.5/src/holder/generated/api/default/patch_ai_threads_thread_id.py +192 -0
  88. holder_python-0.2.5/src/holder/generated/api/default/patch_cards_card_id.py +192 -0
  89. holder_python-0.2.5/src/holder/generated/api/default/patch_cards_card_id_milestones_milestone_id.py +214 -0
  90. holder_python-0.2.5/src/holder/generated/api/default/patch_locations_location_id.py +117 -0
  91. holder_python-0.2.5/src/holder/generated/api/default/patch_projects_project_id.py +192 -0
  92. holder_python-0.2.5/src/holder/generated/api/default/patch_resources_resource_id.py +192 -0
  93. holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages.py +176 -0
  94. holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_capture.py +181 -0
  95. holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_message_id_links.py +192 -0
  96. holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_message_id_restore.py +166 -0
  97. holder_python-0.2.5/src/holder/generated/api/default/post_ai_runner_pull.py +181 -0
  98. holder_python-0.2.5/src/holder/generated/api/default/post_ai_runner_retry.py +139 -0
  99. holder_python-0.2.5/src/holder/generated/api/default/post_ai_runs.py +194 -0
  100. holder_python-0.2.5/src/holder/generated/api/default/post_ai_threads.py +176 -0
  101. holder_python-0.2.5/src/holder/generated/api/default/post_bye.py +166 -0
  102. holder_python-0.2.5/src/holder/generated/api/default/post_card_references_resolve.py +181 -0
  103. holder_python-0.2.5/src/holder/generated/api/default/post_cards.py +176 -0
  104. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_links.py +192 -0
  105. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_milestones.py +199 -0
  106. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_move.py +222 -0
  107. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_resources.py +197 -0
  108. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_restore.py +186 -0
  109. holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_tags.py +197 -0
  110. holder_python-0.2.5/src/holder/generated/api/default/post_imports.py +160 -0
  111. holder_python-0.2.5/src/holder/generated/api/default/post_locations.py +160 -0
  112. holder_python-0.2.5/src/holder/generated/api/default/post_locations_location_id_test.py +105 -0
  113. holder_python-0.2.5/src/holder/generated/api/default/post_projects.py +171 -0
  114. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_pull.py +211 -0
  115. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_push.py +193 -0
  116. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_sync.py +207 -0
  117. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_test_remote.py +205 -0
  118. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_history_cards_card_id_restore.py +240 -0
  119. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_recovery_token_export.py +196 -0
  120. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_recovery_token_import.py +196 -0
  121. holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_repair_hierarchy.py +240 -0
  122. holder_python-0.2.5/src/holder/generated/api/default/post_rebuild.py +176 -0
  123. holder_python-0.2.5/src/holder/generated/api/default/post_recovery_token_import.py +185 -0
  124. holder_python-0.2.5/src/holder/generated/api/default/post_reindex.py +139 -0
  125. holder_python-0.2.5/src/holder/generated/api/default/post_resources.py +176 -0
  126. holder_python-0.2.5/src/holder/generated/api/default/put_ai_local_models_config.py +173 -0
  127. holder_python-0.2.5/src/holder/generated/api/default/put_ai_providers_credentials.py +175 -0
  128. holder_python-0.2.5/src/holder/generated/api/default/put_locations_location_id_binding.py +117 -0
  129. holder_python-0.2.5/src/holder/generated/api/default/put_locations_preferred.py +107 -0
  130. holder_python-0.2.5/src/holder/generated/api/default/stream_changes.py +256 -0
  131. holder_python-0.2.5/src/holder/generated/client.py +280 -0
  132. holder_python-0.2.5/src/holder/generated/errors.py +16 -0
  133. holder_python-0.2.5/src/holder/generated/models/__init__.py +569 -0
  134. holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_data.py +111 -0
  135. holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_response.py +78 -0
  136. holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_update_request.py +134 -0
  137. holder_python-0.2.5/src/holder/generated/models/ai_message.py +204 -0
  138. holder_python-0.2.5/src/holder/generated/models/ai_message_capture_request.py +246 -0
  139. holder_python-0.2.5/src/holder/generated/models/ai_message_capture_request_context_type_0.py +46 -0
  140. holder_python-0.2.5/src/holder/generated/models/ai_message_capture_response.py +78 -0
  141. holder_python-0.2.5/src/holder/generated/models/ai_message_capture_response_data.py +78 -0
  142. holder_python-0.2.5/src/holder/generated/models/ai_message_create_request.py +186 -0
  143. holder_python-0.2.5/src/holder/generated/models/ai_message_create_response.py +78 -0
  144. holder_python-0.2.5/src/holder/generated/models/ai_message_create_response_data.py +62 -0
  145. holder_python-0.2.5/src/holder/generated/models/ai_message_get_response.py +76 -0
  146. holder_python-0.2.5/src/holder/generated/models/ai_message_list_response.py +84 -0
  147. holder_python-0.2.5/src/holder/generated/models/ai_message_update_request.py +203 -0
  148. holder_python-0.2.5/src/holder/generated/models/ai_message_update_response.py +78 -0
  149. holder_python-0.2.5/src/holder/generated/models/ai_message_update_response_data.py +62 -0
  150. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider.py +265 -0
  151. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_api_type_0.py +46 -0
  152. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_auth_type_0.py +46 -0
  153. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_models_item.py +46 -0
  154. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_response.py +78 -0
  155. holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_response_data.py +100 -0
  156. holder_python-0.2.5/src/holder/generated/models/ai_provider_credential.py +94 -0
  157. holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_delete_response.py +80 -0
  158. holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_delete_response_data.py +62 -0
  159. holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_upsert_request.py +92 -0
  160. holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_upsert_response.py +78 -0
  161. holder_python-0.2.5/src/holder/generated/models/ai_provider_credentials_list_response.py +80 -0
  162. holder_python-0.2.5/src/holder/generated/models/ai_provider_credentials_list_response_data.py +78 -0
  163. holder_python-0.2.5/src/holder/generated/models/ai_run_create_request.py +133 -0
  164. holder_python-0.2.5/src/holder/generated/models/ai_run_create_request_context.py +46 -0
  165. holder_python-0.2.5/src/holder/generated/models/ai_run_event_data.py +146 -0
  166. holder_python-0.2.5/src/holder/generated/models/ai_run_get_response.py +76 -0
  167. holder_python-0.2.5/src/holder/generated/models/ai_run_item.py +328 -0
  168. holder_python-0.2.5/src/holder/generated/models/ai_run_item_policy_trace_type_0.py +46 -0
  169. holder_python-0.2.5/src/holder/generated/models/ai_run_list_response.py +84 -0
  170. holder_python-0.2.5/src/holder/generated/models/ai_status_data.py +186 -0
  171. holder_python-0.2.5/src/holder/generated/models/ai_status_pull_job.py +130 -0
  172. holder_python-0.2.5/src/holder/generated/models/ai_status_response.py +76 -0
  173. holder_python-0.2.5/src/holder/generated/models/ai_thread.py +116 -0
  174. holder_python-0.2.5/src/holder/generated/models/ai_thread_create_request.py +119 -0
  175. holder_python-0.2.5/src/holder/generated/models/ai_thread_create_response.py +78 -0
  176. holder_python-0.2.5/src/holder/generated/models/ai_thread_create_response_data.py +62 -0
  177. holder_python-0.2.5/src/holder/generated/models/ai_thread_get_response.py +76 -0
  178. holder_python-0.2.5/src/holder/generated/models/ai_thread_list_response.py +84 -0
  179. holder_python-0.2.5/src/holder/generated/models/ai_thread_patch_response.py +78 -0
  180. holder_python-0.2.5/src/holder/generated/models/ai_thread_patch_response_data.py +62 -0
  181. holder_python-0.2.5/src/holder/generated/models/ai_thread_update_request.py +104 -0
  182. holder_python-0.2.5/src/holder/generated/models/asset_import_job.py +141 -0
  183. holder_python-0.2.5/src/holder/generated/models/asset_import_job_response.py +76 -0
  184. holder_python-0.2.5/src/holder/generated/models/asset_import_job_status.py +13 -0
  185. holder_python-0.2.5/src/holder/generated/models/asset_import_request.py +86 -0
  186. holder_python-0.2.5/src/holder/generated/models/asset_placement.py +96 -0
  187. holder_python-0.2.5/src/holder/generated/models/asset_placement_encoding.py +9 -0
  188. holder_python-0.2.5/src/holder/generated/models/bye_response.py +62 -0
  189. holder_python-0.2.5/src/holder/generated/models/calendar_card_activity.py +86 -0
  190. holder_python-0.2.5/src/holder/generated/models/card_context_breadcrumb.py +113 -0
  191. holder_python-0.2.5/src/holder/generated/models/card_context_breadcrumb_type.py +9 -0
  192. holder_python-0.2.5/src/holder/generated/models/card_context_card.py +161 -0
  193. holder_python-0.2.5/src/holder/generated/models/card_context_data.py +124 -0
  194. holder_python-0.2.5/src/holder/generated/models/card_context_data_project.py +70 -0
  195. holder_python-0.2.5/src/holder/generated/models/card_context_response.py +76 -0
  196. holder_python-0.2.5/src/holder/generated/models/card_create_request.py +147 -0
  197. holder_python-0.2.5/src/holder/generated/models/card_create_response.py +78 -0
  198. holder_python-0.2.5/src/holder/generated/models/card_create_response_data.py +70 -0
  199. holder_python-0.2.5/src/holder/generated/models/card_data.py +160 -0
  200. holder_python-0.2.5/src/holder/generated/models/card_get_response.py +76 -0
  201. holder_python-0.2.5/src/holder/generated/models/card_history_author.py +70 -0
  202. holder_python-0.2.5/src/holder/generated/models/card_history_comparison_data.py +110 -0
  203. holder_python-0.2.5/src/holder/generated/models/card_history_comparison_response.py +78 -0
  204. holder_python-0.2.5/src/holder/generated/models/card_history_diff_line.py +100 -0
  205. holder_python-0.2.5/src/holder/generated/models/card_history_diff_line_origin.py +10 -0
  206. holder_python-0.2.5/src/holder/generated/models/card_history_entry.py +172 -0
  207. holder_python-0.2.5/src/holder/generated/models/card_history_entry_kind.py +16 -0
  208. holder_python-0.2.5/src/holder/generated/models/card_history_entry_saves_item.py +94 -0
  209. holder_python-0.2.5/src/holder/generated/models/card_history_page_data.py +114 -0
  210. holder_python-0.2.5/src/holder/generated/models/card_history_page_response.py +76 -0
  211. holder_python-0.2.5/src/holder/generated/models/card_history_restore_response.py +80 -0
  212. holder_python-0.2.5/src/holder/generated/models/card_history_restore_response_data.py +108 -0
  213. holder_python-0.2.5/src/holder/generated/models/card_history_snapshot_response.py +80 -0
  214. holder_python-0.2.5/src/holder/generated/models/card_history_snapshot_response_data.py +76 -0
  215. holder_python-0.2.5/src/holder/generated/models/card_history_version.py +86 -0
  216. holder_python-0.2.5/src/holder/generated/models/card_link.py +116 -0
  217. holder_python-0.2.5/src/holder/generated/models/card_link_create_request.py +111 -0
  218. holder_python-0.2.5/src/holder/generated/models/card_link_create_response.py +76 -0
  219. holder_python-0.2.5/src/holder/generated/models/card_link_delete_request.py +80 -0
  220. holder_python-0.2.5/src/holder/generated/models/card_link_list_response.py +84 -0
  221. holder_python-0.2.5/src/holder/generated/models/card_list_item.py +161 -0
  222. holder_python-0.2.5/src/holder/generated/models/card_list_response.py +84 -0
  223. holder_python-0.2.5/src/holder/generated/models/card_move_intent.py +15 -0
  224. holder_python-0.2.5/src/holder/generated/models/card_move_request.py +134 -0
  225. holder_python-0.2.5/src/holder/generated/models/card_move_response.py +76 -0
  226. holder_python-0.2.5/src/holder/generated/models/card_move_result.py +114 -0
  227. holder_python-0.2.5/src/holder/generated/models/card_page.py +90 -0
  228. holder_python-0.2.5/src/holder/generated/models/card_page_item.py +170 -0
  229. holder_python-0.2.5/src/holder/generated/models/card_page_response.py +76 -0
  230. holder_python-0.2.5/src/holder/generated/models/card_patch_response.py +78 -0
  231. holder_python-0.2.5/src/holder/generated/models/card_patch_response_data.py +62 -0
  232. holder_python-0.2.5/src/holder/generated/models/card_reference_candidate.py +84 -0
  233. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data.py +129 -0
  234. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data_match_kind.py +10 -0
  235. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data_status.py +10 -0
  236. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_request.py +82 -0
  237. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_request_scope.py +10 -0
  238. holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_response.py +78 -0
  239. holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_request.py +70 -0
  240. holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_response.py +78 -0
  241. holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_result.py +88 -0
  242. holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_result_outcome.py +12 -0
  243. holder_python-0.2.5/src/holder/generated/models/card_update_request.py +122 -0
  244. holder_python-0.2.5/src/holder/generated/models/caste_info.py +85 -0
  245. holder_python-0.2.5/src/holder/generated/models/caste_info_name.py +12 -0
  246. holder_python-0.2.5/src/holder/generated/models/caste_recommended_model.py +143 -0
  247. holder_python-0.2.5/src/holder/generated/models/caste_recommended_model_required_caste.py +12 -0
  248. holder_python-0.2.5/src/holder/generated/models/change_event_data.py +109 -0
  249. holder_python-0.2.5/src/holder/generated/models/change_event_data_entity.py +14 -0
  250. holder_python-0.2.5/src/holder/generated/models/delete_cards_card_id_children.py +9 -0
  251. holder_python-0.2.5/src/holder/generated/models/delete_cards_card_id_resources_body.py +70 -0
  252. holder_python-0.2.5/src/holder/generated/models/error.py +70 -0
  253. holder_python-0.2.5/src/holder/generated/models/error_response.py +76 -0
  254. holder_python-0.2.5/src/holder/generated/models/event_checkpoint.py +92 -0
  255. holder_python-0.2.5/src/holder/generated/models/event_checkpoint_git_revisions.py +66 -0
  256. holder_python-0.2.5/src/holder/generated/models/event_checkpoint_history_urls.py +48 -0
  257. holder_python-0.2.5/src/holder/generated/models/event_checkpoint_response.py +76 -0
  258. holder_python-0.2.5/src/holder/generated/models/event_resync_data.py +116 -0
  259. holder_python-0.2.5/src/holder/generated/models/event_resync_data_reason.py +9 -0
  260. holder_python-0.2.5/src/holder/generated/models/get_ai_catalog_json_response_200.py +46 -0
  261. holder_python-0.2.5/src/holder/generated/models/get_ai_messages_message_id_backlinks_include_deleted.py +9 -0
  262. holder_python-0.2.5/src/holder/generated/models/get_ai_messages_message_id_links_include_deleted.py +9 -0
  263. holder_python-0.2.5/src/holder/generated/models/get_cards_card_id_backlinks_include_deleted.py +9 -0
  264. holder_python-0.2.5/src/holder/generated/models/get_cards_card_id_links_include_deleted.py +9 -0
  265. holder_python-0.2.5/src/holder/generated/models/get_cards_context_order.py +10 -0
  266. holder_python-0.2.5/src/holder/generated/models/get_cards_order.py +10 -0
  267. holder_python-0.2.5/src/holder/generated/models/get_cards_view.py +9 -0
  268. holder_python-0.2.5/src/holder/generated/models/get_git_providers_json_response_200.py +46 -0
  269. holder_python-0.2.5/src/holder/generated/models/get_locations_location_id_response_200.py +46 -0
  270. holder_python-0.2.5/src/holder/generated/models/get_ping_response_200.py +8 -0
  271. holder_python-0.2.5/src/holder/generated/models/get_projects_order.py +13 -0
  272. holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_cards_order.py +9 -0
  273. holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_cards_parent_type_0.py +8 -0
  274. holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_history_cards_card_id_compare_mode.py +9 -0
  275. holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_history_kind.py +13 -0
  276. holder_python-0.2.5/src/holder/generated/models/health_data.py +110 -0
  277. holder_python-0.2.5/src/holder/generated/models/health_data_crypt_filter.py +78 -0
  278. holder_python-0.2.5/src/holder/generated/models/health_response.py +76 -0
  279. holder_python-0.2.5/src/holder/generated/models/hierarchy_repair.py +100 -0
  280. holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_move.py +76 -0
  281. holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_request.py +62 -0
  282. holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_response.py +76 -0
  283. holder_python-0.2.5/src/holder/generated/models/local_model.py +91 -0
  284. holder_python-0.2.5/src/holder/generated/models/location_binding_request.py +81 -0
  285. holder_python-0.2.5/src/holder/generated/models/location_binding_request_values.py +46 -0
  286. holder_python-0.2.5/src/holder/generated/models/milestone.py +177 -0
  287. holder_python-0.2.5/src/holder/generated/models/milestone_create_request.py +135 -0
  288. holder_python-0.2.5/src/holder/generated/models/milestone_list_response.py +84 -0
  289. holder_python-0.2.5/src/holder/generated/models/milestone_remove_response.py +78 -0
  290. holder_python-0.2.5/src/holder/generated/models/milestone_remove_result.py +79 -0
  291. holder_python-0.2.5/src/holder/generated/models/milestone_response.py +76 -0
  292. holder_python-0.2.5/src/holder/generated/models/milestone_update_request.py +116 -0
  293. holder_python-0.2.5/src/holder/generated/models/patch_locations_location_id_body.py +90 -0
  294. holder_python-0.2.5/src/holder/generated/models/patch_locations_location_id_body_configuration.py +46 -0
  295. holder_python-0.2.5/src/holder/generated/models/post_ai_runner_pull_body.py +62 -0
  296. holder_python-0.2.5/src/holder/generated/models/post_cards_card_id_resources_body.py +70 -0
  297. holder_python-0.2.5/src/holder/generated/models/post_locations_response_201.py +46 -0
  298. holder_python-0.2.5/src/holder/generated/models/project.py +197 -0
  299. holder_python-0.2.5/src/holder/generated/models/project_calendar_response.py +78 -0
  300. holder_python-0.2.5/src/holder/generated/models/project_calendar_response_data.py +136 -0
  301. holder_python-0.2.5/src/holder/generated/models/project_create_request.py +177 -0
  302. holder_python-0.2.5/src/holder/generated/models/project_create_request_privacy_mode.py +9 -0
  303. holder_python-0.2.5/src/holder/generated/models/project_create_response.py +78 -0
  304. holder_python-0.2.5/src/holder/generated/models/project_create_response_data.py +62 -0
  305. holder_python-0.2.5/src/holder/generated/models/project_delete_response.py +78 -0
  306. holder_python-0.2.5/src/holder/generated/models/project_delete_response_data.py +62 -0
  307. holder_python-0.2.5/src/holder/generated/models/project_encryption_check.py +94 -0
  308. holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response.py +80 -0
  309. holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response_data.py +92 -0
  310. holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response_data_privacy_mode.py +9 -0
  311. holder_python-0.2.5/src/holder/generated/models/project_get_response.py +76 -0
  312. holder_python-0.2.5/src/holder/generated/models/project_git_push_request.py +95 -0
  313. holder_python-0.2.5/src/holder/generated/models/project_git_push_response.py +78 -0
  314. holder_python-0.2.5/src/holder/generated/models/project_git_push_response_data.py +199 -0
  315. holder_python-0.2.5/src/holder/generated/models/project_git_push_response_data_status.py +15 -0
  316. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response.py +80 -0
  317. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data.py +163 -0
  318. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_pull.py +96 -0
  319. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_pull_status.py +11 -0
  320. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_push.py +118 -0
  321. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_push_status.py +15 -0
  322. holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_status.py +9 -0
  323. holder_python-0.2.5/src/holder/generated/models/project_git_sync_request.py +94 -0
  324. holder_python-0.2.5/src/holder/generated/models/project_git_sync_status_response.py +80 -0
  325. holder_python-0.2.5/src/holder/generated/models/project_git_sync_status_response_data.py +76 -0
  326. holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_request.py +96 -0
  327. holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response.py +80 -0
  328. holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response_data.py +151 -0
  329. holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response_data_status.py +14 -0
  330. holder_python-0.2.5/src/holder/generated/models/project_history_activity.py +138 -0
  331. holder_python-0.2.5/src/holder/generated/models/project_history_affected_object.py +74 -0
  332. holder_python-0.2.5/src/holder/generated/models/project_history_affected_object_kind.py +13 -0
  333. holder_python-0.2.5/src/holder/generated/models/project_history_page_data.py +115 -0
  334. holder_python-0.2.5/src/holder/generated/models/project_history_page_response.py +78 -0
  335. holder_python-0.2.5/src/holder/generated/models/project_list_response.py +84 -0
  336. holder_python-0.2.5/src/holder/generated/models/project_privacy_mode.py +9 -0
  337. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_request.py +62 -0
  338. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_response.py +80 -0
  339. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_response_data.py +78 -0
  340. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_request.py +70 -0
  341. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_response.py +80 -0
  342. holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_response_data.py +62 -0
  343. holder_python-0.2.5/src/holder/generated/models/project_sync.py +227 -0
  344. holder_python-0.2.5/src/holder/generated/models/project_tag.py +70 -0
  345. holder_python-0.2.5/src/holder/generated/models/project_tag_list_response.py +84 -0
  346. holder_python-0.2.5/src/holder/generated/models/project_update_request.py +181 -0
  347. holder_python-0.2.5/src/holder/generated/models/project_update_request_privacy_mode.py +9 -0
  348. holder_python-0.2.5/src/holder/generated/models/project_update_response.py +78 -0
  349. holder_python-0.2.5/src/holder/generated/models/project_update_response_data.py +75 -0
  350. holder_python-0.2.5/src/holder/generated/models/put_locations_preferred_body.py +70 -0
  351. holder_python-0.2.5/src/holder/generated/models/rebuild_data.py +94 -0
  352. holder_python-0.2.5/src/holder/generated/models/rebuild_request.py +62 -0
  353. holder_python-0.2.5/src/holder/generated/models/rebuild_response.py +76 -0
  354. holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response.py +80 -0
  355. holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response_data.py +141 -0
  356. holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response_data_pull_status.py +10 -0
  357. holder_python-0.2.5/src/holder/generated/models/reindex_data.py +62 -0
  358. holder_python-0.2.5/src/holder/generated/models/reindex_response.py +76 -0
  359. holder_python-0.2.5/src/holder/generated/models/resource.py +134 -0
  360. holder_python-0.2.5/src/holder/generated/models/resource_asset.py +140 -0
  361. holder_python-0.2.5/src/holder/generated/models/resource_attachment_response.py +80 -0
  362. holder_python-0.2.5/src/holder/generated/models/resource_attachment_response_data.py +90 -0
  363. holder_python-0.2.5/src/holder/generated/models/resource_attachment_response_data_outcome.py +11 -0
  364. holder_python-0.2.5/src/holder/generated/models/resource_create_request.py +129 -0
  365. holder_python-0.2.5/src/holder/generated/models/resource_delete_response.py +78 -0
  366. holder_python-0.2.5/src/holder/generated/models/resource_delete_response_data.py +62 -0
  367. holder_python-0.2.5/src/holder/generated/models/resource_list_response.py +134 -0
  368. holder_python-0.2.5/src/holder/generated/models/resource_metadata.py +55 -0
  369. holder_python-0.2.5/src/holder/generated/models/resource_response.py +76 -0
  370. holder_python-0.2.5/src/holder/generated/models/resource_update_request.py +102 -0
  371. holder_python-0.2.5/src/holder/generated/models/runner_capabilities_data.py +220 -0
  372. holder_python-0.2.5/src/holder/generated/models/runner_capabilities_response.py +78 -0
  373. holder_python-0.2.5/src/holder/generated/models/runner_pull_job.py +122 -0
  374. holder_python-0.2.5/src/holder/generated/models/runner_pull_progress.py +86 -0
  375. holder_python-0.2.5/src/holder/generated/models/runner_pull_start_response.py +78 -0
  376. holder_python-0.2.5/src/holder/generated/models/runner_pull_start_response_data.py +78 -0
  377. holder_python-0.2.5/src/holder/generated/models/runner_pull_status_response.py +76 -0
  378. holder_python-0.2.5/src/holder/generated/models/search_card_item.py +102 -0
  379. holder_python-0.2.5/src/holder/generated/models/search_cards_response.py +84 -0
  380. holder_python-0.2.5/src/holder/generated/models/search_message_item.py +86 -0
  381. holder_python-0.2.5/src/holder/generated/models/search_messages_response.py +84 -0
  382. holder_python-0.2.5/src/holder/generated/models/storage_location.py +149 -0
  383. holder_python-0.2.5/src/holder/generated/models/storage_location_configuration.py +48 -0
  384. holder_python-0.2.5/src/holder/generated/models/storage_location_list_response.py +100 -0
  385. holder_python-0.2.5/src/holder/generated/models/storage_location_provider.py +9 -0
  386. holder_python-0.2.5/src/holder/generated/models/storage_location_request.py +118 -0
  387. holder_python-0.2.5/src/holder/generated/models/storage_location_request_configuration.py +46 -0
  388. holder_python-0.2.5/src/holder/generated/models/storage_location_request_provider.py +9 -0
  389. holder_python-0.2.5/src/holder/generated/models/trash_delete_response.py +78 -0
  390. holder_python-0.2.5/src/holder/generated/models/trash_delete_response_data.py +46 -0
  391. holder_python-0.2.5/src/holder/generated/models/trash_item.py +211 -0
  392. holder_python-0.2.5/src/holder/generated/models/trash_list_response.py +84 -0
  393. holder_python-0.2.5/src/holder/generated/types.py +54 -0
  394. holder_python-0.2.5/src/holder/library.py +15 -0
  395. holder_python-0.2.5/src/holder/models/__init__.py +15 -0
  396. holder_python-0.2.5/src/holder/models/card.py +272 -0
  397. holder_python-0.2.5/src/holder/models/project.py +207 -0
  398. holder_python-0.2.5/src/holder/models/search.py +66 -0
  399. holder_python-0.2.5/src/holder/models/tag.py +117 -0
  400. holder_python-0.2.5/src/holder/py.typed +0 -0
  401. holder_python-0.2.5/tests/test_events.py +372 -0
  402. holder_python-0.2.5/tests/test_generated_client.py +390 -0
  403. holder_python-0.2.5/tests/test_generation.py +47 -0
  404. holder_python-0.2.5/tests/test_library.py +746 -0
  405. holder_python-0.2.5/tests/test_library_live.py +367 -0
  406. holder_python-0.2.5/tests/test_lifecycle.py +99 -0
  407. holder_python-0.2.5/tests/test_moves.py +187 -0
  408. holder_python-0.2.5/tests/test_search.py +189 -0
  409. holder_python-0.2.5/tests/test_tags.py +227 -0
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ *.egg-info/
7
+ build/
8
+ dist/
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.5
2
+ Name: holder-python
3
+ Version: 0.2.5
4
+ Summary: Control your knowledge using Python
5
+ Project-URL: Repository, https://github.com/HolderTeam/holder/tree/main/python/holder
6
+ Project-URL: Issues, https://github.com/HolderTeam/holder/issues
7
+ License-Expression: GPL-3.0-only
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: attrs>=22.2
10
+ Requires-Dist: httpx<0.29,>=0.23.1
11
+ Requires-Dist: typing-extensions>=4.5
12
+ Provides-Extra: dev
13
+ Requires-Dist: build<2,>=1.2; extra == 'dev'
14
+ Requires-Dist: openapi-python-client==0.29.1; extra == 'dev'
15
+ Requires-Dist: pytest<10,>=8; extra == 'dev'
16
+ Requires-Dist: ruff==0.16.10; extra == 'dev'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # Holder for Python
20
+
21
+ Holder is an open-source, local-first knowledge app for organising your ideas
22
+ and digital information as index cards and the connections between them.
23
+
24
+ Use Python to read and update the projects and cards in your running Holder
25
+ installation. Changes you make in a script appear in Holder too.
26
+
27
+ ## Get started
28
+
29
+ 1. You need the Holder application on your computer.
30
+ Get it from https://www.holder.team/
31
+
32
+ 2. You need Python 3.11 or newer.
33
+ If in doubt, get the latest version (i.e. 3.15) from:
34
+ https://www.python.org/downloads/
35
+
36
+ 3. Install the Holder Python library with:
37
+
38
+ ```sh
39
+ python3 -m pip install holder-python
40
+ ```
41
+
42
+ Save this as `list_cards.py` and run it with `python3 list_cards.py`:
43
+
44
+ ```python
45
+ from holder import Holder
46
+
47
+ with Holder() as holder:
48
+ for project in holder.projects:
49
+ print(project.name)
50
+ for card in project.cards:
51
+ print(" ", card.title)
52
+ ```
53
+
54
+ `Holder()` finds or starts your local Holder daemon using `holderctl`. The
55
+ `with` block closes the Python connection when the script ends; it does not
56
+ stop Holder.
57
+
58
+ ## Create and edit cards
59
+
60
+ This example creates a project and two cards. Run it once: each run creates
61
+ another project named `Research`.
62
+
63
+ ```python
64
+ from holder import Holder
65
+
66
+ with Holder() as holder:
67
+ project = holder.projects.create(name="Research")
68
+ card = project.cards.create(title="An idea", content="My notes")
69
+ child = card.children.create(title="Next step")
70
+ child.update(content="Try it out")
71
+ card.tags.add("research")
72
+ ```
73
+
74
+ To work with an existing project, find it by name and get a card by its ID:
75
+
76
+ ```python
77
+ from holder import Holder
78
+
79
+ with Holder() as holder:
80
+ matches = holder.projects.filter(name="Research")
81
+ project = matches[0]
82
+ for card in project.cards:
83
+ print(card.id, card.title)
84
+
85
+ # Replace this with an ID printed above.
86
+ card = project.cards.get("card-id-here")
87
+ card.update(title="A better title")
88
+ ```
89
+
90
+ The name filter matches part of a name. If there are no matches, `[0]` raises
91
+ `IndexError`. Card content is available as `card.content`; use `card.update(...)`
92
+ to save edits. Card attributes cannot be assigned directly.
93
+
94
+ ## Find cards
95
+
96
+ Search within a project and inspect the matching text:
97
+
98
+ ```python
99
+ from holder import Holder
100
+
101
+ with Holder() as holder:
102
+ project = holder.projects.filter(name="Research")[0]
103
+ for result in project.cards.search("research notes"):
104
+ print(result.title, result.snippet)
105
+ ```
106
+
107
+ You can also list cards with a tag using
108
+ `project.cards.filter(tag="research")`, or list just top-level cards with
109
+ `project.cards.roots()`.
110
+
111
+ ## More help
112
+
113
+ - [More scripting tasks](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/scripting.md): moves, Trash, tags, collection
114
+ refreshes, and connecting to a specific daemon.
115
+ - [Low-level client](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/low-level-client.md): direct access to HTTP endpoints.
116
+ - [Development](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/development.md): tests, builds, and generated code.
117
+ - [Publishing](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/publishing.md): PyPI setup and release steps.
118
+
119
+ For offline analysis and bulk work without a running Holder installation, see
120
+ [Holder Kit](https://github.com/HolderTeam/holder/tree/827907ae32927e7c80fb9fe077bd1dc513f61763/python/kit).
@@ -0,0 +1,102 @@
1
+ # Holder for Python
2
+
3
+ Holder is an open-source, local-first knowledge app for organising your ideas
4
+ and digital information as index cards and the connections between them.
5
+
6
+ Use Python to read and update the projects and cards in your running Holder
7
+ installation. Changes you make in a script appear in Holder too.
8
+
9
+ ## Get started
10
+
11
+ 1. You need the Holder application on your computer.
12
+ Get it from https://www.holder.team/
13
+
14
+ 2. You need Python 3.11 or newer.
15
+ If in doubt, get the latest version (i.e. 3.15) from:
16
+ https://www.python.org/downloads/
17
+
18
+ 3. Install the Holder Python library with:
19
+
20
+ ```sh
21
+ python3 -m pip install holder-python
22
+ ```
23
+
24
+ Save this as `list_cards.py` and run it with `python3 list_cards.py`:
25
+
26
+ ```python
27
+ from holder import Holder
28
+
29
+ with Holder() as holder:
30
+ for project in holder.projects:
31
+ print(project.name)
32
+ for card in project.cards:
33
+ print(" ", card.title)
34
+ ```
35
+
36
+ `Holder()` finds or starts your local Holder daemon using `holderctl`. The
37
+ `with` block closes the Python connection when the script ends; it does not
38
+ stop Holder.
39
+
40
+ ## Create and edit cards
41
+
42
+ This example creates a project and two cards. Run it once: each run creates
43
+ another project named `Research`.
44
+
45
+ ```python
46
+ from holder import Holder
47
+
48
+ with Holder() as holder:
49
+ project = holder.projects.create(name="Research")
50
+ card = project.cards.create(title="An idea", content="My notes")
51
+ child = card.children.create(title="Next step")
52
+ child.update(content="Try it out")
53
+ card.tags.add("research")
54
+ ```
55
+
56
+ To work with an existing project, find it by name and get a card by its ID:
57
+
58
+ ```python
59
+ from holder import Holder
60
+
61
+ with Holder() as holder:
62
+ matches = holder.projects.filter(name="Research")
63
+ project = matches[0]
64
+ for card in project.cards:
65
+ print(card.id, card.title)
66
+
67
+ # Replace this with an ID printed above.
68
+ card = project.cards.get("card-id-here")
69
+ card.update(title="A better title")
70
+ ```
71
+
72
+ The name filter matches part of a name. If there are no matches, `[0]` raises
73
+ `IndexError`. Card content is available as `card.content`; use `card.update(...)`
74
+ to save edits. Card attributes cannot be assigned directly.
75
+
76
+ ## Find cards
77
+
78
+ Search within a project and inspect the matching text:
79
+
80
+ ```python
81
+ from holder import Holder
82
+
83
+ with Holder() as holder:
84
+ project = holder.projects.filter(name="Research")[0]
85
+ for result in project.cards.search("research notes"):
86
+ print(result.title, result.snippet)
87
+ ```
88
+
89
+ You can also list cards with a tag using
90
+ `project.cards.filter(tag="research")`, or list just top-level cards with
91
+ `project.cards.roots()`.
92
+
93
+ ## More help
94
+
95
+ - [More scripting tasks](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/scripting.md): moves, Trash, tags, collection
96
+ refreshes, and connecting to a specific daemon.
97
+ - [Low-level client](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/low-level-client.md): direct access to HTTP endpoints.
98
+ - [Development](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/development.md): tests, builds, and generated code.
99
+ - [Publishing](https://github.com/HolderTeam/holder/blob/827907ae32927e7c80fb9fe077bd1dc513f61763/python/holder/docs/publishing.md): PyPI setup and release steps.
100
+
101
+ For offline analysis and bulk work without a running Holder installation, see
102
+ [Holder Kit](https://github.com/HolderTeam/holder/tree/827907ae32927e7c80fb9fe077bd1dc513f61763/python/kit).
@@ -0,0 +1,62 @@
1
+ # Developing Holder for Python
2
+
3
+ Please refer to this package as Holder for Python or the Holder Python library,
4
+ or just Holder when the Python context is clear. Its scope is Holder
5
+ functionality using Python, independent of the current transport.
6
+
7
+ ## Set up a checkout
8
+
9
+ Requires Python 3.11 or newer. From `python/holder/` in the Holder repository:
10
+
11
+ ```sh
12
+ python3 -m venv .venv
13
+ source .venv/bin/activate
14
+ python -m pip install -e '.[dev]'
15
+ python -m pytest
16
+ python scripts/generate.py --check
17
+ python -m build
18
+ ```
19
+
20
+ The current implementation uses the daemon's HTTP API. The generated client
21
+ comes from [openapi-python-client](https://github.com/openapi-generators/openapi-python-client),
22
+ which is a development dependency. Installed clients need only HTTPX, attrs,
23
+ and typing-extensions. Entity and recovery policy belongs in the daemon or
24
+ core, not in this library.
25
+
26
+ ## Layout and regeneration
27
+
28
+ ```text
29
+ ../../api/openapi.yaml Owning HTTP contract for generation
30
+ openapi/ Generator config and contract/tool provenance
31
+ src/holder/generated/ Generated transport, endpoint modules and models
32
+ src/holder/events.py Handwritten incremental asyncio change-feed transport
33
+ scripts/generate.py Regeneration and comparison against checked-in code
34
+ tests/ Mock HTTP transport and contract coverage checks
35
+ ```
36
+
37
+ Do not hand-edit `src/holder/generated`. It is isolated so it can be replaced
38
+ if a different implementation is needed. Handwritten transport and higher-level
39
+ APIs live beside it; the incremental change-feed transport is in
40
+ `src/holder/events.py`.
41
+
42
+ Fix contract errors in the canonical [`api/openapi.yaml`](../../../api/openapi.yaml)
43
+ and test them with the daemon before regenerating the client. The generator
44
+ finds that contract from its own location, regardless of the caller's working
45
+ directory.
46
+
47
+ ```sh
48
+ # Regenerate from the owning contract.
49
+ python scripts/generate.py
50
+
51
+ # Compare the owning contract, provenance and generated output without changing files.
52
+ python scripts/generate.py --check
53
+ ```
54
+
55
+ The generator and Ruff versions are pinned in `pyproject.toml`. Generation runs
56
+ in a temporary directory and fails on warnings before replacing the package.
57
+ The provenance file records the contract's SHA-256 and tool versions. No schema
58
+ transformations or custom templates are used. The config treats YAML download
59
+ responses as plain text so their bodies are retained. CI checks the owning
60
+ contract against the generated client, runs tests and builds on Python 3.11
61
+ and 3.14. Installed packages contain the generated code and do not need the
62
+ repository contract.
@@ -0,0 +1,35 @@
1
+ # Low-level Holder client
2
+
3
+ The regular `Holder` API covers common scripting tasks. For direct access to
4
+ the daemon's HTTP endpoints, use `holder.generated`. Supply both the daemon URL
5
+ and bearer token explicitly; this client does not discover local connection
6
+ details or read credentials from your machine.
7
+
8
+ ```python
9
+ import os
10
+
11
+ from holder.generated import AuthenticatedClient
12
+ from holder.generated.api.default import get_health
13
+ from holder.generated.models import HealthResponse
14
+
15
+ with AuthenticatedClient(
16
+ base_url="http://127.0.0.1:11499",
17
+ token=os.environ["HOLDER_TOKEN"],
18
+ raise_on_unexpected_status=True,
19
+ ) as client:
20
+ response = get_health.sync_detailed(client=client)
21
+ if isinstance(response.parsed, HealthResponse):
22
+ print(response.parsed.data.server_version)
23
+ else:
24
+ print(response.status_code, response.parsed)
25
+ ```
26
+
27
+ `Client` supports public endpoints such as `get_ping`. Endpoint modules expose
28
+ `sync`, `sync_detailed`, `asyncio` and `asyncio_detailed`; use `async with` for
29
+ asynchronous clients. Detailed responses retain status, headers, raw bytes and
30
+ the parsed response. Documented HTTP errors return an `ErrorResponse` when the
31
+ contract specifies one; `raise_on_unexpected_status` applies to undocumented
32
+ statuses. Transport errors propagate from HTTPX.
33
+
34
+ This code is generated from the daemon's [OpenAPI contract](../../../api/openapi.yaml).
35
+ For regeneration and contribution instructions, see [development](development.md).
@@ -0,0 +1,79 @@
1
+ # Publishing Holder for Python
2
+
3
+ The distribution is `holder-python`; users import `holder`. It is a pure Python
4
+ package, so one `py3-none-any` wheel and one source archive cover all supported
5
+ platforms. The version follows the repository's root `VERSION`.
6
+
7
+ [`Release / Holder Python to PyPI`](../../../.github/workflows/release-holder-python-pypi.yml)
8
+ builds both files, checks their metadata, installs each in a fresh virtual
9
+ environment, and saves them as the `holder-python-distributions` artifact. A
10
+ pull request or a manual run with `destination=none` only builds. Publishing
11
+ uses Trusted Publishing. PyPI requires a manual run from the
12
+ `holder-v<version>` tag with a matching `python/holder/pyproject.toml` version.
13
+ The initial package-only `0.2.5` release also accepts
14
+ `holder-python-v0.2.5-r2`; this tag does not start a Holder-wide release.
15
+
16
+ ## One-time setup for each package index
17
+
18
+ PyPI and TestPyPI are separate services. Sign in to each one where you want to
19
+ publish and configure a **GitHub Actions Trusted Publisher** for the project
20
+ `holder-python`. If that project has not yet been created, use your account's
21
+ **Publishing** page to add a *pending publisher*. If it already belongs to you,
22
+ open the project's **Manage → Publishing** page and add a publisher there.
23
+ Use these values on both sites:
24
+
25
+ | Field | Value |
26
+ | --- | --- |
27
+ | PyPI project name (pending publisher only) | `holder-python` |
28
+ | GitHub owner | `HolderTeam` |
29
+ | GitHub repository | `holder` |
30
+ | Workflow filename | `release-holder-python-pypi.yml` |
31
+ | Environment name | `pypi` on PyPI; `testpypi` on TestPyPI |
32
+
33
+ The repository's GitHub environments must have those exact names. If they use
34
+ deployment branch or tag rules, allow `main`, `holder-v*`, and, for the
35
+ backfill, `holder-python-v0.2.5-r2`; add required reviewers if desired. The Kit
36
+ release workflow already uses these environment names, but **each PyPI project
37
+ needs its own Trusted Publisher entry**. No PyPI API token or GitHub secret is
38
+ needed. A pending publisher does not reserve the
39
+ project name until the first successful upload.
40
+
41
+ ## TestPyPI previews
42
+
43
+ TestPyPI already has `holder-python 0.2.5` from the original README. Uploaded
44
+ files cannot be replaced, even after deleting the project. Keep that project
45
+ and use a new preview number for each revised build:
46
+
47
+ 1. Merge the changes to `main`. In GitHub Actions, run **Release / Holder
48
+ Python to PyPI** on `main` with `destination=testpypi` and
49
+ `preview_number=1`. The build temporarily changes the package version to
50
+ `0.2.5.post1`; the committed `pyproject.toml` and root `VERSION` stay at
51
+ `0.2.5`.
52
+ 2. Wait for the TestPyPI upload and published-wheel install check to pass.
53
+ Review the `0.2.5.post1` page on TestPyPI.
54
+ 3. If the description needs another edit, merge that edit and repeat from
55
+ `main` with `preview_number=2`, then `3`, and so on. Each number creates
56
+ new wheel and source filenames. A preview number can only publish to
57
+ TestPyPI from `main`.
58
+
59
+ ## First `0.2.5` PyPI release
60
+
61
+ After accepting a preview, create `holder-python-v0.2.5-r2` on its reviewed
62
+ `main` commit. The original `holder-python-v0.2.5` tag points to the old README
63
+ and must not be moved. Run **Release / Holder Python to PyPI** from the new tag
64
+ with `destination=pypi` and `preview_number=0`. This publishes version `0.2.5`
65
+ with the corrected README to real PyPI, which has not received that version.
66
+ Confirm the project page and install it in a fresh environment with
67
+ `python -m pip install holder-python==0.2.5`.
68
+
69
+ ## Later releases
70
+
71
+ Update the unified version with `release/scripts/version.py <new-version>`, then
72
+ publish `holder-python` from the matching `holder-v<version>` tag as part of
73
+ the normal Holder release. The package-specific tag is accepted only for
74
+ `0.2.5`.
75
+
76
+ The workflow resolves README links to URLs at the build commit, so the project
77
+ description links back to that exact source. A failed upload does not make an
78
+ existing file replaceable: inspect the index before retrying, and choose a new
79
+ preview number if its files were already published.
@@ -0,0 +1,139 @@
1
+ # More Holder scripting tasks
2
+
3
+ Start with the [README](../README.md) for installation and a first script.
4
+ The examples below assume you have a `project` or `card` inside a
5
+ `with Holder() as holder:` block.
6
+
7
+ ## Create projects with options
8
+
9
+ ```python
10
+ from pathlib import Path
11
+
12
+ project = holder.projects.create(
13
+ name="Research",
14
+ root_path=Path("/path/to/my/project"),
15
+ privacy_mode="encrypted_git",
16
+ )
17
+ ```
18
+
19
+ The daemon chooses IDs, timestamps and card placement. You can omit
20
+ `root_path` and `privacy_mode`; the daemon then uses its defaults, including
21
+ encrypted Git for privacy. You can also choose `privacy_mode="plain"`.
22
+ Creation returns a fully loaded object. Filters on a collection do not supply
23
+ values when you create an object through it; `card.children.create(...)` does
24
+ supply the parent.
25
+
26
+ ## Work with tags
27
+
28
+ Tags belong to a project. Add and remove them on a card, or list cards sharing
29
+ a tag:
30
+
31
+ ```python
32
+ card.tags.add("research")
33
+ card.tags.remove("draft")
34
+ tag = project.tags.get("research")
35
+ for related_card in tag.cards:
36
+ print(related_card.title)
37
+ ```
38
+
39
+ The daemon validates and normalizes tag names. `project.tags.get(name)` uses
40
+ the normalized name. Removing a tag edits its trailing tag line; a mention in
41
+ the body stays until you edit the content. Project tags include `card_count`
42
+ and are ordered by descending count, then name.
43
+
44
+ ## Move, trash and restore cards
45
+
46
+ Supply exactly one target when moving a card:
47
+
48
+ ```python
49
+ card.move(parent=another_card) # append as a child
50
+ card.move(parent=None) # append at the project's top level
51
+ card.move(before=sibling)
52
+ card.move(after=sibling)
53
+ ```
54
+
55
+ Moving before or after another card adopts that card's parent. The daemon
56
+ checks project and hierarchy rules.
57
+
58
+ ```python
59
+ card.trash() # its live children move up a level
60
+ card.trash(children="trash_subtree") # its live descendants go to Trash too
61
+ card.restore() # restore this card alone
62
+ ```
63
+
64
+ When you restore a card, children that were moved up stay where they are.
65
+
66
+ ## Find and repair hidden cards
67
+
68
+ Older clients, manual file removal, or sync can leave cards under a missing or
69
+ trashed parent. Preview a repair before applying it:
70
+
71
+ ```python
72
+ repair = project.repair_hierarchy()
73
+ print(repair.moved)
74
+ repair = project.repair_hierarchy(apply=True)
75
+ ```
76
+
77
+ The daemon also repairs at startup and after every pull.
78
+
79
+ ## Search and filter
80
+
81
+ ```python
82
+ for result in project.cards.search("research notes"):
83
+ print(result.title, result.snippet)
84
+ print(result.card.content)
85
+ ```
86
+
87
+ Search results are ordered by relevance and loaded as you iterate. The
88
+ `result.card` property fetches and caches the current card on first access;
89
+ the snippet reflects the search result. Search collections support indexing,
90
+ `.all()` and `.refresh()`. Search uses the daemon's full-text syntax and cannot
91
+ be combined with tag or hierarchy filters, so search through `project.cards`.
92
+ For listing, use `project.cards.filter(tag="research")`,
93
+ `project.cards.roots()`, or `card.children`. Tag filters can be combined with
94
+ hierarchy queries. Card listings exclude trashed cards and are always scoped
95
+ to a project.
96
+
97
+ Project filters are `name` (substring), `updated_after`, and `updated_before`.
98
+ `get(id)` fetches an object directly. Collection indexes must be nonnegative.
99
+
100
+ ## Refresh data after changes
101
+
102
+ Collections load as you iterate and cache results they have visited. To see
103
+ changes made after a listing was loaded, call `.refresh()` on that collection:
104
+
105
+ ```python
106
+ cards = project.cards
107
+ for card in cards:
108
+ print(card.title)
109
+
110
+ project.cards.create(title="Another idea")
111
+ cards.refresh()
112
+ for card in cards:
113
+ print(card.title)
114
+ ```
115
+
116
+ `.all()` makes a fresh, independent query. Objects also have `.refresh()`.
117
+ Card bodies load when you read `card.content`. Explicit `.update(...)` writes
118
+ changes; card attributes cannot be assigned directly. Moves and tag changes
119
+ refresh the affected card, but other previously loaded listings still need `.refresh()`.
120
+ A move may also change nearby siblings' sort keys. Iteration observes live
121
+ data rather than a frozen snapshot.
122
+
123
+ ## Connect to a specific daemon
124
+
125
+ For a daemon you already know how to reach, supply both its URL and bearer
126
+ token:
127
+
128
+ ```python
129
+ import os
130
+
131
+ from holder import Holder
132
+
133
+ with Holder(url="http://127.0.0.1:11499", token=os.environ["HOLDER_TOKEN"]) as holder:
134
+ for project in holder.projects:
135
+ print(project.name)
136
+ ```
137
+
138
+ Connection and API failures raise exceptions from `holder.exceptions`.
139
+ For direct endpoint access, see the [low-level client](low-level-client.md).
@@ -0,0 +1,4 @@
1
+ package_name_override: generated
2
+ project_name_override: holder-python
3
+ content_type_overrides:
4
+ application/yaml: text/plain
@@ -0,0 +1,8 @@
1
+ {
2
+ "source": "api/openapi.yaml",
3
+ "sha256": "aee5268031b6aaa4b7a3d7a43340af312a6e6f145c75c32575debe4b36de260b",
4
+ "generator": {
5
+ "openapi-python-client": "0.29.1",
6
+ "ruff": "0.16.10"
7
+ }
8
+ }
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "holder-python"
7
+ version = "0.2.5"
8
+ description = "Control your knowledge using Python"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "GPL-3.0-only"
12
+ dependencies = ["httpx>=0.23.1,<0.29", "attrs>=22.2", "typing-extensions>=4.5"]
13
+
14
+ [project.urls]
15
+ Repository = "https://github.com/HolderTeam/holder/tree/main/python/holder"
16
+ Issues = "https://github.com/HolderTeam/holder/issues"
17
+
18
+ [project.optional-dependencies]
19
+ dev = [
20
+ "openapi-python-client==0.29.1",
21
+ "ruff==0.16.10",
22
+ "pytest>=8,<10",
23
+ "build>=1.2,<2",
24
+ ]
25
+
26
+ [tool.hatch.build.targets.wheel]
27
+ packages = ["src/holder"]
28
+
29
+ [tool.pytest.ini_options]
30
+ testpaths = ["tests"]
31
+
32
+ [tool.ruff]
33
+ target-version = "py311"