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.
Files changed (204) hide show
  1. {sunholo-0.145.1/src/sunholo.egg-info → sunholo-0.145.3}/PKG-INFO +1 -1
  2. {sunholo-0.145.1 → sunholo-0.145.3}/pyproject.toml +1 -1
  3. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/async_task_runner.py +30 -5
  4. {sunholo-0.145.1 → sunholo-0.145.3/src/sunholo.egg-info}/PKG-INFO +1 -1
  5. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async_task_runner.py +88 -17
  6. {sunholo-0.145.1 → sunholo-0.145.3}/LICENSE.txt +0 -0
  7. {sunholo-0.145.1 → sunholo-0.145.3}/MANIFEST.in +0 -0
  8. {sunholo-0.145.1 → sunholo-0.145.3}/README.md +0 -0
  9. {sunholo-0.145.1 → sunholo-0.145.3}/setup.cfg +0 -0
  10. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/__init__.py +0 -0
  11. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/__init__.py +0 -0
  12. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/agent_card.py +0 -0
  13. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/task_manager.py +0 -0
  14. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
  15. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/__init__.py +0 -0
  16. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/chat_history.py +0 -0
  17. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/dispatch_to_qa.py +0 -0
  18. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/__init__.py +0 -0
  19. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/base.py +0 -0
  20. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
  21. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/fastapi/vac_routes.py +0 -0
  22. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/__init__.py +0 -0
  23. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/base.py +0 -0
  24. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/flask/vac_routes.py +0 -0
  25. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/langserve.py +0 -0
  26. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/pubsub.py +0 -0
  27. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/route.py +0 -0
  28. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/special_commands.py +0 -0
  29. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/agents/swagger.py +0 -0
  30. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/archive/__init__.py +0 -0
  31. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/archive/archive.py +0 -0
  32. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/__init__.py +0 -0
  33. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/gcloud.py +0 -0
  34. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/refresh.py +0 -0
  35. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/auth/run.py +0 -0
  36. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/__init__.py +0 -0
  37. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/auth.py +0 -0
  38. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/blobs.py +0 -0
  39. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/azure/event_grid.py +0 -0
  40. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/__init__.py +0 -0
  41. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/discord.py +0 -0
  42. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/github_webhook.py +0 -0
  43. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/bots/webapp.py +0 -0
  44. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/__init__.py +0 -0
  45. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/azure.py +0 -0
  46. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/doc_handling.py +0 -0
  47. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/encode_metadata.py +0 -0
  48. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/images.py +0 -0
  49. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/loaders.py +0 -0
  50. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/message_data.py +0 -0
  51. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/pdfs.py +0 -0
  52. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/process_chunker_data.py +0 -0
  53. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/publish.py +0 -0
  54. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/pubsub.py +0 -0
  55. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/chunker/splitter.py +0 -0
  56. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/__init__.py +0 -0
  57. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/chat_vac.py +0 -0
  58. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/cli.py +0 -0
  59. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/cli_init.py +0 -0
  60. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/configs.py +0 -0
  61. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/deploy.py +0 -0
  62. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/embedder.py +0 -0
  63. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/merge_texts.py +0 -0
  64. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/run_proxy.py +0 -0
  65. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/sun_rich.py +0 -0
  66. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/swagger.py +0 -0
  67. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/cli/vertex.py +0 -0
  68. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/__init__.py +0 -0
  69. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/llm.py +0 -0
  70. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/retriever.py +0 -0
  71. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/components/vectorstore.py +0 -0
  72. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/custom_logging.py +0 -0
  73. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/__init__.py +0 -0
  74. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/alloydb.py +0 -0
  75. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/alloydb_client.py +0 -0
  76. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/database.py +0 -0
  77. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/lancedb.py +0 -0
  78. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_function.sql +0 -0
  79. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
  80. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/create_table.sql +0 -0
  81. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  82. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
  83. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/sql/sb/setup.sql +0 -0
  84. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/static_dbs.py +0 -0
  85. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/database/uuid.py +0 -0
  86. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/__init__.py +0 -0
  87. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
  88. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/cli.py +0 -0
  89. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/create_new.py +0 -0
  90. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  91. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  92. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/__init__.py +0 -0
  93. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/embed_chunk.py +0 -0
  94. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/embedder/embed_metadata.py +0 -0
  95. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/excel/__init__.py +0 -0
  96. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/excel/plugin.py +0 -0
  97. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/__init__.py +0 -0
  98. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/add_file.py +0 -0
  99. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_folder.py +0 -0
  100. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_gcs_text.py +0 -0
  101. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/download_url.py +0 -0
  102. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/extract_and_sign.py +0 -0
  103. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/gcs/metadata.py +0 -0
  104. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/__init__.py +0 -0
  105. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/file_handling.py +0 -0
  106. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/genaiv2.py +0 -0
  107. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/images.py +0 -0
  108. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/init.py +0 -0
  109. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/process_funcs_cls.py +0 -0
  110. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/genai/safety.py +0 -0
  111. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/__init__.py +0 -0
  112. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/async_class.py +0 -0
  113. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/direct_vac_func.py +0 -0
  114. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
  115. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langchain_types.py +0 -0
  116. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/__init__.py +0 -0
  117. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/callback.py +0 -0
  118. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/evals.py +0 -0
  119. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/langfuse/prompts.py +0 -0
  120. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/__init__.py +0 -0
  121. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/get_files.py +0 -0
  122. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/import_files.py +0 -0
  123. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
  124. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/llamaindex/user_history.py +0 -0
  125. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/lookup/__init__.py +0 -0
  126. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/lookup/model_lookup.yaml +0 -0
  127. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/__init__.py +0 -0
  128. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/cli.py +0 -0
  129. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/cli_fastmcp.py +0 -0
  130. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/extensible_mcp_server.py +0 -0
  131. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/mcp_manager.py +0 -0
  132. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/sse_utils.py +0 -0
  133. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/stdio_http_bridge.py +0 -0
  134. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_mcp_server.py +0 -0
  135. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_mcp_server_fastmcp.py +0 -0
  136. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/mcp/vac_tools.py +0 -0
  137. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/ollama/__init__.py +0 -0
  138. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/ollama/ollama_images.py +0 -0
  139. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/__init__.py +0 -0
  140. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/process_pubsub.py +0 -0
  141. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/pubsub/pubsub_manager.py +0 -0
  142. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/__init__.py +0 -0
  143. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/parsers.py +0 -0
  144. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/qna/retry.py +0 -0
  145. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/senses/__init__.py +0 -0
  146. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/senses/stream_voice.py +0 -0
  147. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/__init__.py +0 -0
  148. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/content_buffer.py +0 -0
  149. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/langserve.py +0 -0
  150. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/stream_lookup.py +0 -0
  151. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/streaming/streaming.py +0 -0
  152. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/summarise/__init__.py +0 -0
  153. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/summarise/summarise.py +0 -0
  154. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/__init__.py +0 -0
  155. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/agent_service.py +0 -0
  156. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/app.py +0 -0
  157. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/my_log.py +0 -0
  158. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/tools/__init__.py +0 -0
  159. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
  160. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/agent/vac_service.py +0 -0
  161. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/__init__.py +0 -0
  162. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/app.py +0 -0
  163. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/my_log.py +0 -0
  164. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/project/vac_service.py +0 -0
  165. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/__init__.py +0 -0
  166. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/app.py +0 -0
  167. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/templates/system_services/my_log.py +0 -0
  168. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/terraform/__init__.py +0 -0
  169. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/terraform/tfvars_editor.py +0 -0
  170. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/tools/__init__.py +0 -0
  171. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/tools/web_browser.py +0 -0
  172. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/__init__.py +0 -0
  173. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/api_key.py +0 -0
  174. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/big_context.py +0 -0
  175. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config.py +0 -0
  176. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config_class.py +0 -0
  177. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/config_schema.py +0 -0
  178. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/gcp.py +0 -0
  179. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/gcp_project.py +0 -0
  180. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/mime.py +0 -0
  181. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/parsers.py +0 -0
  182. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/proto_convert.py +0 -0
  183. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/timedelta.py +0 -0
  184. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/user_ids.py +0 -0
  185. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/utils/version.py +0 -0
  186. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/__init__.py +0 -0
  187. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/extensions_call.py +0 -0
  188. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/extensions_class.py +0 -0
  189. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/genai_functions.py +0 -0
  190. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/init.py +0 -0
  191. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/memory_tools.py +0 -0
  192. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/safety.py +0 -0
  193. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo/vertex/type_dict_to_json.py +0 -0
  194. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/SOURCES.txt +0 -0
  195. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/dependency_links.txt +0 -0
  196. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/entry_points.txt +0 -0
  197. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/requires.txt +0 -0
  198. {sunholo-0.145.1 → sunholo-0.145.3}/src/sunholo.egg-info/top_level.txt +0 -0
  199. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async.py +0 -0
  200. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_async_genai2.py +0 -0
  201. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_chat_history.py +0 -0
  202. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_config.py +0 -0
  203. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_genai2.py +0 -0
  204. {sunholo-0.145.1 → sunholo-0.145.3}/tests/test_unstructured.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.145.1
3
+ Version: 0.145.3
4
4
  Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
5
  Author-email: Holosun ApS <multivac@sunholo.com>
6
6
  License: Apache License, Version 2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sunholo"
7
- version = "0.145.1"
7
+ version = "0.145.3"
8
8
  description = "AI DevOps - a package to help deploy GenAI to the Cloud."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -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
- log.info(f"Adding task: {func.__name__} with args: {args}, kwargs: {kwargs}, config: {task_config}")
223
- self.tasks.append((func.__name__, func, args, kwargs, task_config))
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']['fetch_data']) # Access specific result
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
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.145.1
3
+ Version: 0.145.3
4
4
  Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
5
  Author-email: Holosun ApS <multivac@sunholo.com>
6
6
  License: Apache License, Version 2.0
@@ -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: test2" # Last one wins with same name
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'].count('simple_task') == 2
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 'failing_task_attempt_2' in results['retries']
114
- assert 'failing_task_attempt_3' in results['retries']
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 'slow_task' in results['results']
208
- assert results['results']['slow_task'] == "Slow result: complete_task"
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
- assert all(name == 'simple_task' for name in results['task_order'])
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 the last result (overwrites)
287
- assert results['results']['simple_task'] == "Result: third"
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'].count('simple_task') == 3
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'].count('simple_task') == 3
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