pydantic-ai 0.1.10__tar.gz → 0.1.11__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.
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/PKG-INFO +3 -3
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/pyproject.toml +9 -4
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/conftest.py +5 -5
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_evaluator_common.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_otel.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_mermaid.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_bedrock.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_cohere.py +1 -3
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_gemini.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_groq.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_mistral.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_model_function.py +2 -2
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_openai.py +2 -2
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_openai_responses.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_google_vertex.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_provider_names.py +1 -1
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_cli.py +3 -39
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_examples.py +19 -10
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_streaming.py +3 -3
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/.gitignore +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/LICENSE +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/Makefile +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/README.md +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/__init__.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/assets/dummy.pdf +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/assets/kiwi.png +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/assets/marcelo.mp3 +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/assets/small_video.mp4 +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_agent_with_stdio_server.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_dict.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_error.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_image.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_image_resource.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_multiple_items.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_none.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_str.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_text_resource.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[anthropic].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[bedrock].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[cohere].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[gemini].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[groq].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[mistral].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_settings/test_stop_settings[openai].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/__init__.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_dataset.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_evaluator_base.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_evaluator_context.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_evaluator_spec.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_evaluators.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_llm_as_a_judge.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_render_numbers.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_reporting.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_reports.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/test_utils.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/evals/utils.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/example_modules/README.md +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/example_modules/bank_database.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/example_modules/fake_database.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/example_modules/weather_service.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/__init__.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_file_persistence.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_graph.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_persistence.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_state.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/graph/test_utils.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/import_examples.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/json_body_serializer.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/mcp_server.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/__init__.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_anthropic_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_document_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_extra_headers.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_image_url_input_invalid_mime_type.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_multiple_parallel_tool_calls.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_anthropic/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_empty_system_prompt.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_anthropic_model_without_tools.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_guardrail_config.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_iter_stream.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_max_tokens.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_other_parameters.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_performance_config.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_retry.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_stream.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_structured_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_model_top_p.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_bedrock_multiple_documents_in_history.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_text_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_video_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_bedrock/test_video_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_cohere/test_cohere_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_cohere/test_request_simple_success_with_vcr.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_false.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_gemini_additional_properties_is_true.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_gemini_drop_exclusive_maximum.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_gemini_exclusive_minimum_and_maximum.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_gemini_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_video_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_gemini/test_video_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_groq/test_extra_headers.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_groq/test_groq_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_groq/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_groq/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_groq/test_image_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_mistral/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_mistral/test_mistral_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_audio_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_document_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_extra_headers.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_image_url_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4.5-preview].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_max_completion_tokens[gpt-4o-mini].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_max_completion_tokens[o3-mini].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_multiple_agent_tool_calls.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_audio_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_instructions_with_tool_calls_keep_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_model_without_system_prompt.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[developer].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_openai_o1_mini_system_role[system].yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai/test_user_id.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_audio_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_image_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_image_as_binary_content_tool_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_as_binary_content_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_image_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_builtin_tools.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_http_error.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_instructions.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_retry.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_model_simple_response_with_tool_call.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_output_type.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_effort.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_reasoning_generate_summary.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_stream.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_system_prompt.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/cassettes/test_openai_responses/test_openai_responses_text_document_url_input.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/mock_async_stream.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_anthropic.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_fallback.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_instrumented.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_model.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_model_names.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/models/test_model_test.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/__init__.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/cassettes/test_azure/test_azure_provider_call.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/cassettes/test_google_vertex/test_vertexai_provider.yaml +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_anthropic.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_azure.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_bedrock.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_cohere.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_deepseek.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_google_gla.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_groq.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_mistral.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/providers/test_openai.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_agent.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_deps.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_format_as_xml.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_json_body_serializer.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_live.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_logfire.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_mcp.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_messages.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_parts_manager.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_settings.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_tools.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_usage_limits.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/test_utils.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/typed_agent.py +0 -0
- {pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/typed_graph.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs
|
|
5
5
|
Project-URL: Homepage, https://ai.pydantic.dev
|
|
6
6
|
Project-URL: Source, https://github.com/pydantic/pydantic-ai
|
|
@@ -28,9 +28,9 @@ Classifier: Topic :: Internet
|
|
|
28
28
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
29
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
30
|
Requires-Python: >=3.9
|
|
31
|
-
Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,evals,groq,mcp,mistral,openai,vertexai]==0.1.
|
|
31
|
+
Requires-Dist: pydantic-ai-slim[anthropic,bedrock,cli,cohere,evals,groq,mcp,mistral,openai,vertexai]==0.1.11
|
|
32
32
|
Provides-Extra: examples
|
|
33
|
-
Requires-Dist: pydantic-ai-examples==0.1.
|
|
33
|
+
Requires-Dist: pydantic-ai-examples==0.1.11; extra == 'examples'
|
|
34
34
|
Provides-Extra: logfire
|
|
35
35
|
Requires-Dist: logfire>=3.11.0; extra == 'logfire'
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
@@ -60,14 +60,13 @@ Documentation = "https://ai.pydantic.dev"
|
|
|
60
60
|
Changelog = "https://github.com/pydantic/pydantic-ai/releases"
|
|
61
61
|
|
|
62
62
|
[project.scripts]
|
|
63
|
-
pai = "pydantic_ai._cli:
|
|
63
|
+
pai = "pydantic_ai._cli:cli_exit" # TODO remove this when clai has been out for a while
|
|
64
64
|
|
|
65
65
|
[tool.uv.sources]
|
|
66
66
|
pydantic-ai-slim = { workspace = true }
|
|
67
67
|
pydantic-evals = { workspace = true }
|
|
68
68
|
pydantic-graph = { workspace = true }
|
|
69
69
|
pydantic-ai-examples = { workspace = true }
|
|
70
|
-
mcp-run-python = { workspace = true }
|
|
71
70
|
|
|
72
71
|
[tool.uv.workspace]
|
|
73
72
|
members = [
|
|
@@ -75,6 +74,7 @@ members = [
|
|
|
75
74
|
"pydantic_evals",
|
|
76
75
|
"pydantic_graph",
|
|
77
76
|
"mcp-run-python",
|
|
77
|
+
"clai",
|
|
78
78
|
"examples",
|
|
79
79
|
]
|
|
80
80
|
|
|
@@ -106,6 +106,7 @@ include = [
|
|
|
106
106
|
"pydantic_graph/**/*.py",
|
|
107
107
|
"mcp-run-python/**/*.py",
|
|
108
108
|
"examples/**/*.py",
|
|
109
|
+
"clai/**/*.py",
|
|
109
110
|
"tests/**/*.py",
|
|
110
111
|
"docs/**/*.py",
|
|
111
112
|
]
|
|
@@ -114,7 +115,7 @@ include = [
|
|
|
114
115
|
extend-select = [
|
|
115
116
|
"Q",
|
|
116
117
|
"RUF100",
|
|
117
|
-
"RUF018",
|
|
118
|
+
"RUF018", # https://docs.astral.sh/ruff/rules/assignment-in-assert/
|
|
118
119
|
"C90",
|
|
119
120
|
"UP",
|
|
120
121
|
"I",
|
|
@@ -163,6 +164,7 @@ include = [
|
|
|
163
164
|
"mcp-run-python",
|
|
164
165
|
"tests",
|
|
165
166
|
"examples",
|
|
167
|
+
"clai",
|
|
166
168
|
]
|
|
167
169
|
venvPath = ".venv"
|
|
168
170
|
# see https://github.com/microsoft/pyright/issues/7771 - we don't want to error on decorated functions in tests
|
|
@@ -193,7 +195,7 @@ filterwarnings = [
|
|
|
193
195
|
"ignore:websockets.server.WebSocketServerProtocol is deprecated:DeprecationWarning",
|
|
194
196
|
# random resource warnings; I suspect these are coming from vendor SDKs when running examples..
|
|
195
197
|
"ignore:unclosed <socket:ResourceWarning",
|
|
196
|
-
"ignore:unclosed event loop:ResourceWarning"
|
|
198
|
+
"ignore:unclosed event loop:ResourceWarning",
|
|
197
199
|
]
|
|
198
200
|
|
|
199
201
|
# https://coverage.readthedocs.io/en/latest/config.html#run
|
|
@@ -215,7 +217,10 @@ show_missing = true
|
|
|
215
217
|
ignore_errors = true
|
|
216
218
|
precision = 2
|
|
217
219
|
exclude_lines = [
|
|
220
|
+
# `# pragma: no cover` is standard marker for code that's not covered, this will error if code is covered
|
|
218
221
|
'pragma: no cover',
|
|
222
|
+
# use `# pragma: lax no cover` if you want to ignore cases where (some of) the code is covered
|
|
223
|
+
'pragma: lax no cover',
|
|
219
224
|
'raise NotImplementedError',
|
|
220
225
|
'if TYPE_CHECKING:',
|
|
221
226
|
'if typing.TYPE_CHECKING:',
|
|
@@ -59,7 +59,7 @@ class TestEnv:
|
|
|
59
59
|
def remove(self, name: str) -> None:
|
|
60
60
|
self.envars[name] = os.environ.pop(name, None)
|
|
61
61
|
|
|
62
|
-
def reset(self) -> None:
|
|
62
|
+
def reset(self) -> None:
|
|
63
63
|
for name, value in self.envars.items():
|
|
64
64
|
if value is None:
|
|
65
65
|
os.environ.pop(name, None)
|
|
@@ -100,7 +100,7 @@ async def client_with_handler() -> AsyncIterator[ClientWithHandler]:
|
|
|
100
100
|
try:
|
|
101
101
|
yield create_client
|
|
102
102
|
finally:
|
|
103
|
-
if client:
|
|
103
|
+
if client:
|
|
104
104
|
await client.aclose()
|
|
105
105
|
|
|
106
106
|
|
|
@@ -155,7 +155,7 @@ def create_module(tmp_path: Path, request: pytest.FixtureRequest) -> Callable[[s
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
@contextmanager
|
|
158
|
-
def try_import() -> Iterator[Callable[[], bool]]:
|
|
158
|
+
def try_import() -> Iterator[Callable[[], bool]]:
|
|
159
159
|
import_success = False
|
|
160
160
|
|
|
161
161
|
def check_import() -> bool:
|
|
@@ -276,7 +276,7 @@ def mistral_api_key() -> str:
|
|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
@pytest.fixture(scope='session')
|
|
279
|
-
def bedrock_provider():
|
|
279
|
+
def bedrock_provider():
|
|
280
280
|
try:
|
|
281
281
|
import boto3
|
|
282
282
|
|
|
@@ -304,7 +304,7 @@ def model(
|
|
|
304
304
|
co_api_key: str,
|
|
305
305
|
gemini_api_key: str,
|
|
306
306
|
bedrock_provider: BedrockProvider,
|
|
307
|
-
) -> Model: # pragma: no cover
|
|
307
|
+
) -> Model: # pragma: lax no cover
|
|
308
308
|
try:
|
|
309
309
|
if request.param == 'openai':
|
|
310
310
|
from pydantic_ai.models.openai import OpenAIModel
|
|
@@ -879,7 +879,7 @@ async def test_context_subtree_invalid_tracer_provider(mocker: MockerFixture):
|
|
|
879
879
|
|
|
880
880
|
mocker.patch('pydantic_evals.otel._context_in_memory_span_exporter.get_tracer_provider', return_value=None)
|
|
881
881
|
with pytest.raises(TypeError) as exc_info:
|
|
882
|
-
with context_subtree():
|
|
882
|
+
with context_subtree():
|
|
883
883
|
pass
|
|
884
884
|
assert str(exc_info.value) == snapshot(
|
|
885
885
|
"Expected `tracer_provider` to have an `add_span_processor` method; got an instance of <class 'NoneType'>. For help resolving this, please create an issue at https://github.com/pydantic/pydantic-ai/issues."
|
|
@@ -358,7 +358,7 @@ async def test_bedrock_model_iter_stream(allow_model_requests: None, bedrock_pro
|
|
|
358
358
|
Args:
|
|
359
359
|
city: The city name.
|
|
360
360
|
"""
|
|
361
|
-
return '30°C'
|
|
361
|
+
return '30°C'
|
|
362
362
|
|
|
363
363
|
event_parts: list[Any] = []
|
|
364
364
|
async with agent.iter(user_prompt='What is the temperature of the capital of France?') as agent_run:
|
|
@@ -66,9 +66,7 @@ class MockAsyncClientV2:
|
|
|
66
66
|
def create_mock(cls, completions: MockChatResponse | Sequence[MockChatResponse]) -> AsyncClientV2:
|
|
67
67
|
return cast(AsyncClientV2, cls(completions=completions))
|
|
68
68
|
|
|
69
|
-
async def chat(
|
|
70
|
-
self, *_args: Any, **_kwargs: Any
|
|
71
|
-
) -> ChatResponse:
|
|
69
|
+
async def chat(self, *_args: Any, **_kwargs: Any) -> ChatResponse:
|
|
72
70
|
assert self.completions is not None
|
|
73
71
|
if isinstance(self.completions, Sequence):
|
|
74
72
|
raise_if_exception(self.completions[self.index])
|
|
@@ -420,7 +420,7 @@ async def get_gemini_client(
|
|
|
420
420
|
|
|
421
421
|
def gemini_response(content: _GeminiContent, finish_reason: Literal['STOP'] | None = 'STOP') -> _GeminiResponse:
|
|
422
422
|
candidate = _GeminiCandidates(content=content, index=0, safety_ratings=[])
|
|
423
|
-
if finish_reason:
|
|
423
|
+
if finish_reason:
|
|
424
424
|
candidate['finish_reason'] = finish_reason
|
|
425
425
|
return _GeminiResponse(candidates=[candidate], usage_metadata=example_usage(), model_version='gemini-1.5-flash-123')
|
|
426
426
|
|
|
@@ -489,7 +489,7 @@ async def test_no_content(allow_model_requests: None):
|
|
|
489
489
|
|
|
490
490
|
with pytest.raises(UnexpectedModelBehavior, match='Received empty model response'):
|
|
491
491
|
async with agent.run_stream(''):
|
|
492
|
-
pass
|
|
492
|
+
pass
|
|
493
493
|
|
|
494
494
|
|
|
495
495
|
async def test_no_delta(allow_model_requests: None):
|
|
@@ -92,7 +92,7 @@ class MockMistralAI:
|
|
|
92
92
|
) -> Mistral:
|
|
93
93
|
return cast(Mistral, cls(stream=completions_streams))
|
|
94
94
|
|
|
95
|
-
async def chat_completions_create( # pragma: no cover
|
|
95
|
+
async def chat_completions_create( # pragma: lax no cover
|
|
96
96
|
self, *_args: Any, stream: bool = False, **_kwargs: Any
|
|
97
97
|
) -> MistralChatCompletionResponse | MockAsyncStream[MockCompletionEvent]:
|
|
98
98
|
if stream or self.stream:
|
|
@@ -92,7 +92,7 @@ def test_simple():
|
|
|
92
92
|
)
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
async def weather_model(messages: list[ModelMessage], info: AgentInfo) -> ModelResponse: # pragma: no cover
|
|
95
|
+
async def weather_model(messages: list[ModelMessage], info: AgentInfo) -> ModelResponse: # pragma: lax no cover
|
|
96
96
|
assert info.allow_text_output
|
|
97
97
|
assert {t.name for t in info.function_tools} == {'get_location', 'get_weather'}
|
|
98
98
|
last = messages[-1].parts[-1]
|
|
@@ -194,7 +194,7 @@ def test_weather():
|
|
|
194
194
|
assert result.output == 'Sunny in Ipswich'
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
async def call_function_model(messages: list[ModelMessage], _: AgentInfo) -> ModelResponse: # pragma: no cover
|
|
197
|
+
async def call_function_model(messages: list[ModelMessage], _: AgentInfo) -> ModelResponse: # pragma: lax no cover
|
|
198
198
|
last = messages[-1].parts[-1]
|
|
199
199
|
if isinstance(last, UserPromptPart):
|
|
200
200
|
if isinstance(last.content, str) and last.content.startswith('{'):
|
|
@@ -99,7 +99,7 @@ class MockOpenAI:
|
|
|
99
99
|
) -> AsyncOpenAI:
|
|
100
100
|
return cast(AsyncOpenAI, cls(stream=stream))
|
|
101
101
|
|
|
102
|
-
async def chat_completions_create( # pragma: no cover
|
|
102
|
+
async def chat_completions_create( # pragma: lax no cover
|
|
103
103
|
self, *_args: Any, stream: bool = False, **kwargs: Any
|
|
104
104
|
) -> chat.ChatCompletion | MockAsyncStream[MockChatCompletionChunk]:
|
|
105
105
|
self.chat_completion_kwargs.append({k: v for k, v in kwargs.items() if v is not NOT_GIVEN})
|
|
@@ -519,7 +519,7 @@ async def test_no_content(allow_model_requests: None):
|
|
|
519
519
|
|
|
520
520
|
with pytest.raises(UnexpectedModelBehavior, match='Received empty model response'):
|
|
521
521
|
async with agent.run_stream(''):
|
|
522
|
-
pass
|
|
522
|
+
pass
|
|
523
523
|
|
|
524
524
|
|
|
525
525
|
async def test_no_delta(allow_model_requests: None):
|
|
@@ -68,7 +68,7 @@ async def test_openai_responses_output_type(allow_model_requests: None, openai_a
|
|
|
68
68
|
|
|
69
69
|
agent = Agent(model=model, output_type=MyOutput)
|
|
70
70
|
result = await agent.run('Give me the name and age of Brazil, Argentina, and Chile.')
|
|
71
|
-
assert result.output == snapshot({'name': 'Brazil', 'age': 2023})
|
|
71
|
+
assert result.output == snapshot({'name': 'Brazil', 'age': 2023})
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
async def test_openai_responses_reasoning_effort(allow_model_requests: None, openai_api_key: str):
|
|
@@ -147,7 +147,7 @@ def save_service_account(service_account_path: Path, project_id: str) -> None:
|
|
|
147
147
|
def vertex_provider_auth(mocker: MockerFixture) -> None:
|
|
148
148
|
# Locally, we authenticate via `gcloud` CLI, so we don't need to patch anything.
|
|
149
149
|
if not os.getenv('CI'):
|
|
150
|
-
return # pragma: no cover
|
|
150
|
+
return # pragma: lax no cover
|
|
151
151
|
|
|
152
152
|
@dataclass
|
|
153
153
|
class NoOpCredentials:
|
|
@@ -37,7 +37,7 @@ with try_import() as imports_successful:
|
|
|
37
37
|
]
|
|
38
38
|
|
|
39
39
|
if not imports_successful():
|
|
40
|
-
test_infer_provider_params = []
|
|
40
|
+
test_infer_provider_params = []
|
|
41
41
|
|
|
42
42
|
pytestmark = pytest.mark.skipif(not imports_successful(), reason='need to install all extra packages')
|
|
43
43
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
1
|
from io import StringIO
|
|
4
2
|
from typing import Any
|
|
5
3
|
|
|
@@ -31,40 +29,6 @@ def test_cli_version(capfd: CaptureFixture[str]):
|
|
|
31
29
|
assert capfd.readouterr().out.startswith('pai - PydanticAI CLI')
|
|
32
30
|
|
|
33
31
|
|
|
34
|
-
@pytest.mark.skipif(not os.getenv('CI', False), reason="Marcelo can't make this test pass locally")
|
|
35
|
-
@pytest.mark.skipif(sys.version_info >= (3, 13), reason='slightly different output with 3.13')
|
|
36
|
-
def test_cli_help(capfd: CaptureFixture[str]):
|
|
37
|
-
with pytest.raises(SystemExit) as exc:
|
|
38
|
-
cli(['--help'])
|
|
39
|
-
assert exc.value.code == 0
|
|
40
|
-
|
|
41
|
-
assert capfd.readouterr().out.splitlines() == snapshot(
|
|
42
|
-
[
|
|
43
|
-
'usage: pai [-h] [-m [MODEL]] [-l] [-t [CODE_THEME]] [--no-stream] [--version] [prompt]',
|
|
44
|
-
'',
|
|
45
|
-
IsStr(),
|
|
46
|
-
'',
|
|
47
|
-
'Special prompt:',
|
|
48
|
-
'* `/exit` - exit the interactive mode',
|
|
49
|
-
'* `/markdown` - show the last markdown output of the last question',
|
|
50
|
-
'* `/multiline` - toggle multiline mode',
|
|
51
|
-
'',
|
|
52
|
-
'positional arguments:',
|
|
53
|
-
' prompt AI Prompt, if omitted fall into interactive mode',
|
|
54
|
-
'',
|
|
55
|
-
IsStr(),
|
|
56
|
-
' -h, --help show this help message and exit',
|
|
57
|
-
' -m [MODEL], --model [MODEL]',
|
|
58
|
-
' Model to use, in format "<provider>:<model>" e.g. "openai:gpt-4o". Defaults to "openai:gpt-4o".',
|
|
59
|
-
' -l, --list-models List all available models and exit',
|
|
60
|
-
' -t [CODE_THEME], --code-theme [CODE_THEME]',
|
|
61
|
-
' Which colors to use for code, can be "dark", "light" or any theme from pygments.org/styles/. Defaults to "monokai".',
|
|
62
|
-
' --no-stream Whether to stream responses from the model',
|
|
63
|
-
' --version Show version and exit',
|
|
64
|
-
]
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
32
|
def test_invalid_model(capfd: CaptureFixture[str]):
|
|
69
33
|
assert cli(['--model', 'potato']) == 1
|
|
70
34
|
assert capfd.readouterr().out.splitlines() == snapshot(
|
|
@@ -169,7 +133,7 @@ def test_code_theme_unset(mocker: MockerFixture, env: TestEnv):
|
|
|
169
133
|
mock_run_chat = mocker.patch('pydantic_ai._cli.run_chat')
|
|
170
134
|
cli([])
|
|
171
135
|
mock_run_chat.assert_awaited_once_with(
|
|
172
|
-
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'monokai'
|
|
136
|
+
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'monokai', 'pai'
|
|
173
137
|
)
|
|
174
138
|
|
|
175
139
|
|
|
@@ -178,7 +142,7 @@ def test_code_theme_light(mocker: MockerFixture, env: TestEnv):
|
|
|
178
142
|
mock_run_chat = mocker.patch('pydantic_ai._cli.run_chat')
|
|
179
143
|
cli(['--code-theme=light'])
|
|
180
144
|
mock_run_chat.assert_awaited_once_with(
|
|
181
|
-
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'default'
|
|
145
|
+
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'default', 'pai'
|
|
182
146
|
)
|
|
183
147
|
|
|
184
148
|
|
|
@@ -187,5 +151,5 @@ def test_code_theme_dark(mocker: MockerFixture, env: TestEnv):
|
|
|
187
151
|
mock_run_chat = mocker.patch('pydantic_ai._cli.run_chat')
|
|
188
152
|
cli(['--code-theme=dark'])
|
|
189
153
|
mock_run_chat.assert_awaited_once_with(
|
|
190
|
-
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'monokai'
|
|
154
|
+
IsInstance(PromptSession), True, IsInstance(Agent), IsInstance(Console), 'monokai', 'pai'
|
|
191
155
|
)
|
|
@@ -74,6 +74,15 @@ def find_filter_examples() -> Iterable[ParameterSet]:
|
|
|
74
74
|
yield pytest.param(ex, id=test_id)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def reset_cwd():
|
|
79
|
+
original_cwd = os.getcwd()
|
|
80
|
+
try:
|
|
81
|
+
yield
|
|
82
|
+
finally:
|
|
83
|
+
os.chdir(original_cwd)
|
|
84
|
+
|
|
85
|
+
|
|
77
86
|
@pytest.mark.parametrize('example', find_filter_examples())
|
|
78
87
|
def test_docs_examples( # noqa: C901
|
|
79
88
|
example: CodeExample,
|
|
@@ -83,6 +92,7 @@ def test_docs_examples( # noqa: C901
|
|
|
83
92
|
allow_model_requests: None,
|
|
84
93
|
env: TestEnv,
|
|
85
94
|
tmp_path: Path,
|
|
95
|
+
reset_cwd: None,
|
|
86
96
|
):
|
|
87
97
|
mocker.patch('pydantic_ai.agent.models.infer_model', side_effect=mock_infer_model)
|
|
88
98
|
mocker.patch('pydantic_ai._utils.group_by_temporal', side_effect=mock_group_by_temporal)
|
|
@@ -97,7 +107,7 @@ def test_docs_examples( # noqa: C901
|
|
|
97
107
|
|
|
98
108
|
class CustomEvaluationReport(EvaluationReport):
|
|
99
109
|
def print(self, *args: Any, **kwargs: Any) -> None:
|
|
100
|
-
if 'width' in kwargs: # pragma: no cover
|
|
110
|
+
if 'width' in kwargs: # pragma: lax no cover
|
|
101
111
|
raise ValueError('width should not be passed to CustomEvaluationReport')
|
|
102
112
|
table = self.console_table(*args, **kwargs)
|
|
103
113
|
io_file = StringIO()
|
|
@@ -134,8 +144,6 @@ def test_docs_examples( # noqa: C901
|
|
|
134
144
|
if sys.version_info < python_version_info:
|
|
135
145
|
pytest.skip(f'Python version {python_version} required')
|
|
136
146
|
|
|
137
|
-
cwd = Path.cwd()
|
|
138
|
-
|
|
139
147
|
if opt_test.startswith('skip') and opt_lint.startswith('skip'):
|
|
140
148
|
pytest.skip('both running code and lint skipped')
|
|
141
149
|
|
|
@@ -173,7 +181,7 @@ def test_docs_examples( # noqa: C901
|
|
|
173
181
|
|
|
174
182
|
if not opt_lint.startswith('skip'):
|
|
175
183
|
# ruff and seem to black disagree here, not sure if that's easily fixable
|
|
176
|
-
if eval_example.update_examples: # pragma: no cover
|
|
184
|
+
if eval_example.update_examples: # pragma: lax no cover
|
|
177
185
|
eval_example.format_ruff(example)
|
|
178
186
|
else:
|
|
179
187
|
eval_example.lint_ruff(example)
|
|
@@ -184,12 +192,11 @@ def test_docs_examples( # noqa: C901
|
|
|
184
192
|
test_globals: dict[str, str] = {}
|
|
185
193
|
if opt_title == 'mcp_client.py':
|
|
186
194
|
test_globals['__name__'] = '__test__'
|
|
187
|
-
if eval_example.update_examples: # pragma: no cover
|
|
195
|
+
if eval_example.update_examples: # pragma: lax no cover
|
|
188
196
|
module_dict = eval_example.run_print_update(example, call=call_name, module_globals=test_globals)
|
|
189
197
|
else:
|
|
190
198
|
module_dict = eval_example.run_print_check(example, call=call_name, module_globals=test_globals)
|
|
191
199
|
|
|
192
|
-
os.chdir(cwd)
|
|
193
200
|
if title := opt_title:
|
|
194
201
|
if title.endswith('.py'):
|
|
195
202
|
module_name = title[:-3]
|
|
@@ -234,7 +241,7 @@ def rich_prompt_ask(prompt: str, *_args: Any, **_kwargs: Any) -> str:
|
|
|
234
241
|
return 'Vichy'
|
|
235
242
|
elif prompt == 'what is 1 + 1?':
|
|
236
243
|
return '2'
|
|
237
|
-
else:
|
|
244
|
+
else:
|
|
238
245
|
raise ValueError(f'Unexpected prompt: {prompt}')
|
|
239
246
|
|
|
240
247
|
|
|
@@ -397,7 +404,9 @@ tool_responses: dict[tuple[str, str], str] = {
|
|
|
397
404
|
}
|
|
398
405
|
|
|
399
406
|
|
|
400
|
-
async def model_logic(
|
|
407
|
+
async def model_logic( # noqa: C901
|
|
408
|
+
messages: list[ModelMessage], info: AgentInfo
|
|
409
|
+
) -> ModelResponse: # pragma: lax no cover
|
|
401
410
|
m = messages[-1].parts[-1]
|
|
402
411
|
if isinstance(m, UserPromptPart):
|
|
403
412
|
if isinstance(m.content, list) and m.content[0] == 'This is file d9a13f:':
|
|
@@ -573,7 +582,7 @@ async def model_logic(messages: list[ModelMessage], info: AgentInfo) -> ModelRes
|
|
|
573
582
|
|
|
574
583
|
async def stream_model_logic( # noqa C901
|
|
575
584
|
messages: list[ModelMessage], info: AgentInfo
|
|
576
|
-
) -> AsyncIterator[str | DeltaToolCalls]: # pragma: no cover
|
|
585
|
+
) -> AsyncIterator[str | DeltaToolCalls]: # pragma: lax no cover
|
|
577
586
|
async def stream_text_response(r: str) -> AsyncIterator[str]:
|
|
578
587
|
if isinstance(r, str):
|
|
579
588
|
words = r.split(' ')
|
|
@@ -631,7 +640,7 @@ def mock_infer_model(model: Model | KnownModelName) -> Model:
|
|
|
631
640
|
if isinstance(model, FallbackModel):
|
|
632
641
|
# When a fallback model is encountered, replace any OpenAIModel with a model that will raise a ModelHTTPError.
|
|
633
642
|
# Otherwise, do the usual inference.
|
|
634
|
-
def raise_http_error(messages: list[ModelMessage], info: AgentInfo) -> ModelResponse:
|
|
643
|
+
def raise_http_error(messages: list[ModelMessage], info: AgentInfo) -> ModelResponse:
|
|
635
644
|
raise ModelHTTPError(401, 'Invalid API Key')
|
|
636
645
|
|
|
637
646
|
mock_fallback_models: list[Model] = []
|
|
@@ -245,7 +245,7 @@ async def test_plain_response():
|
|
|
245
245
|
|
|
246
246
|
with pytest.raises(UnexpectedModelBehavior, match=r'Exceeded maximum retries \(1\) for result validation'):
|
|
247
247
|
async with agent.run_stream(''):
|
|
248
|
-
pass
|
|
248
|
+
pass
|
|
249
249
|
|
|
250
250
|
assert call_index == 2
|
|
251
251
|
|
|
@@ -357,7 +357,7 @@ async def test_call_tool_empty():
|
|
|
357
357
|
|
|
358
358
|
with pytest.raises(UnexpectedModelBehavior, match='Received empty model response'):
|
|
359
359
|
async with agent.run_stream('hello'):
|
|
360
|
-
pass
|
|
360
|
+
pass
|
|
361
361
|
|
|
362
362
|
|
|
363
363
|
async def test_call_tool_wrong_name():
|
|
@@ -377,7 +377,7 @@ async def test_call_tool_wrong_name():
|
|
|
377
377
|
with capture_run_messages() as messages:
|
|
378
378
|
with pytest.raises(UnexpectedModelBehavior, match=r'Exceeded maximum retries \(0\) for result validation'):
|
|
379
379
|
async with agent.run_stream('hello'):
|
|
380
|
-
pass
|
|
380
|
+
pass
|
|
381
381
|
|
|
382
382
|
assert messages == snapshot(
|
|
383
383
|
[
|
|
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
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_agent_with_stdio_server.yaml
RENAMED
|
File without changes
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_dict.yaml
RENAMED
|
File without changes
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_error.yaml
RENAMED
|
File without changes
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_image.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_none.yaml
RENAMED
|
File without changes
|
{pydantic_ai-0.1.10 → pydantic_ai-0.1.11}/tests/cassettes/test_mcp/test_tool_returning_str.yaml
RENAMED
|
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
|