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.
- holder_python-0.2.5/.gitignore +8 -0
- holder_python-0.2.5/PKG-INFO +120 -0
- holder_python-0.2.5/README.md +102 -0
- holder_python-0.2.5/docs/development.md +62 -0
- holder_python-0.2.5/docs/low-level-client.md +35 -0
- holder_python-0.2.5/docs/publishing.md +79 -0
- holder_python-0.2.5/docs/scripting.md +139 -0
- holder_python-0.2.5/openapi/generator.yaml +4 -0
- holder_python-0.2.5/openapi/provenance.json +8 -0
- holder_python-0.2.5/pyproject.toml +33 -0
- holder_python-0.2.5/scripts/generate.py +119 -0
- holder_python-0.2.5/scripts/pypi_readme.py +64 -0
- holder_python-0.2.5/src/holder/__init__.py +21 -0
- holder_python-0.2.5/src/holder/client.py +182 -0
- holder_python-0.2.5/src/holder/collections.py +70 -0
- holder_python-0.2.5/src/holder/events.py +238 -0
- holder_python-0.2.5/src/holder/exceptions.py +35 -0
- holder_python-0.2.5/src/holder/generated/__init__.py +8 -0
- holder_python-0.2.5/src/holder/generated/api/__init__.py +1 -0
- holder_python-0.2.5/src/holder/generated/api/default/__init__.py +1 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_ai_messages_message_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_ai_messages_message_id_links.py +205 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_ai_providers_credentials_provider.py +168 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_ai_threads_thread_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id.py +225 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_links.py +205 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_milestones_milestone_id.py +175 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_resources.py +197 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_cards_card_id_tags.py +197 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_locations_location_id.py +105 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_locations_location_id_binding.py +102 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_projects_project_id.py +187 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_resources_resource_id.py +161 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_trash.py +181 -0
- holder_python-0.2.5/src/holder/generated/api/default/delete_trash_type_id.py +175 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_capabilities.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_catalog_json.py +134 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_catalog_yaml.py +132 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_local_models_config.py +134 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages.py +186 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id_backlinks.py +194 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_messages_message_id_links.py +194 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_providers_catalog.py +139 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_providers_credentials.py +136 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_runner_pull_job_id.py +171 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_runner_pull_job_id_events.py +218 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs.py +186 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs_run_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_runs_run_id_events.py +213 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_status.py +134 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_threads.py +171 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ai_threads_thread_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_calendar.py +221 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards.py +286 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_backlinks.py +194 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_links.py +194 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards_card_id_milestones.py +173 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_cards_context.py +226 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_event_cursor.py +198 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_git_providers_json.py +134 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_git_providers_yaml.py +132 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_health.py +134 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_imports_job_id.py +159 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_locations.py +160 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_locations_location_id.py +157 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_openapi_yaml.py +132 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_ping.py +128 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects.py +261 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_cards.py +321 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_encryption_check.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_git_sync_status.py +171 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history.py +246 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id.py +243 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id_compare.py +286 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_history_cards_card_id_snapshot.py +225 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_projects_project_id_tags.py +171 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_resources.py +242 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_resources_resource_id.py +161 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_resources_resource_id_assets_asset_id_content.py +247 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_search_ai.py +216 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_search_cards.py +216 -0
- holder_python-0.2.5/src/holder/generated/api/default/get_trash.py +181 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_ai_messages_message_id.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_ai_threads_thread_id.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_cards_card_id.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_cards_card_id_milestones_milestone_id.py +214 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_locations_location_id.py +117 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_projects_project_id.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/patch_resources_resource_id.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages.py +176 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_capture.py +181 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_message_id_links.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_messages_message_id_restore.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_runner_pull.py +181 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_runner_retry.py +139 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_runs.py +194 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_ai_threads.py +176 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_bye.py +166 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_card_references_resolve.py +181 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards.py +176 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_links.py +192 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_milestones.py +199 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_move.py +222 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_resources.py +197 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_restore.py +186 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_cards_card_id_tags.py +197 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_imports.py +160 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_locations.py +160 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_locations_location_id_test.py +105 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects.py +171 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_pull.py +211 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_push.py +193 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_sync.py +207 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_git_test_remote.py +205 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_history_cards_card_id_restore.py +240 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_recovery_token_export.py +196 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_recovery_token_import.py +196 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_projects_project_id_repair_hierarchy.py +240 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_rebuild.py +176 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_recovery_token_import.py +185 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_reindex.py +139 -0
- holder_python-0.2.5/src/holder/generated/api/default/post_resources.py +176 -0
- holder_python-0.2.5/src/holder/generated/api/default/put_ai_local_models_config.py +173 -0
- holder_python-0.2.5/src/holder/generated/api/default/put_ai_providers_credentials.py +175 -0
- holder_python-0.2.5/src/holder/generated/api/default/put_locations_location_id_binding.py +117 -0
- holder_python-0.2.5/src/holder/generated/api/default/put_locations_preferred.py +107 -0
- holder_python-0.2.5/src/holder/generated/api/default/stream_changes.py +256 -0
- holder_python-0.2.5/src/holder/generated/client.py +280 -0
- holder_python-0.2.5/src/holder/generated/errors.py +16 -0
- holder_python-0.2.5/src/holder/generated/models/__init__.py +569 -0
- holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_data.py +111 -0
- holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_local_model_config_update_request.py +134 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message.py +204 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_capture_request.py +246 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_capture_request_context_type_0.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_capture_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_capture_response_data.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_create_request.py +186 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_create_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_create_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_get_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_update_request.py +203 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_update_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_message_update_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider.py +265 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_api_type_0.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_auth_type_0.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_provider_models_item.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_catalog_response_data.py +100 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credential.py +94 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_delete_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_delete_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_upsert_request.py +92 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credential_upsert_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credentials_list_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/ai_provider_credentials_list_response_data.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_create_request.py +133 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_create_request_context.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_event_data.py +146 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_get_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_item.py +328 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_item_policy_trace_type_0.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/ai_run_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/ai_status_data.py +186 -0
- holder_python-0.2.5/src/holder/generated/models/ai_status_pull_job.py +130 -0
- holder_python-0.2.5/src/holder/generated/models/ai_status_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread.py +116 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_create_request.py +119 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_create_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_create_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_get_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_patch_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_patch_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/ai_thread_update_request.py +104 -0
- holder_python-0.2.5/src/holder/generated/models/asset_import_job.py +141 -0
- holder_python-0.2.5/src/holder/generated/models/asset_import_job_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/asset_import_job_status.py +13 -0
- holder_python-0.2.5/src/holder/generated/models/asset_import_request.py +86 -0
- holder_python-0.2.5/src/holder/generated/models/asset_placement.py +96 -0
- holder_python-0.2.5/src/holder/generated/models/asset_placement_encoding.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/bye_response.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/calendar_card_activity.py +86 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_breadcrumb.py +113 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_breadcrumb_type.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_card.py +161 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_data.py +124 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_data_project.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/card_context_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_create_request.py +147 -0
- holder_python-0.2.5/src/holder/generated/models/card_create_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/card_create_response_data.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/card_data.py +160 -0
- holder_python-0.2.5/src/holder/generated/models/card_get_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_author.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_comparison_data.py +110 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_comparison_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_diff_line.py +100 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_diff_line_origin.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_entry.py +172 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_entry_kind.py +16 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_entry_saves_item.py +94 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_page_data.py +114 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_page_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_restore_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_restore_response_data.py +108 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_snapshot_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_snapshot_response_data.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_history_version.py +86 -0
- holder_python-0.2.5/src/holder/generated/models/card_link.py +116 -0
- holder_python-0.2.5/src/holder/generated/models/card_link_create_request.py +111 -0
- holder_python-0.2.5/src/holder/generated/models/card_link_create_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_link_delete_request.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/card_link_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/card_list_item.py +161 -0
- holder_python-0.2.5/src/holder/generated/models/card_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/card_move_intent.py +15 -0
- holder_python-0.2.5/src/holder/generated/models/card_move_request.py +134 -0
- holder_python-0.2.5/src/holder/generated/models/card_move_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_move_result.py +114 -0
- holder_python-0.2.5/src/holder/generated/models/card_page.py +90 -0
- holder_python-0.2.5/src/holder/generated/models/card_page_item.py +170 -0
- holder_python-0.2.5/src/holder/generated/models/card_page_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/card_patch_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/card_patch_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_candidate.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data.py +129 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data_match_kind.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_data_status.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_request.py +82 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_request_scope.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/card_reference_resolve_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_request.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_result.py +88 -0
- holder_python-0.2.5/src/holder/generated/models/card_tag_mutation_result_outcome.py +12 -0
- holder_python-0.2.5/src/holder/generated/models/card_update_request.py +122 -0
- holder_python-0.2.5/src/holder/generated/models/caste_info.py +85 -0
- holder_python-0.2.5/src/holder/generated/models/caste_info_name.py +12 -0
- holder_python-0.2.5/src/holder/generated/models/caste_recommended_model.py +143 -0
- holder_python-0.2.5/src/holder/generated/models/caste_recommended_model_required_caste.py +12 -0
- holder_python-0.2.5/src/holder/generated/models/change_event_data.py +109 -0
- holder_python-0.2.5/src/holder/generated/models/change_event_data_entity.py +14 -0
- holder_python-0.2.5/src/holder/generated/models/delete_cards_card_id_children.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/delete_cards_card_id_resources_body.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/error.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/error_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/event_checkpoint.py +92 -0
- holder_python-0.2.5/src/holder/generated/models/event_checkpoint_git_revisions.py +66 -0
- holder_python-0.2.5/src/holder/generated/models/event_checkpoint_history_urls.py +48 -0
- holder_python-0.2.5/src/holder/generated/models/event_checkpoint_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/event_resync_data.py +116 -0
- holder_python-0.2.5/src/holder/generated/models/event_resync_data_reason.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_ai_catalog_json_response_200.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/get_ai_messages_message_id_backlinks_include_deleted.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_ai_messages_message_id_links_include_deleted.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_cards_card_id_backlinks_include_deleted.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_cards_card_id_links_include_deleted.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_cards_context_order.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/get_cards_order.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/get_cards_view.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_git_providers_json_response_200.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/get_locations_location_id_response_200.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/get_ping_response_200.py +8 -0
- holder_python-0.2.5/src/holder/generated/models/get_projects_order.py +13 -0
- holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_cards_order.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_cards_parent_type_0.py +8 -0
- holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_history_cards_card_id_compare_mode.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/get_projects_project_id_history_kind.py +13 -0
- holder_python-0.2.5/src/holder/generated/models/health_data.py +110 -0
- holder_python-0.2.5/src/holder/generated/models/health_data_crypt_filter.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/health_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/hierarchy_repair.py +100 -0
- holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_move.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_request.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/hierarchy_repair_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/local_model.py +91 -0
- holder_python-0.2.5/src/holder/generated/models/location_binding_request.py +81 -0
- holder_python-0.2.5/src/holder/generated/models/location_binding_request_values.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/milestone.py +177 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_create_request.py +135 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_remove_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_remove_result.py +79 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/milestone_update_request.py +116 -0
- holder_python-0.2.5/src/holder/generated/models/patch_locations_location_id_body.py +90 -0
- holder_python-0.2.5/src/holder/generated/models/patch_locations_location_id_body_configuration.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/post_ai_runner_pull_body.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/post_cards_card_id_resources_body.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/post_locations_response_201.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/project.py +197 -0
- holder_python-0.2.5/src/holder/generated/models/project_calendar_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_calendar_response_data.py +136 -0
- holder_python-0.2.5/src/holder/generated/models/project_create_request.py +177 -0
- holder_python-0.2.5/src/holder/generated/models/project_create_request_privacy_mode.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/project_create_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_create_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/project_delete_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_delete_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/project_encryption_check.py +94 -0
- holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response_data.py +92 -0
- holder_python-0.2.5/src/holder/generated/models/project_encryption_check_response_data_privacy_mode.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/project_get_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_push_request.py +95 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_push_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_push_response_data.py +199 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_push_response_data_status.py +15 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data.py +163 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_pull.py +96 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_pull_status.py +11 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_push.py +118 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_push_status.py +15 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_operation_response_data_status.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_request.py +94 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_status_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_sync_status_response_data.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_request.py +96 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response_data.py +151 -0
- holder_python-0.2.5/src/holder/generated/models/project_git_test_remote_response_data_status.py +14 -0
- holder_python-0.2.5/src/holder/generated/models/project_history_activity.py +138 -0
- holder_python-0.2.5/src/holder/generated/models/project_history_affected_object.py +74 -0
- holder_python-0.2.5/src/holder/generated/models/project_history_affected_object_kind.py +13 -0
- holder_python-0.2.5/src/holder/generated/models/project_history_page_data.py +115 -0
- holder_python-0.2.5/src/holder/generated/models/project_history_page_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/project_privacy_mode.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_request.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_export_response_data.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_request.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/project_recovery_token_import_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/project_sync.py +227 -0
- holder_python-0.2.5/src/holder/generated/models/project_tag.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/project_tag_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/project_update_request.py +181 -0
- holder_python-0.2.5/src/holder/generated/models/project_update_request_privacy_mode.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/project_update_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/project_update_response_data.py +75 -0
- holder_python-0.2.5/src/holder/generated/models/put_locations_preferred_body.py +70 -0
- holder_python-0.2.5/src/holder/generated/models/rebuild_data.py +94 -0
- holder_python-0.2.5/src/holder/generated/models/rebuild_request.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/rebuild_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response_data.py +141 -0
- holder_python-0.2.5/src/holder/generated/models/recovery_token_import_auto_response_data_pull_status.py +10 -0
- holder_python-0.2.5/src/holder/generated/models/reindex_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/reindex_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/resource.py +134 -0
- holder_python-0.2.5/src/holder/generated/models/resource_asset.py +140 -0
- holder_python-0.2.5/src/holder/generated/models/resource_attachment_response.py +80 -0
- holder_python-0.2.5/src/holder/generated/models/resource_attachment_response_data.py +90 -0
- holder_python-0.2.5/src/holder/generated/models/resource_attachment_response_data_outcome.py +11 -0
- holder_python-0.2.5/src/holder/generated/models/resource_create_request.py +129 -0
- holder_python-0.2.5/src/holder/generated/models/resource_delete_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/resource_delete_response_data.py +62 -0
- holder_python-0.2.5/src/holder/generated/models/resource_list_response.py +134 -0
- holder_python-0.2.5/src/holder/generated/models/resource_metadata.py +55 -0
- holder_python-0.2.5/src/holder/generated/models/resource_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/resource_update_request.py +102 -0
- holder_python-0.2.5/src/holder/generated/models/runner_capabilities_data.py +220 -0
- holder_python-0.2.5/src/holder/generated/models/runner_capabilities_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/runner_pull_job.py +122 -0
- holder_python-0.2.5/src/holder/generated/models/runner_pull_progress.py +86 -0
- holder_python-0.2.5/src/holder/generated/models/runner_pull_start_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/runner_pull_start_response_data.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/runner_pull_status_response.py +76 -0
- holder_python-0.2.5/src/holder/generated/models/search_card_item.py +102 -0
- holder_python-0.2.5/src/holder/generated/models/search_cards_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/search_message_item.py +86 -0
- holder_python-0.2.5/src/holder/generated/models/search_messages_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location.py +149 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_configuration.py +48 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_list_response.py +100 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_provider.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_request.py +118 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_request_configuration.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/storage_location_request_provider.py +9 -0
- holder_python-0.2.5/src/holder/generated/models/trash_delete_response.py +78 -0
- holder_python-0.2.5/src/holder/generated/models/trash_delete_response_data.py +46 -0
- holder_python-0.2.5/src/holder/generated/models/trash_item.py +211 -0
- holder_python-0.2.5/src/holder/generated/models/trash_list_response.py +84 -0
- holder_python-0.2.5/src/holder/generated/types.py +54 -0
- holder_python-0.2.5/src/holder/library.py +15 -0
- holder_python-0.2.5/src/holder/models/__init__.py +15 -0
- holder_python-0.2.5/src/holder/models/card.py +272 -0
- holder_python-0.2.5/src/holder/models/project.py +207 -0
- holder_python-0.2.5/src/holder/models/search.py +66 -0
- holder_python-0.2.5/src/holder/models/tag.py +117 -0
- holder_python-0.2.5/src/holder/py.typed +0 -0
- holder_python-0.2.5/tests/test_events.py +372 -0
- holder_python-0.2.5/tests/test_generated_client.py +390 -0
- holder_python-0.2.5/tests/test_generation.py +47 -0
- holder_python-0.2.5/tests/test_library.py +746 -0
- holder_python-0.2.5/tests/test_library_live.py +367 -0
- holder_python-0.2.5/tests/test_lifecycle.py +99 -0
- holder_python-0.2.5/tests/test_moves.py +187 -0
- holder_python-0.2.5/tests/test_search.py +189 -0
- holder_python-0.2.5/tests/test_tags.py +227 -0
|
@@ -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,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"
|