holder-python 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. holder/__init__.py +21 -0
  2. holder/client.py +182 -0
  3. holder/collections.py +70 -0
  4. holder/events.py +238 -0
  5. holder/exceptions.py +35 -0
  6. holder/generated/__init__.py +8 -0
  7. holder/generated/api/__init__.py +1 -0
  8. holder/generated/api/default/__init__.py +1 -0
  9. holder/generated/api/default/delete_ai_messages_message_id.py +166 -0
  10. holder/generated/api/default/delete_ai_messages_message_id_links.py +205 -0
  11. holder/generated/api/default/delete_ai_providers_credentials_provider.py +168 -0
  12. holder/generated/api/default/delete_ai_threads_thread_id.py +166 -0
  13. holder/generated/api/default/delete_cards_card_id.py +225 -0
  14. holder/generated/api/default/delete_cards_card_id_links.py +205 -0
  15. holder/generated/api/default/delete_cards_card_id_milestones_milestone_id.py +175 -0
  16. holder/generated/api/default/delete_cards_card_id_resources.py +197 -0
  17. holder/generated/api/default/delete_cards_card_id_tags.py +197 -0
  18. holder/generated/api/default/delete_locations_location_id.py +105 -0
  19. holder/generated/api/default/delete_locations_location_id_binding.py +102 -0
  20. holder/generated/api/default/delete_projects_project_id.py +187 -0
  21. holder/generated/api/default/delete_resources_resource_id.py +161 -0
  22. holder/generated/api/default/delete_trash.py +181 -0
  23. holder/generated/api/default/delete_trash_type_id.py +175 -0
  24. holder/generated/api/default/get_ai_capabilities.py +166 -0
  25. holder/generated/api/default/get_ai_catalog_json.py +134 -0
  26. holder/generated/api/default/get_ai_catalog_yaml.py +132 -0
  27. holder/generated/api/default/get_ai_local_models_config.py +134 -0
  28. holder/generated/api/default/get_ai_messages.py +186 -0
  29. holder/generated/api/default/get_ai_messages_message_id.py +166 -0
  30. holder/generated/api/default/get_ai_messages_message_id_backlinks.py +194 -0
  31. holder/generated/api/default/get_ai_messages_message_id_links.py +194 -0
  32. holder/generated/api/default/get_ai_providers_catalog.py +139 -0
  33. holder/generated/api/default/get_ai_providers_credentials.py +136 -0
  34. holder/generated/api/default/get_ai_runner_pull_job_id.py +171 -0
  35. holder/generated/api/default/get_ai_runner_pull_job_id_events.py +218 -0
  36. holder/generated/api/default/get_ai_runs.py +186 -0
  37. holder/generated/api/default/get_ai_runs_run_id.py +166 -0
  38. holder/generated/api/default/get_ai_runs_run_id_events.py +213 -0
  39. holder/generated/api/default/get_ai_status.py +134 -0
  40. holder/generated/api/default/get_ai_threads.py +171 -0
  41. holder/generated/api/default/get_ai_threads_thread_id.py +166 -0
  42. holder/generated/api/default/get_calendar.py +221 -0
  43. holder/generated/api/default/get_cards.py +286 -0
  44. holder/generated/api/default/get_cards_card_id.py +166 -0
  45. holder/generated/api/default/get_cards_card_id_backlinks.py +194 -0
  46. holder/generated/api/default/get_cards_card_id_links.py +194 -0
  47. holder/generated/api/default/get_cards_card_id_milestones.py +173 -0
  48. holder/generated/api/default/get_cards_context.py +226 -0
  49. holder/generated/api/default/get_event_cursor.py +198 -0
  50. holder/generated/api/default/get_git_providers_json.py +134 -0
  51. holder/generated/api/default/get_git_providers_yaml.py +132 -0
  52. holder/generated/api/default/get_health.py +134 -0
  53. holder/generated/api/default/get_imports_job_id.py +159 -0
  54. holder/generated/api/default/get_locations.py +160 -0
  55. holder/generated/api/default/get_locations_location_id.py +157 -0
  56. holder/generated/api/default/get_openapi_yaml.py +132 -0
  57. holder/generated/api/default/get_ping.py +128 -0
  58. holder/generated/api/default/get_projects.py +261 -0
  59. holder/generated/api/default/get_projects_project_id.py +166 -0
  60. holder/generated/api/default/get_projects_project_id_cards.py +321 -0
  61. holder/generated/api/default/get_projects_project_id_encryption_check.py +166 -0
  62. holder/generated/api/default/get_projects_project_id_git_sync_status.py +171 -0
  63. holder/generated/api/default/get_projects_project_id_history.py +246 -0
  64. holder/generated/api/default/get_projects_project_id_history_cards_card_id.py +243 -0
  65. holder/generated/api/default/get_projects_project_id_history_cards_card_id_compare.py +286 -0
  66. holder/generated/api/default/get_projects_project_id_history_cards_card_id_snapshot.py +225 -0
  67. holder/generated/api/default/get_projects_project_id_tags.py +171 -0
  68. holder/generated/api/default/get_resources.py +242 -0
  69. holder/generated/api/default/get_resources_resource_id.py +161 -0
  70. holder/generated/api/default/get_resources_resource_id_assets_asset_id_content.py +247 -0
  71. holder/generated/api/default/get_search_ai.py +216 -0
  72. holder/generated/api/default/get_search_cards.py +216 -0
  73. holder/generated/api/default/get_trash.py +181 -0
  74. holder/generated/api/default/patch_ai_messages_message_id.py +192 -0
  75. holder/generated/api/default/patch_ai_threads_thread_id.py +192 -0
  76. holder/generated/api/default/patch_cards_card_id.py +192 -0
  77. holder/generated/api/default/patch_cards_card_id_milestones_milestone_id.py +214 -0
  78. holder/generated/api/default/patch_locations_location_id.py +117 -0
  79. holder/generated/api/default/patch_projects_project_id.py +192 -0
  80. holder/generated/api/default/patch_resources_resource_id.py +192 -0
  81. holder/generated/api/default/post_ai_messages.py +176 -0
  82. holder/generated/api/default/post_ai_messages_capture.py +181 -0
  83. holder/generated/api/default/post_ai_messages_message_id_links.py +192 -0
  84. holder/generated/api/default/post_ai_messages_message_id_restore.py +166 -0
  85. holder/generated/api/default/post_ai_runner_pull.py +181 -0
  86. holder/generated/api/default/post_ai_runner_retry.py +139 -0
  87. holder/generated/api/default/post_ai_runs.py +194 -0
  88. holder/generated/api/default/post_ai_threads.py +176 -0
  89. holder/generated/api/default/post_bye.py +166 -0
  90. holder/generated/api/default/post_card_references_resolve.py +181 -0
  91. holder/generated/api/default/post_cards.py +176 -0
  92. holder/generated/api/default/post_cards_card_id_links.py +192 -0
  93. holder/generated/api/default/post_cards_card_id_milestones.py +199 -0
  94. holder/generated/api/default/post_cards_card_id_move.py +222 -0
  95. holder/generated/api/default/post_cards_card_id_resources.py +197 -0
  96. holder/generated/api/default/post_cards_card_id_restore.py +186 -0
  97. holder/generated/api/default/post_cards_card_id_tags.py +197 -0
  98. holder/generated/api/default/post_imports.py +160 -0
  99. holder/generated/api/default/post_locations.py +160 -0
  100. holder/generated/api/default/post_locations_location_id_test.py +105 -0
  101. holder/generated/api/default/post_projects.py +171 -0
  102. holder/generated/api/default/post_projects_project_id_git_pull.py +211 -0
  103. holder/generated/api/default/post_projects_project_id_git_push.py +193 -0
  104. holder/generated/api/default/post_projects_project_id_git_sync.py +207 -0
  105. holder/generated/api/default/post_projects_project_id_git_test_remote.py +205 -0
  106. holder/generated/api/default/post_projects_project_id_history_cards_card_id_restore.py +240 -0
  107. holder/generated/api/default/post_projects_project_id_recovery_token_export.py +196 -0
  108. holder/generated/api/default/post_projects_project_id_recovery_token_import.py +196 -0
  109. holder/generated/api/default/post_projects_project_id_repair_hierarchy.py +240 -0
  110. holder/generated/api/default/post_rebuild.py +176 -0
  111. holder/generated/api/default/post_recovery_token_import.py +185 -0
  112. holder/generated/api/default/post_reindex.py +139 -0
  113. holder/generated/api/default/post_resources.py +176 -0
  114. holder/generated/api/default/put_ai_local_models_config.py +173 -0
  115. holder/generated/api/default/put_ai_providers_credentials.py +175 -0
  116. holder/generated/api/default/put_locations_location_id_binding.py +117 -0
  117. holder/generated/api/default/put_locations_preferred.py +107 -0
  118. holder/generated/api/default/stream_changes.py +256 -0
  119. holder/generated/client.py +280 -0
  120. holder/generated/errors.py +16 -0
  121. holder/generated/models/__init__.py +569 -0
  122. holder/generated/models/ai_local_model_config_data.py +111 -0
  123. holder/generated/models/ai_local_model_config_response.py +78 -0
  124. holder/generated/models/ai_local_model_config_update_request.py +134 -0
  125. holder/generated/models/ai_message.py +204 -0
  126. holder/generated/models/ai_message_capture_request.py +246 -0
  127. holder/generated/models/ai_message_capture_request_context_type_0.py +46 -0
  128. holder/generated/models/ai_message_capture_response.py +78 -0
  129. holder/generated/models/ai_message_capture_response_data.py +78 -0
  130. holder/generated/models/ai_message_create_request.py +186 -0
  131. holder/generated/models/ai_message_create_response.py +78 -0
  132. holder/generated/models/ai_message_create_response_data.py +62 -0
  133. holder/generated/models/ai_message_get_response.py +76 -0
  134. holder/generated/models/ai_message_list_response.py +84 -0
  135. holder/generated/models/ai_message_update_request.py +203 -0
  136. holder/generated/models/ai_message_update_response.py +78 -0
  137. holder/generated/models/ai_message_update_response_data.py +62 -0
  138. holder/generated/models/ai_provider_catalog_provider.py +265 -0
  139. holder/generated/models/ai_provider_catalog_provider_api_type_0.py +46 -0
  140. holder/generated/models/ai_provider_catalog_provider_auth_type_0.py +46 -0
  141. holder/generated/models/ai_provider_catalog_provider_models_item.py +46 -0
  142. holder/generated/models/ai_provider_catalog_response.py +78 -0
  143. holder/generated/models/ai_provider_catalog_response_data.py +100 -0
  144. holder/generated/models/ai_provider_credential.py +94 -0
  145. holder/generated/models/ai_provider_credential_delete_response.py +80 -0
  146. holder/generated/models/ai_provider_credential_delete_response_data.py +62 -0
  147. holder/generated/models/ai_provider_credential_upsert_request.py +92 -0
  148. holder/generated/models/ai_provider_credential_upsert_response.py +78 -0
  149. holder/generated/models/ai_provider_credentials_list_response.py +80 -0
  150. holder/generated/models/ai_provider_credentials_list_response_data.py +78 -0
  151. holder/generated/models/ai_run_create_request.py +133 -0
  152. holder/generated/models/ai_run_create_request_context.py +46 -0
  153. holder/generated/models/ai_run_event_data.py +146 -0
  154. holder/generated/models/ai_run_get_response.py +76 -0
  155. holder/generated/models/ai_run_item.py +328 -0
  156. holder/generated/models/ai_run_item_policy_trace_type_0.py +46 -0
  157. holder/generated/models/ai_run_list_response.py +84 -0
  158. holder/generated/models/ai_status_data.py +186 -0
  159. holder/generated/models/ai_status_pull_job.py +130 -0
  160. holder/generated/models/ai_status_response.py +76 -0
  161. holder/generated/models/ai_thread.py +116 -0
  162. holder/generated/models/ai_thread_create_request.py +119 -0
  163. holder/generated/models/ai_thread_create_response.py +78 -0
  164. holder/generated/models/ai_thread_create_response_data.py +62 -0
  165. holder/generated/models/ai_thread_get_response.py +76 -0
  166. holder/generated/models/ai_thread_list_response.py +84 -0
  167. holder/generated/models/ai_thread_patch_response.py +78 -0
  168. holder/generated/models/ai_thread_patch_response_data.py +62 -0
  169. holder/generated/models/ai_thread_update_request.py +104 -0
  170. holder/generated/models/asset_import_job.py +141 -0
  171. holder/generated/models/asset_import_job_response.py +76 -0
  172. holder/generated/models/asset_import_job_status.py +13 -0
  173. holder/generated/models/asset_import_request.py +86 -0
  174. holder/generated/models/asset_placement.py +96 -0
  175. holder/generated/models/asset_placement_encoding.py +9 -0
  176. holder/generated/models/bye_response.py +62 -0
  177. holder/generated/models/calendar_card_activity.py +86 -0
  178. holder/generated/models/card_context_breadcrumb.py +113 -0
  179. holder/generated/models/card_context_breadcrumb_type.py +9 -0
  180. holder/generated/models/card_context_card.py +161 -0
  181. holder/generated/models/card_context_data.py +124 -0
  182. holder/generated/models/card_context_data_project.py +70 -0
  183. holder/generated/models/card_context_response.py +76 -0
  184. holder/generated/models/card_create_request.py +147 -0
  185. holder/generated/models/card_create_response.py +78 -0
  186. holder/generated/models/card_create_response_data.py +70 -0
  187. holder/generated/models/card_data.py +160 -0
  188. holder/generated/models/card_get_response.py +76 -0
  189. holder/generated/models/card_history_author.py +70 -0
  190. holder/generated/models/card_history_comparison_data.py +110 -0
  191. holder/generated/models/card_history_comparison_response.py +78 -0
  192. holder/generated/models/card_history_diff_line.py +100 -0
  193. holder/generated/models/card_history_diff_line_origin.py +10 -0
  194. holder/generated/models/card_history_entry.py +172 -0
  195. holder/generated/models/card_history_entry_kind.py +16 -0
  196. holder/generated/models/card_history_entry_saves_item.py +94 -0
  197. holder/generated/models/card_history_page_data.py +114 -0
  198. holder/generated/models/card_history_page_response.py +76 -0
  199. holder/generated/models/card_history_restore_response.py +80 -0
  200. holder/generated/models/card_history_restore_response_data.py +108 -0
  201. holder/generated/models/card_history_snapshot_response.py +80 -0
  202. holder/generated/models/card_history_snapshot_response_data.py +76 -0
  203. holder/generated/models/card_history_version.py +86 -0
  204. holder/generated/models/card_link.py +116 -0
  205. holder/generated/models/card_link_create_request.py +111 -0
  206. holder/generated/models/card_link_create_response.py +76 -0
  207. holder/generated/models/card_link_delete_request.py +80 -0
  208. holder/generated/models/card_link_list_response.py +84 -0
  209. holder/generated/models/card_list_item.py +161 -0
  210. holder/generated/models/card_list_response.py +84 -0
  211. holder/generated/models/card_move_intent.py +15 -0
  212. holder/generated/models/card_move_request.py +134 -0
  213. holder/generated/models/card_move_response.py +76 -0
  214. holder/generated/models/card_move_result.py +114 -0
  215. holder/generated/models/card_page.py +90 -0
  216. holder/generated/models/card_page_item.py +170 -0
  217. holder/generated/models/card_page_response.py +76 -0
  218. holder/generated/models/card_patch_response.py +78 -0
  219. holder/generated/models/card_patch_response_data.py +62 -0
  220. holder/generated/models/card_reference_candidate.py +84 -0
  221. holder/generated/models/card_reference_resolve_data.py +129 -0
  222. holder/generated/models/card_reference_resolve_data_match_kind.py +10 -0
  223. holder/generated/models/card_reference_resolve_data_status.py +10 -0
  224. holder/generated/models/card_reference_resolve_request.py +82 -0
  225. holder/generated/models/card_reference_resolve_request_scope.py +10 -0
  226. holder/generated/models/card_reference_resolve_response.py +78 -0
  227. holder/generated/models/card_tag_mutation_request.py +70 -0
  228. holder/generated/models/card_tag_mutation_response.py +78 -0
  229. holder/generated/models/card_tag_mutation_result.py +88 -0
  230. holder/generated/models/card_tag_mutation_result_outcome.py +12 -0
  231. holder/generated/models/card_update_request.py +122 -0
  232. holder/generated/models/caste_info.py +85 -0
  233. holder/generated/models/caste_info_name.py +12 -0
  234. holder/generated/models/caste_recommended_model.py +143 -0
  235. holder/generated/models/caste_recommended_model_required_caste.py +12 -0
  236. holder/generated/models/change_event_data.py +109 -0
  237. holder/generated/models/change_event_data_entity.py +14 -0
  238. holder/generated/models/delete_cards_card_id_children.py +9 -0
  239. holder/generated/models/delete_cards_card_id_resources_body.py +70 -0
  240. holder/generated/models/error.py +70 -0
  241. holder/generated/models/error_response.py +76 -0
  242. holder/generated/models/event_checkpoint.py +92 -0
  243. holder/generated/models/event_checkpoint_git_revisions.py +66 -0
  244. holder/generated/models/event_checkpoint_history_urls.py +48 -0
  245. holder/generated/models/event_checkpoint_response.py +76 -0
  246. holder/generated/models/event_resync_data.py +116 -0
  247. holder/generated/models/event_resync_data_reason.py +9 -0
  248. holder/generated/models/get_ai_catalog_json_response_200.py +46 -0
  249. holder/generated/models/get_ai_messages_message_id_backlinks_include_deleted.py +9 -0
  250. holder/generated/models/get_ai_messages_message_id_links_include_deleted.py +9 -0
  251. holder/generated/models/get_cards_card_id_backlinks_include_deleted.py +9 -0
  252. holder/generated/models/get_cards_card_id_links_include_deleted.py +9 -0
  253. holder/generated/models/get_cards_context_order.py +10 -0
  254. holder/generated/models/get_cards_order.py +10 -0
  255. holder/generated/models/get_cards_view.py +9 -0
  256. holder/generated/models/get_git_providers_json_response_200.py +46 -0
  257. holder/generated/models/get_locations_location_id_response_200.py +46 -0
  258. holder/generated/models/get_ping_response_200.py +8 -0
  259. holder/generated/models/get_projects_order.py +13 -0
  260. holder/generated/models/get_projects_project_id_cards_order.py +9 -0
  261. holder/generated/models/get_projects_project_id_cards_parent_type_0.py +8 -0
  262. holder/generated/models/get_projects_project_id_history_cards_card_id_compare_mode.py +9 -0
  263. holder/generated/models/get_projects_project_id_history_kind.py +13 -0
  264. holder/generated/models/health_data.py +110 -0
  265. holder/generated/models/health_data_crypt_filter.py +78 -0
  266. holder/generated/models/health_response.py +76 -0
  267. holder/generated/models/hierarchy_repair.py +100 -0
  268. holder/generated/models/hierarchy_repair_move.py +76 -0
  269. holder/generated/models/hierarchy_repair_request.py +62 -0
  270. holder/generated/models/hierarchy_repair_response.py +76 -0
  271. holder/generated/models/local_model.py +91 -0
  272. holder/generated/models/location_binding_request.py +81 -0
  273. holder/generated/models/location_binding_request_values.py +46 -0
  274. holder/generated/models/milestone.py +177 -0
  275. holder/generated/models/milestone_create_request.py +135 -0
  276. holder/generated/models/milestone_list_response.py +84 -0
  277. holder/generated/models/milestone_remove_response.py +78 -0
  278. holder/generated/models/milestone_remove_result.py +79 -0
  279. holder/generated/models/milestone_response.py +76 -0
  280. holder/generated/models/milestone_update_request.py +116 -0
  281. holder/generated/models/patch_locations_location_id_body.py +90 -0
  282. holder/generated/models/patch_locations_location_id_body_configuration.py +46 -0
  283. holder/generated/models/post_ai_runner_pull_body.py +62 -0
  284. holder/generated/models/post_cards_card_id_resources_body.py +70 -0
  285. holder/generated/models/post_locations_response_201.py +46 -0
  286. holder/generated/models/project.py +197 -0
  287. holder/generated/models/project_calendar_response.py +78 -0
  288. holder/generated/models/project_calendar_response_data.py +136 -0
  289. holder/generated/models/project_create_request.py +177 -0
  290. holder/generated/models/project_create_request_privacy_mode.py +9 -0
  291. holder/generated/models/project_create_response.py +78 -0
  292. holder/generated/models/project_create_response_data.py +62 -0
  293. holder/generated/models/project_delete_response.py +78 -0
  294. holder/generated/models/project_delete_response_data.py +62 -0
  295. holder/generated/models/project_encryption_check.py +94 -0
  296. holder/generated/models/project_encryption_check_response.py +80 -0
  297. holder/generated/models/project_encryption_check_response_data.py +92 -0
  298. holder/generated/models/project_encryption_check_response_data_privacy_mode.py +9 -0
  299. holder/generated/models/project_get_response.py +76 -0
  300. holder/generated/models/project_git_push_request.py +95 -0
  301. holder/generated/models/project_git_push_response.py +78 -0
  302. holder/generated/models/project_git_push_response_data.py +199 -0
  303. holder/generated/models/project_git_push_response_data_status.py +15 -0
  304. holder/generated/models/project_git_sync_operation_response.py +80 -0
  305. holder/generated/models/project_git_sync_operation_response_data.py +163 -0
  306. holder/generated/models/project_git_sync_operation_response_data_pull.py +96 -0
  307. holder/generated/models/project_git_sync_operation_response_data_pull_status.py +11 -0
  308. holder/generated/models/project_git_sync_operation_response_data_push.py +118 -0
  309. holder/generated/models/project_git_sync_operation_response_data_push_status.py +15 -0
  310. holder/generated/models/project_git_sync_operation_response_data_status.py +9 -0
  311. holder/generated/models/project_git_sync_request.py +94 -0
  312. holder/generated/models/project_git_sync_status_response.py +80 -0
  313. holder/generated/models/project_git_sync_status_response_data.py +76 -0
  314. holder/generated/models/project_git_test_remote_request.py +96 -0
  315. holder/generated/models/project_git_test_remote_response.py +80 -0
  316. holder/generated/models/project_git_test_remote_response_data.py +151 -0
  317. holder/generated/models/project_git_test_remote_response_data_status.py +14 -0
  318. holder/generated/models/project_history_activity.py +138 -0
  319. holder/generated/models/project_history_affected_object.py +74 -0
  320. holder/generated/models/project_history_affected_object_kind.py +13 -0
  321. holder/generated/models/project_history_page_data.py +115 -0
  322. holder/generated/models/project_history_page_response.py +78 -0
  323. holder/generated/models/project_list_response.py +84 -0
  324. holder/generated/models/project_privacy_mode.py +9 -0
  325. holder/generated/models/project_recovery_token_export_request.py +62 -0
  326. holder/generated/models/project_recovery_token_export_response.py +80 -0
  327. holder/generated/models/project_recovery_token_export_response_data.py +78 -0
  328. holder/generated/models/project_recovery_token_import_request.py +70 -0
  329. holder/generated/models/project_recovery_token_import_response.py +80 -0
  330. holder/generated/models/project_recovery_token_import_response_data.py +62 -0
  331. holder/generated/models/project_sync.py +227 -0
  332. holder/generated/models/project_tag.py +70 -0
  333. holder/generated/models/project_tag_list_response.py +84 -0
  334. holder/generated/models/project_update_request.py +181 -0
  335. holder/generated/models/project_update_request_privacy_mode.py +9 -0
  336. holder/generated/models/project_update_response.py +78 -0
  337. holder/generated/models/project_update_response_data.py +75 -0
  338. holder/generated/models/put_locations_preferred_body.py +70 -0
  339. holder/generated/models/rebuild_data.py +94 -0
  340. holder/generated/models/rebuild_request.py +62 -0
  341. holder/generated/models/rebuild_response.py +76 -0
  342. holder/generated/models/recovery_token_import_auto_response.py +80 -0
  343. holder/generated/models/recovery_token_import_auto_response_data.py +141 -0
  344. holder/generated/models/recovery_token_import_auto_response_data_pull_status.py +10 -0
  345. holder/generated/models/reindex_data.py +62 -0
  346. holder/generated/models/reindex_response.py +76 -0
  347. holder/generated/models/resource.py +134 -0
  348. holder/generated/models/resource_asset.py +140 -0
  349. holder/generated/models/resource_attachment_response.py +80 -0
  350. holder/generated/models/resource_attachment_response_data.py +90 -0
  351. holder/generated/models/resource_attachment_response_data_outcome.py +11 -0
  352. holder/generated/models/resource_create_request.py +129 -0
  353. holder/generated/models/resource_delete_response.py +78 -0
  354. holder/generated/models/resource_delete_response_data.py +62 -0
  355. holder/generated/models/resource_list_response.py +134 -0
  356. holder/generated/models/resource_metadata.py +55 -0
  357. holder/generated/models/resource_response.py +76 -0
  358. holder/generated/models/resource_update_request.py +102 -0
  359. holder/generated/models/runner_capabilities_data.py +220 -0
  360. holder/generated/models/runner_capabilities_response.py +78 -0
  361. holder/generated/models/runner_pull_job.py +122 -0
  362. holder/generated/models/runner_pull_progress.py +86 -0
  363. holder/generated/models/runner_pull_start_response.py +78 -0
  364. holder/generated/models/runner_pull_start_response_data.py +78 -0
  365. holder/generated/models/runner_pull_status_response.py +76 -0
  366. holder/generated/models/search_card_item.py +102 -0
  367. holder/generated/models/search_cards_response.py +84 -0
  368. holder/generated/models/search_message_item.py +86 -0
  369. holder/generated/models/search_messages_response.py +84 -0
  370. holder/generated/models/storage_location.py +149 -0
  371. holder/generated/models/storage_location_configuration.py +48 -0
  372. holder/generated/models/storage_location_list_response.py +100 -0
  373. holder/generated/models/storage_location_provider.py +9 -0
  374. holder/generated/models/storage_location_request.py +118 -0
  375. holder/generated/models/storage_location_request_configuration.py +46 -0
  376. holder/generated/models/storage_location_request_provider.py +9 -0
  377. holder/generated/models/trash_delete_response.py +78 -0
  378. holder/generated/models/trash_delete_response_data.py +46 -0
  379. holder/generated/models/trash_item.py +211 -0
  380. holder/generated/models/trash_list_response.py +84 -0
  381. holder/generated/types.py +54 -0
  382. holder/library.py +15 -0
  383. holder/models/__init__.py +15 -0
  384. holder/models/card.py +272 -0
  385. holder/models/project.py +207 -0
  386. holder/models/search.py +66 -0
  387. holder/models/tag.py +117 -0
  388. holder/py.typed +0 -0
  389. holder_python-0.2.5.dist-info/METADATA +120 -0
  390. holder_python-0.2.5.dist-info/RECORD +391 -0
  391. holder_python-0.2.5.dist-info/WHEEL +4 -0
@@ -0,0 +1,207 @@
1
+ """Projects and their synchronous collection queries."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import time
7
+ from dataclasses import dataclass, field, fields
8
+ from functools import cached_property
9
+ from typing import TYPE_CHECKING, Any, Literal, Self, cast
10
+
11
+ from ..collections import Collection
12
+ from ..generated.api.default import (
13
+ get_projects,
14
+ get_projects_project_id,
15
+ patch_projects_project_id,
16
+ post_projects,
17
+ post_projects_project_id_repair_hierarchy,
18
+ )
19
+ from ..generated.models import (
20
+ HierarchyRepairRequest,
21
+ ProjectCreateRequest,
22
+ ProjectCreateRequestPrivacyMode,
23
+ ProjectPrivacyMode,
24
+ ProjectSync,
25
+ ProjectUpdateRequest,
26
+ )
27
+ from ..generated.types import UNSET, Unset
28
+ from .card import CardCollection
29
+ from .tag import TagCollection
30
+
31
+ if TYPE_CHECKING:
32
+ from ..client import Holder
33
+
34
+
35
+ class ProjectCollection(Collection["Project"]):
36
+ def create(
37
+ self,
38
+ *,
39
+ name: str,
40
+ root_path: str | os.PathLike[str] | Unset = UNSET,
41
+ privacy_mode: Literal["encrypted_git", "plain"] | Unset = UNSET,
42
+ ) -> Project:
43
+ """Create a project using daemon defaults for omitted settings.
44
+
45
+ Listing filters do not supply creation values. Cached listings remain
46
+ unchanged until refreshed. The write is never retried; if the subsequent
47
+ fetch fails, the project may already exist.
48
+ """
49
+ if not isinstance(name, str):
50
+ raise TypeError("name must be a string")
51
+ if not isinstance(root_path, Unset):
52
+ root_path = os.fspath(root_path)
53
+ if not isinstance(root_path, str):
54
+ raise TypeError("root_path must be a string or a text path")
55
+ mode = (
56
+ UNSET
57
+ if isinstance(privacy_mode, Unset)
58
+ else ProjectCreateRequestPrivacyMode(privacy_mode)
59
+ )
60
+ data = self._holder._call(
61
+ post_projects,
62
+ body=ProjectCreateRequest(
63
+ name=name, root_path=root_path, privacy_mode=mode
64
+ ),
65
+ write=True,
66
+ )
67
+ return self.get(data.project_id)
68
+
69
+ def _clone(self, query: dict[str, Any]) -> Self:
70
+ return type(self)(self._holder, query)
71
+
72
+ def filter(
73
+ self,
74
+ *,
75
+ name: str | Unset = UNSET,
76
+ updated_after: int | Unset = UNSET,
77
+ updated_before: int | Unset = UNSET,
78
+ ) -> Self:
79
+ values = {
80
+ key: value
81
+ for key, value in {
82
+ "name": name,
83
+ "updated_after": updated_after,
84
+ "updated_before": updated_before,
85
+ }.items()
86
+ if not isinstance(value, Unset)
87
+ }
88
+ if "name" in values and not isinstance(name, str):
89
+ raise TypeError("name must be a string")
90
+ for key in ("updated_after", "updated_before"):
91
+ if key in values and (
92
+ not isinstance(values[key], int) or isinstance(values[key], bool)
93
+ ):
94
+ raise TypeError(f"{key} must be an integer")
95
+ return self._clone({**self._query, **values})
96
+
97
+ def _fetch_page(self) -> tuple[list[Project], int | None]:
98
+ offset = cast(int, self._next or 0)
99
+ data = self._holder._call(get_projects, limit=100, offset=offset, **self._query)
100
+ rows = [Project._from(self._holder, item) for item in data]
101
+ next_offset = offset + len(data) if len(data) == 100 else None
102
+ return rows, next_offset
103
+
104
+ def get(self, project_id: str) -> Project:
105
+ project = Project._from(
106
+ self._holder, self._holder._call(get_projects_project_id, project_id)
107
+ )
108
+ # get(id) is a direct scoped lookup, not evaluation of a filtered listing.
109
+ return project
110
+
111
+
112
+ @dataclass(frozen=True)
113
+ class RepairedCard:
114
+ """A hidden branch's top card and where repair moves it (None: top level)."""
115
+
116
+ card_id: str
117
+ parent_card_id: str | None
118
+
119
+
120
+ @dataclass(frozen=True)
121
+ class HierarchyRepair:
122
+ """Cards hidden under missing or trashed parents, and what repair does."""
123
+
124
+ applied: bool
125
+ moved: list[RepairedCard]
126
+ changed_card_count: int
127
+ cycle_card_ids: list[str]
128
+
129
+
130
+ @dataclass(frozen=True, eq=False)
131
+ class Project:
132
+ project_id: str
133
+ name: str
134
+ root_path: str
135
+ privacy_mode: ProjectPrivacyMode
136
+ created_at: int
137
+ updated_at: int
138
+ sync: ProjectSync
139
+ git_remote_url: str | None
140
+ git_provider: str | None
141
+ project_key_id: str | None
142
+ card_count: int | None
143
+ root_card_count: int | None
144
+ _holder: Holder = field(repr=False, compare=False)
145
+
146
+ @property
147
+ def id(self) -> str:
148
+ return self.project_id
149
+
150
+ @cached_property
151
+ def cards(self) -> CardCollection:
152
+ return CardCollection(self)
153
+
154
+ @cached_property
155
+ def tags(self) -> TagCollection:
156
+ return TagCollection(self)
157
+
158
+ @classmethod
159
+ def _from(cls, holder: Holder, data: Any) -> Self:
160
+ values: dict[str, Any] = {}
161
+ for f in fields(cls):
162
+ if f.name != "_holder":
163
+ value = getattr(data, f.name, None)
164
+ values[f.name] = None if isinstance(value, Unset) else value
165
+ return cls(**values, _holder=holder)
166
+
167
+ def refresh(self) -> Self:
168
+ fresh = self._holder.projects.get(self.id)
169
+ for f in fields(self):
170
+ if f.name != "_holder":
171
+ object.__setattr__(self, f.name, getattr(fresh, f.name))
172
+ return self
173
+
174
+ def update(self, *, name: str) -> Self:
175
+ """Rename this project and refresh its server metadata."""
176
+ if not isinstance(name, str):
177
+ raise TypeError("name must be a string")
178
+ self._holder._call(
179
+ patch_projects_project_id,
180
+ self.id,
181
+ body=ProjectUpdateRequest(updated_at=int(time.time()), name=name),
182
+ write=True,
183
+ )
184
+ return self.refresh()
185
+
186
+ def repair_hierarchy(self, *, apply: bool = False) -> HierarchyRepair:
187
+ """Find, and with apply=True fix, cards hidden under missing or trashed parents.
188
+
189
+ Each hidden branch moves to its nearest live ancestor (or the top level)
190
+ with its descendants, in one commit. Cards in parent cycles are only
191
+ reported. The daemon also repairs at startup, and every pull repairs
192
+ what it brings in. Cached listings need an explicit refresh.
193
+ """
194
+ if not isinstance(apply, bool):
195
+ raise TypeError("apply must be a bool")
196
+ data = self._holder._call(
197
+ post_projects_project_id_repair_hierarchy,
198
+ self.id,
199
+ body=HierarchyRepairRequest(apply=apply),
200
+ write=apply,
201
+ )
202
+ return HierarchyRepair(
203
+ applied=data.applied,
204
+ moved=[RepairedCard(m.card_id, m.parent_card_id) for m in data.moved],
205
+ changed_card_count=data.changed_card_count,
206
+ cycle_card_ids=list(data.cycle_card_ids),
207
+ )
@@ -0,0 +1,66 @@
1
+ """Project-scoped card search results and lazy pagination."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from functools import cached_property
7
+ from typing import TYPE_CHECKING, Any, Self, cast
8
+
9
+ from ..collections import Collection
10
+ from ..generated.api.default import get_search_cards
11
+
12
+ if TYPE_CHECKING:
13
+ from .card import Card
14
+ from .project import Project
15
+
16
+
17
+ class CardSearchCollection(Collection["CardSearchResult"]):
18
+ """Lazy relevance-ordered results, with the usual all/refresh/index behavior."""
19
+
20
+ def __init__(self, project: Project, query: str) -> None:
21
+ self._project = project
22
+ super().__init__(project._holder, {"q": query})
23
+
24
+ def _clone(self, query: dict[str, Any]) -> Self:
25
+ return type(self)(self._project, query["q"])
26
+
27
+ def _fetch_page(self) -> tuple[list[CardSearchResult], int | None]:
28
+ offset = cast(int, self._next or 0)
29
+ data = self._holder._call(
30
+ get_search_cards,
31
+ project_id=self._project.id,
32
+ q=self._query["q"],
33
+ limit=100,
34
+ offset=offset,
35
+ )
36
+ rows = [CardSearchResult._from(self._project, item) for item in data]
37
+ return rows, offset + len(rows) if len(rows) == 100 else None
38
+
39
+
40
+ @dataclass(frozen=True, eq=False)
41
+ class CardSearchResult:
42
+ """Search metadata from one query, with lazy access to the current card."""
43
+
44
+ card_id: str
45
+ title: str
46
+ created_at: int
47
+ updated_at: int
48
+ snippet: str
49
+ rank: float
50
+ _project: Project = field(repr=False, compare=False)
51
+
52
+ @cached_property
53
+ def card(self) -> Card:
54
+ return self._project.cards.get(self.card_id)
55
+
56
+ @classmethod
57
+ def _from(cls, project: Project, data: Any) -> Self:
58
+ return cls(
59
+ card_id=data.card_id,
60
+ title=data.title,
61
+ created_at=data.created_at,
62
+ updated_at=data.updated_at,
63
+ snippet=data.snippet,
64
+ rank=data.rank,
65
+ _project=project,
66
+ )
holder/models/tag.py ADDED
@@ -0,0 +1,117 @@
1
+ """Project-scoped tags and their synchronous collections."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from functools import cached_property
7
+ from typing import TYPE_CHECKING, Any, Self
8
+
9
+ from ..collections import Collection
10
+ from ..exceptions import NotFoundError, ProtocolError
11
+ from ..generated.api.default import (
12
+ delete_cards_card_id_tags,
13
+ get_cards_card_id,
14
+ get_projects_project_id_tags,
15
+ post_cards_card_id_tags,
16
+ )
17
+ from ..generated.models import CardTagMutationRequest
18
+
19
+ if TYPE_CHECKING:
20
+ from .card import Card, CardCollection
21
+ from .project import Project
22
+
23
+
24
+ class TagCollection(Collection["Tag"]):
25
+ """Lazy project tags, ordered by usage count and then name."""
26
+
27
+ def __init__(self, project: Project) -> None:
28
+ self._project = project
29
+ super().__init__(project._holder)
30
+
31
+ def _clone(self, query: dict[str, Any]) -> Self:
32
+ return type(self)(self._project)
33
+
34
+ def _fetch_page(self) -> tuple[list[Tag], None]:
35
+ data = self._holder._call(get_projects_project_id_tags, self._project.id)
36
+ return [Tag(row.tag, self._project, row.card_count) for row in data], None
37
+
38
+ def get(self, name: str) -> Tag:
39
+ """Fetch a tag by its normalized name, independently of cached results."""
40
+ if not isinstance(name, str):
41
+ raise TypeError("name must be a string")
42
+ for tag in self.all():
43
+ if tag.name == name:
44
+ return tag
45
+ raise NotFoundError(404, "not_found", "Tag not found in this collection")
46
+
47
+
48
+ class CardTagCollection(TagCollection):
49
+ """Tags attached to one card; mutations use the daemon's editable tag line."""
50
+
51
+ def __init__(self, card: Card) -> None:
52
+ self._card = card
53
+ super().__init__(card._project)
54
+
55
+ def _clone(self, query: dict[str, Any]) -> Self:
56
+ return type(self)(self._card)
57
+
58
+ def _fetch_page(self) -> tuple[list[Tag], None]:
59
+ data = self._holder._call(get_cards_card_id, self._card.id)
60
+ if data.project_id != self._project.id:
61
+ raise NotFoundError(404, "not_found", "Card not found in this project")
62
+ # The generated client retains the daemon's tag array as an additional
63
+ # property because CardData does not yet declare it explicitly.
64
+ names = data.additional_properties.get("tags")
65
+ if not isinstance(names, list) or any(
66
+ not isinstance(name, str) or not name for name in names
67
+ ):
68
+ raise ProtocolError("Card response did not include valid tags")
69
+ return [Tag(name, self._project) for name in names], None
70
+
71
+ def add(self, name: str) -> Self:
72
+ """Add a tag and refresh the card. Validation and normalization are server-side."""
73
+ return self._mutate(post_cards_card_id_tags, name)
74
+
75
+ def remove(self, name: str) -> Self:
76
+ """Remove a trailing-line tag; body mentions remain until content is edited."""
77
+ return self._mutate(delete_cards_card_id_tags, name)
78
+
79
+ def _mutate(self, endpoint: Any, name: str) -> Self:
80
+ if not isinstance(name, str):
81
+ raise TypeError("name must be a string")
82
+ self._holder._call(
83
+ endpoint,
84
+ self._card.id,
85
+ body=CardTagMutationRequest(project_id=self._project.id, tag=name),
86
+ write=True,
87
+ )
88
+ # Invalidate even if the following read fails. The write is never retried.
89
+ self.refresh()
90
+ self._card.refresh()
91
+ return self
92
+
93
+
94
+ @dataclass(frozen=True, eq=False)
95
+ class Tag:
96
+ """A normalized project tag.
97
+
98
+ Project listings supply card_count; tags read from a card omit it until
99
+ refresh() fetches their project-wide count.
100
+ """
101
+
102
+ name: str
103
+ _project: Project = field(repr=False, compare=False)
104
+ card_count: int | None = None
105
+
106
+ @property
107
+ def project_id(self) -> str:
108
+ return self._project.id
109
+
110
+ @cached_property
111
+ def cards(self) -> CardCollection:
112
+ return self._project.cards.filter(tag=self.name)
113
+
114
+ def refresh(self) -> Self:
115
+ fresh = self._project.tags.get(self.name)
116
+ object.__setattr__(self, "card_count", fresh.card_count)
117
+ return self
holder/py.typed ADDED
File without changes
@@ -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).