sunholo 0.145.1__tar.gz → 0.145.3__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.
- {sunholo-0.145.1/src/sunholo.egg-info → sunholo-0.145.3}/PKG-INFO +1 -1
- {sunholo-0.145.1 → sunholo-0.145.3}/pyproject.toml +1 -1
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/async_task_runner.py +30 -5
- {sunholo-0.145.1 → sunholo-0.145.3/src/sunholo.egg-info}/PKG-INFO +1 -1
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async_task_runner.py +88 -17
- {sunholo-0.145.1 → sunholo-0.145.3}/LICENSE.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/MANIFEST.in +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/README.md +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/setup.cfg +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/agent_card.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/task_manager.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/vac_routes.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/refresh.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/database.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_gcs_text.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/file_handling.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/cli_fastmcp.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/extensible_mcp_server.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/mcp_manager.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/sse_utils.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/stdio_http_bridge.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_mcp_server.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_mcp_server_fastmcp.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_tools.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/ollama/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/ollama/ollama_images.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config_class.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/proto_convert.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/SOURCES.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async_genai2.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_chat_history.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_config.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_genai2.py +0 -0
- {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_unstructured.py +0 -0
@@ -96,6 +96,13 @@ class AsyncTaskRunner:
|
|
96
96
|
>>> results = await runner.get_aggregated_results()
|
97
97
|
>>> print(results['results']) # {'fetch_data': 'data from api'}
|
98
98
|
|
99
|
+
# Custom task names for better clarity
|
100
|
+
>>> runner = AsyncTaskRunner()
|
101
|
+
>>> runner.add_task(fetch_data, "user_api", task_name="fetch_user_data")
|
102
|
+
>>> runner.add_task(fetch_data, "posts_api", task_name="fetch_posts")
|
103
|
+
>>> results = await runner.get_aggregated_results()
|
104
|
+
>>> print(results['results']['fetch_user_data']) # User data
|
105
|
+
|
99
106
|
# Silent mode - no console output but still collects results
|
100
107
|
>>> runner = AsyncTaskRunner(verbose=False)
|
101
108
|
|
@@ -108,6 +115,7 @@ class AsyncTaskRunner:
|
|
108
115
|
>>> runner = AsyncTaskRunner(use_default_callbacks=False)
|
109
116
|
"""
|
110
117
|
self.tasks = []
|
118
|
+
self.task_name_counts = {} # Track task names to ensure uniqueness
|
111
119
|
self.retry_enabled = retry_enabled
|
112
120
|
self.retry_kwargs = retry_kwargs or {}
|
113
121
|
self.timeout = timeout
|
@@ -209,18 +217,35 @@ class AsyncTaskRunner:
|
|
209
217
|
func: Callable[..., Any],
|
210
218
|
*args: Any,
|
211
219
|
task_config: Optional[TaskConfig] = None,
|
220
|
+
task_name: Optional[str] = None,
|
212
221
|
**kwargs: Any):
|
213
222
|
"""
|
214
223
|
Adds a task to the list of tasks to be executed, with optional per-task configuration.
|
224
|
+
|
225
|
+
Automatically ensures task names are unique by appending a suffix if needed.
|
215
226
|
|
216
227
|
Args:
|
217
228
|
func: The function to be executed.
|
218
229
|
*args: Positional arguments for the function.
|
219
230
|
task_config: Optional per-task configuration for timeout, retry, and callbacks.
|
231
|
+
task_name: Optional custom name for the task. If not provided, uses func.__name__.
|
220
232
|
**kwargs: Keyword arguments for the function.
|
221
233
|
"""
|
222
|
-
|
223
|
-
|
234
|
+
# Get base name from task_name or function name
|
235
|
+
base_name = task_name if task_name is not None else func.__name__
|
236
|
+
|
237
|
+
# Ensure uniqueness by adding suffix if needed
|
238
|
+
if base_name in self.task_name_counts:
|
239
|
+
# Name already exists, increment count and add suffix
|
240
|
+
self.task_name_counts[base_name] += 1
|
241
|
+
name = f"{base_name}_{self.task_name_counts[base_name]}"
|
242
|
+
else:
|
243
|
+
# First occurrence of this name
|
244
|
+
self.task_name_counts[base_name] = 0
|
245
|
+
name = base_name
|
246
|
+
|
247
|
+
log.info(f"Adding task: {name} with args: {args}, kwargs: {kwargs}, config: {task_config}")
|
248
|
+
self.tasks.append((name, func, args, kwargs, task_config))
|
224
249
|
|
225
250
|
async def run_async_with_callbacks(self) -> AsyncGenerator[CallbackContext, None]:
|
226
251
|
"""
|
@@ -313,10 +338,10 @@ class AsyncTaskRunner:
|
|
313
338
|
|
314
339
|
Example:
|
315
340
|
>>> runner = AsyncTaskRunner()
|
316
|
-
>>> runner.add_task(fetch_data, "api")
|
317
|
-
>>> runner.add_task(process_data, "raw_data")
|
341
|
+
>>> runner.add_task(fetch_data, "api", task_name="api_fetch")
|
342
|
+
>>> runner.add_task(process_data, "raw_data", task_name="data_processing")
|
318
343
|
>>> results = await runner.get_aggregated_results()
|
319
|
-
>>> print(results['results']['
|
344
|
+
>>> print(results['results']['api_fetch']) # Access specific result
|
320
345
|
>>> if results['errors']: # Check for any errors
|
321
346
|
... print(f"Errors occurred: {results['errors']}")
|
322
347
|
"""
|
@@ -46,13 +46,16 @@ async def test_default_callbacks_basic():
|
|
46
46
|
assert 'started' in results
|
47
47
|
assert 'errors' in results
|
48
48
|
|
49
|
-
# Check task results
|
49
|
+
# Check task results - with auto-naming, second task gets _1 suffix
|
50
50
|
assert 'simple_task' in results['results']
|
51
|
-
assert results['results']['simple_task'] == "Result:
|
51
|
+
assert results['results']['simple_task'] == "Result: test1"
|
52
|
+
assert 'simple_task_1' in results['results']
|
53
|
+
assert results['results']['simple_task_1'] == "Result: test2"
|
52
54
|
|
53
|
-
# Check completed list
|
55
|
+
# Check completed list - should have unique names
|
54
56
|
assert len(results['completed']) == 2
|
55
|
-
assert results['completed']
|
57
|
+
assert 'simple_task' in results['completed']
|
58
|
+
assert 'simple_task_1' in results['completed']
|
56
59
|
|
57
60
|
# Check started list
|
58
61
|
assert len(results['started']) == 2
|
@@ -110,8 +113,8 @@ async def test_default_callbacks_with_retry():
|
|
110
113
|
# Check that retries were tracked
|
111
114
|
assert 'retries' in results
|
112
115
|
assert len(results['retries']) == 2 # Attempts 2 and 3 (not 1)
|
113
|
-
assert '
|
114
|
-
assert '
|
116
|
+
assert results['retries'][0] == 'failing_task_attempt_2'
|
117
|
+
assert results['retries'][1] == 'failing_task_attempt_3'
|
115
118
|
|
116
119
|
# Task should have error after all retries
|
117
120
|
assert 'failing_task' in results['errors']
|
@@ -193,7 +196,7 @@ async def test_per_task_timeout_with_defaults():
|
|
193
196
|
|
194
197
|
results = await runner.get_aggregated_results()
|
195
198
|
|
196
|
-
# Check that one timed out
|
199
|
+
# Check that one timed out (first slow_task)
|
197
200
|
assert 'timed_out' in results
|
198
201
|
assert 'slow_task' in results['timed_out']
|
199
202
|
|
@@ -203,9 +206,9 @@ async def test_per_task_timeout_with_defaults():
|
|
203
206
|
error_msg = results['errors'].get('slow_task', '').lower()
|
204
207
|
assert 'timeout' in error_msg or 'unknown' in error_msg
|
205
208
|
|
206
|
-
# The one with extended timeout should complete
|
207
|
-
assert '
|
208
|
-
assert results['results']['
|
209
|
+
# The one with extended timeout should complete (gets _1 suffix)
|
210
|
+
assert 'slow_task_1' in results['results']
|
211
|
+
assert results['results']['slow_task_1'] == "Slow result: complete_task"
|
209
212
|
|
210
213
|
|
211
214
|
@pytest.mark.asyncio
|
@@ -238,7 +241,10 @@ async def test_shared_state_persistence():
|
|
238
241
|
# Check custom state was maintained
|
239
242
|
assert results['custom_counter'] == 3
|
240
243
|
assert len(results['task_order']) == 3
|
241
|
-
|
244
|
+
# With auto-naming, tasks are now: simple_task, simple_task_1, simple_task_2
|
245
|
+
assert 'simple_task' in results['task_order']
|
246
|
+
assert 'simple_task_1' in results['task_order']
|
247
|
+
assert 'simple_task_2' in results['task_order']
|
242
248
|
|
243
249
|
# Default keys should also be present
|
244
250
|
assert 'results' in results
|
@@ -283,14 +289,20 @@ async def test_multiple_tasks_same_name():
|
|
283
289
|
|
284
290
|
results = await runner.get_aggregated_results()
|
285
291
|
|
286
|
-
# Results dict should have
|
287
|
-
assert results['results']['simple_task'] == "Result:
|
292
|
+
# Results dict should have all three with unique names
|
293
|
+
assert results['results']['simple_task'] == "Result: first"
|
294
|
+
assert results['results']['simple_task_1'] == "Result: second"
|
295
|
+
assert results['results']['simple_task_2'] == "Result: third"
|
288
296
|
|
289
|
-
# Completed list should have all three
|
290
|
-
assert results['completed']
|
297
|
+
# Completed list should have all three with unique names
|
298
|
+
assert 'simple_task' in results['completed']
|
299
|
+
assert 'simple_task_1' in results['completed']
|
300
|
+
assert 'simple_task_2' in results['completed']
|
291
301
|
|
292
|
-
# Started list should have all three
|
293
|
-
assert results['started']
|
302
|
+
# Started list should have all three with unique names
|
303
|
+
assert 'simple_task' in results['started']
|
304
|
+
assert 'simple_task_1' in results['started']
|
305
|
+
assert 'simple_task_2' in results['started']
|
294
306
|
|
295
307
|
|
296
308
|
@pytest.mark.asyncio
|
@@ -339,6 +351,63 @@ async def test_task_config_none_values():
|
|
339
351
|
assert results['results']['simple_task'] == "Result: test"
|
340
352
|
|
341
353
|
|
354
|
+
@pytest.mark.asyncio
|
355
|
+
async def test_custom_task_names():
|
356
|
+
"""Test custom task naming feature for better differentiation."""
|
357
|
+
runner = AsyncTaskRunner(verbose=False)
|
358
|
+
|
359
|
+
# Use custom task names to differentiate multiple calls to the same function
|
360
|
+
runner.add_task(simple_task, "API", task_name="fetch_api_data")
|
361
|
+
runner.add_task(simple_task, "Database", task_name="fetch_db_data")
|
362
|
+
runner.add_task(simple_task, "Cache", task_name="fetch_cache_data")
|
363
|
+
|
364
|
+
results = await runner.get_aggregated_results()
|
365
|
+
|
366
|
+
# Check that custom names were used
|
367
|
+
assert 'fetch_api_data' in results['results']
|
368
|
+
assert 'fetch_db_data' in results['results']
|
369
|
+
assert 'fetch_cache_data' in results['results']
|
370
|
+
|
371
|
+
# Check the results values
|
372
|
+
assert results['results']['fetch_api_data'] == "Result: API"
|
373
|
+
assert results['results']['fetch_db_data'] == "Result: Database"
|
374
|
+
assert results['results']['fetch_cache_data'] == "Result: Cache"
|
375
|
+
|
376
|
+
# Check completed list has custom names
|
377
|
+
assert set(results['completed']) == {'fetch_api_data', 'fetch_db_data', 'fetch_cache_data'}
|
378
|
+
|
379
|
+
# Check started list has custom names
|
380
|
+
assert set(results['started']) == {'fetch_api_data', 'fetch_db_data', 'fetch_cache_data'}
|
381
|
+
|
382
|
+
|
383
|
+
@pytest.mark.asyncio
|
384
|
+
async def test_custom_task_names_with_duplicates():
|
385
|
+
"""Test that duplicate custom task names are automatically made unique."""
|
386
|
+
runner = AsyncTaskRunner(verbose=False)
|
387
|
+
|
388
|
+
# Add multiple tasks with the same custom name - should auto-suffix
|
389
|
+
runner.add_task(simple_task, "first", task_name="duplicate_name")
|
390
|
+
runner.add_task(simple_task, "second", task_name="duplicate_name")
|
391
|
+
runner.add_task(simple_task, "third", task_name="duplicate_name")
|
392
|
+
|
393
|
+
results = await runner.get_aggregated_results()
|
394
|
+
|
395
|
+
# Check that names were made unique with suffixes
|
396
|
+
assert 'duplicate_name' in results['results']
|
397
|
+
assert 'duplicate_name_1' in results['results']
|
398
|
+
assert 'duplicate_name_2' in results['results']
|
399
|
+
|
400
|
+
# Check the results values
|
401
|
+
assert results['results']['duplicate_name'] == "Result: first"
|
402
|
+
assert results['results']['duplicate_name_1'] == "Result: second"
|
403
|
+
assert results['results']['duplicate_name_2'] == "Result: third"
|
404
|
+
|
405
|
+
# Check completed list has unique names
|
406
|
+
assert 'duplicate_name' in results['completed']
|
407
|
+
assert 'duplicate_name_1' in results['completed']
|
408
|
+
assert 'duplicate_name_2' in results['completed']
|
409
|
+
|
410
|
+
|
342
411
|
if __name__ == "__main__":
|
343
412
|
# Run tests with asyncio
|
344
413
|
asyncio.run(test_default_callbacks_basic())
|
@@ -352,4 +421,6 @@ if __name__ == "__main__":
|
|
352
421
|
asyncio.run(test_multiple_tasks_same_name())
|
353
422
|
asyncio.run(test_empty_runner())
|
354
423
|
asyncio.run(test_task_config_none_values())
|
424
|
+
asyncio.run(test_custom_task_names())
|
425
|
+
asyncio.run(test_custom_task_names_with_duplicates())
|
355
426
|
print("All tests passed!")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|