use crate::{
error::{EvalResult, InterpreterError},
value::Value,
};
pub fn constant(name: &str) -> Option<Value> {
match name {
"Any" | "Optional" | "Union" | "List" | "Dict" | "Set" | "Tuple" | "FrozenSet"
| "Iterable" | "Iterator" | "Generator" | "Callable" | "Mapping" | "MutableMapping"
| "Sequence" | "MutableSequence" | "Collection" | "Container" | "Hashable" | "Sized"
| "Type" | "Final" | "Literal" | "ClassVar" | "Annotated" | "NoReturn" | "Never"
| "Self" | "TypeAlias" | "TypeGuard" | "Concatenate" | "ParamSpec" | "TypeVar" => {
Some(Value::Type(format!("typing.{name}")))
}
_ => None,
}
}
pub fn has_function(name: &str) -> bool {
matches!(
name,
"cast" | "NewType" | "TYPE_CHECKING" | "get_type_hints" | "get_args" | "get_origin"
)
}
pub fn call(func: &str, args: &[Value]) -> EvalResult {
match func {
"cast" => args.get(1).cloned().ok_or_else(|| {
InterpreterError::TypeError("cast() requires 2 arguments".into()).into()
}),
"NewType" => Ok(Value::Type(format!(
"typing.NewType:{}",
args.first()
.and_then(|v| match v {
Value::String(s) => Some(s.as_str().to_owned()),
_ => None,
})
.unwrap_or_else(|| "anon".to_string())
))),
"get_args" => Ok(Value::Tuple(Vec::new())),
"get_origin" => Ok(Value::None),
"get_type_hints" => Ok(Value::Dict(indexmap::IndexMap::new())),
"TYPE_CHECKING" => Ok(Value::Bool(false)),
_ => Err(InterpreterError::AttributeError(format!(
"module 'typing' has no attribute '{func}'"
))
.into()),
}
}
pub struct TypingModule;
#[async_trait::async_trait]
impl crate::eval::modules::Module for TypingModule {
fn name(&self) -> &'static str {
"typing"
}
fn constant(&self, name: &str) -> Option<Value> {
constant(name)
}
fn has_function(&self, name: &str) -> bool {
has_function(name)
}
async fn call(
&self,
_state: &mut crate::state::InterpreterState,
func: &str,
args: &[Value],
_kwargs: &indexmap::IndexMap<String, Value>,
_tools: &crate::tools::Tools,
) -> EvalResult {
call(func, args)
}
}