Extract comprehensive function parameter schema using introspection and docstring parsing
(
func: &Bound<'_, PyAny>,
py: Python<'_>,
)
| 565 | |
| 566 | /// Extract comprehensive function parameter schema using introspection and docstring parsing |
| 567 | fn extract_comprehensive_function_schema( |
| 568 | func: &Bound<'_, PyAny>, |
| 569 | py: Python<'_>, |
| 570 | ) -> PyResult<serde_json::Value> { |
| 571 | let inspect = py.import("inspect")?; |
| 572 | let signature = inspect.call_method1("signature", (func,))?; |
| 573 | let parameters = signature.getattr("parameters")?; |
| 574 | |
| 575 | // Extract docstring for parameter descriptions |
| 576 | let docstring = func |
| 577 | .getattr("__doc__") |
| 578 | .and_then(|doc| doc.extract::<Option<String>>()) |
| 579 | .unwrap_or(None) |
| 580 | .unwrap_or_else(|| String::new()); |
| 581 | |
| 582 | let param_descriptions = parse_docstring_parameters(&docstring); |
| 583 | |
| 584 | let mut properties = serde_json::Map::new(); |
| 585 | let mut required = Vec::new(); |
| 586 | |
| 587 | // Iterate through function parameters using Python dict iteration |
| 588 | let param_items = parameters.call_method0("items")?; |
| 589 | for item in param_items.try_iter()? { |
| 590 | let item_tuple = item?; |
| 591 | let param_name = item_tuple.get_item(0)?.extract::<String>()?; |
| 592 | let param_obj = item_tuple.get_item(1)?; |
| 593 | |
| 594 | // Skip 'self' and 'cls' parameters |
| 595 | if param_name == "self" || param_name == "cls" { |
| 596 | continue; |
| 597 | } |
| 598 | |
| 599 | // Get parameter annotation for type information |
| 600 | let annotation = param_obj.getattr("annotation")?; |
| 601 | let param_type = |
| 602 | if annotation.is_none() || annotation.to_string() == "<class 'inspect._empty'>" { |
| 603 | "string" // Default type |
| 604 | } else { |
| 605 | map_python_type_to_json_schema(&annotation.to_string()) |
| 606 | }; |
| 607 | |
| 608 | let mut param_info = serde_json::Map::new(); |
| 609 | param_info.insert( |
| 610 | "type".to_string(), |
| 611 | serde_json::Value::String(param_type.to_string()), |
| 612 | ); |
| 613 | |
| 614 | // Add description from docstring if available, otherwise use a default |
| 615 | let description = param_descriptions |
| 616 | .get(¶m_name) |
| 617 | .cloned() |
| 618 | .unwrap_or_else(|| format!("Parameter {}", param_name)); |
| 619 | param_info.insert( |
| 620 | "description".to_string(), |
| 621 | serde_json::Value::String(description), |
| 622 | ); |
| 623 | |
| 624 | // Check if parameter has a default value |
no test coverage detected