fn check_partial_args(
        &self,
        object: &Term,
        field: &Term,
        value: &Term,
    ) -> PolarResult<Option<Term>> {
        // If the lookup is a `Value::Call`, then we need to check for partial args
        let (name, args, maybe_kwargs): (Symbol, Vec<Term>, Option<BTreeMap<Symbol, Term>>) =
            match self.deref(field).value() {
                Value::Call(Call { name, args, kwargs }) => (
                    name.clone(),
                    args.iter().map(|arg| self.deep_deref(arg)).collect(),
                    kwargs.as_ref().map(|unwrapped| {
                        unwrapped
                            .iter()
                            .map(|(k, v)| (k.to_owned(), self.deep_deref(v)))
                            .collect()
                    }),
                ),
                _ => return Ok(None),
            };

        // get all partially-bound args
        let partial_args = args
            .iter()
            .enumerate()
            .filter_map(|(i, arg)| {
                if let Value::Variable(v) = arg.value() {
                    match self.binding_manager.variable_state(v) {
                        // bound variables are fine, continue
                        VariableState::Bound(_) => None,
                        // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows"
                        VariableState::Partial => Some(Ok((i, arg))),
                        VariableState::Unbound => Some(Err(self.set_error_context(
                            field,
                            error::RuntimeError::Unsupported {
                                msg: format!(
                                    "cannot call method {} with unbound variable argument {}",
                                    name, v
                                ),
                            },
                        ))),
                    }
                } else {
                    None
                }
            })
            .collect::<Result<Vec<_>, _>>()?;

        // get all partially-bound kwargs
        let partial_kwargs = maybe_kwargs
                .clone()
                .map(|kwargs| {
                    kwargs
                        .iter()
                        .filter_map(|(key, arg)| {
                            if let Value::Variable(v) = arg.value() {
                                match self.binding_manager.variable_state(v) {
                                    // bound variables are fine, continue
                                    VariableState::Bound(_) => None,
                                    // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows"
                                    VariableState::Partial => Some(Ok((key.clone(), arg.clone()))),
                                    VariableState::Unbound => Some(Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!(
                                                "cannot call method {} with unbound variable argument {}", name, v
                                            ),
                                        },
                                    ))),
                                }
                            } else {
                                None
                            }
                        })
                        .collect::<Result<Vec<_>, _>>()
                })
                .transpose()?.unwrap_or_else(Vec::new);

        // If there are no partial args or kwargs, return
        if partial_args.len() + partial_kwargs.len() == 0 {
            return Ok(None);
        }

        // TODO: temprorary fix--If there are partial args, they must be called on `role_allows` or `user_in_role`
        if let Value::ExternalInstance(external) = self.deep_deref(&object).value() {
            if let Some(repr) = external.repr.clone() {
                if repr.contains("sqlalchemy_oso.roles2.OsoRoles")
                    && (name.0 == "role_allows" || name.0 == "user_in_role")
                {
                    if partial_args.len() + partial_kwargs.len() > 1 {
                        // More than 1 partial arg results in error
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with more than 1 partially bound argument.", name.0
                                            ),
                                        }));
                    } else if partial_args.len() == 1 && partial_args[0].0 != 2 {
                        // Non-resource partial arg results in error
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with partially bound argument at index {}.", name.0, partial_args[0].0
                                            ),
                                        }));
                    } else if partial_kwargs.len() == 1 && partial_kwargs[0].0 != sym!("resource") {
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with partially bound argument with keyword {}.", name.0, partial_kwargs[0].0
                                            ),
                                        }));
                    }
                    let dot = op!(
                        Dot,
                        object.clone(),
                        term!(value!(Call {
                            name,
                            args,
                            kwargs: maybe_kwargs
                        }))
                    );
                    let constraint_term = op!(Unify, value.clone(), dot.into_term()).into_term();
                    return Ok(Some(constraint_term));
                }
            }
        }
        // If the call wasn't to one of the specially-allowed methods, throw an error
        Err(self.set_error_context(
            field,
            error::RuntimeError::Unsupported {
                msg: format!(
                    "cannot call method {} with partially-bound arguments.",
                    name,
                ),
            },
        ))
    }
/// Check for partially bound or unbound variable arguments to an external call.
/// If any arguments are partially bound or unbound, return an error.
/// The only exception is the method `OsoRoles.role_allows()`, which expects a partially bound resource argument.
/// If the call is `OsoRoles.role_allows()`, return a term representing a special constraint for the method call.
Check for partially bound or unbound variable arguments to an external call.
If any arguments are partially bound or unbound, return an error.
The only exception is the method `OsoRoles.role_allows()`, which expects a partially bound resource argument.
If the call is `OsoRoles.role_allows()`, return a term representing a special constraint for the method call.
Check for partially bound or unbound variable arguments to an external call . If any arguments are partially bound or unbound return an error . The only exception is the method ` OsoRoles . role_allows () ` which expects a partially bound resource argument . If the call is ` OsoRoles . role_allows () ` return a term representing a special constraint for the method call .
fn check_partial_args(
        &self,
        object: &Term,
        field: &Term,
        value: &Term,
    ) -> PolarResult<Option<Term>> {
        // If the lookup is a `Value::Call`, then we need to check for partial args
        let (name, args, maybe_kwargs): (Symbol, Vec<Term>, Option<BTreeMap<Symbol, Term>>) =
            match self.deref(field).value() {
                Value::Call(Call { name, args, kwargs }) => (
                    name.clone(),
                    args.iter().map(|arg| self.deep_deref(arg)).collect(),
                    kwargs.as_ref().map(|unwrapped| {
                        unwrapped
                            .iter()
                            .map(|(k, v)| (k.to_owned(), self.deep_deref(v)))
                            .collect()
                    }),
                ),
                _ => return Ok(None),
            };
        // get all partially-bound args
        let partial_args = args
            .iter()
            .enumerate()
            .filter_map(|(i, arg)| {
                if let Value::Variable(v) = arg.value() {
                    match self.binding_manager.variable_state(v) {
                        // bound variables are fine, continue
                        VariableState::Bound(_) => None,
                        // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows"
                        VariableState::Partial => Some(Ok((i, arg))),
                        VariableState::Unbound => Some(Err(self.set_error_context(
                            field,
                            error::RuntimeError::Unsupported {
                                msg: format!(
                                    "cannot call method {} with unbound variable argument {}",
                                    name, v
                                ),
                            },
                        ))),
                    }
                } else {
                    None
                }
            })
            .collect::<Result<Vec<_>, _>>()?;
        // get all partially-bound kwargs
        let partial_kwargs = maybe_kwargs
                .clone()
                .map(|kwargs| {
                    kwargs
                        .iter()
                        .filter_map(|(key, arg)| {
                            if let Value::Variable(v) = arg.value() {
                                match self.binding_manager.variable_state(v) {
                                    // bound variables are fine, continue
                                    VariableState::Bound(_) => None,
                                    // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows"
                                    VariableState::Partial => Some(Ok((key.clone(), arg.clone()))),
                                    VariableState::Unbound => Some(Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!(
                                                "cannot call method {} with unbound variable argument {}", name, v
                                            ),
                                        },
                                    ))),
                                }
                            } else {
                                None
                            }
                        })
                        .collect::<Result<Vec<_>, _>>()
                })
                .transpose()?.unwrap_or_else(Vec::new);
        // If there are no partial args or kwargs, return
        if partial_args.len() + partial_kwargs.len() == 0 {
            return Ok(None);
        }
        // TODO: temprorary fix--If there are partial args, they must be called on `role_allows` or `user_in_role`
        if let Value::ExternalInstance(external) = self.deep_deref(&object).value() {
            if let Some(repr) = external.repr.clone() {
                if repr.contains("sqlalchemy_oso.roles2.OsoRoles")
                    && (name.0 == "role_allows" || name.0 == "user_in_role")
                {
                    if partial_args.len() + partial_kwargs.len() > 1 {
                        // More than 1 partial arg results in error
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with more than 1 partially bound argument.", name.0
                                            ),
                                        }));
                    } else if partial_args.len() == 1 && partial_args[0].0 != 2 {
                        // Non-resource partial arg results in error
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with partially bound argument at index {}.", name.0, partial_args[0].0
                                            ),
                                        }));
                    } else if partial_kwargs.len() == 1 && partial_kwargs[0].0 != sym!("resource") {
                        return Err(self.set_error_context(
                                        field,
                                        error::RuntimeError::Unsupported {
                                            msg: format!("Cannot call method {} with partially bound argument with keyword {}.", name.0, partial_kwargs[0].0
                                            ),
                                        }));
                    }
                    let dot = op!(
                        Dot,
                        object.clone(),
                        term!(value!(Call {
                            name,
                            args,
                            kwargs: maybe_kwargs
                        }))
                    );
                    let constraint_term = op!(Unify, value.clone(), dot.into_term()).into_term();
                    return Ok(Some(constraint_term));
                }
            }
        }
        // If the call wasn't to one of the specially-allowed methods, throw an error
        Err(self.set_error_context(
            field,
            error::RuntimeError::Unsupported {
                msg: format!(
                    "cannot call method {} with partially-bound arguments.",
                    name,
                ),
            },
        ))
    }
fn check_partial_args ( & self , object : & Term , field : & Term , value : & Term , ) -> PolarResult < Option < Term > > { // If the lookup is a `Value::Call`, then we need to check for partial args let ( name , args , maybe_kwargs ) : ( Symbol , Vec < Term > , Option < BTreeMap < Symbol , Term > > ) = match self . deref ( field ) . value ( ) { Value :: Call ( Call { name , args , kwargs } ) => ( name . clone ( ) , args . iter ( ) . map ( | arg | self . deep_deref ( arg ) ) . collect ( ) , kwargs . as_ref ( ) . map ( | unwrapped | { unwrapped . iter ( ) . map ( | ( k , v ) | ( k . to_owned ( ) , self . deep_deref ( v ) ) ) . collect ( ) } ) , ) , _ => return Ok ( None ) , } ; // get all partially-bound args let partial_args = args . iter ( ) . enumerate ( ) . filter_map ( | ( i , arg ) | { if let Value :: Variable ( v ) = arg . value ( ) { match self . binding_manager . variable_state ( v ) { // bound variables are fine, continue VariableState :: Bound ( _ ) => None , // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows" VariableState :: Partial => Some ( Ok ( ( i , arg ) ) ) , VariableState :: Unbound => Some ( Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name v ) , } , ) ) ) , } } else { None } } ) . collect :: < Result < Vec < _ > , _ > > ( ) ? ; // get all partially-bound kwargs let partial_kwargs = maybe_kwargs . clone ( ) . map ( | kwargs | { kwargs . iter ( ) . filter_map ( | ( key , arg ) | { if let Value :: Variable ( v ) = arg . value ( ) { match self . binding_manager . variable_state ( v ) { // bound variables are fine, continue VariableState :: Bound ( _ ) => None , // TODO: temporary fix so that partial variables are only fine if being passed into "role_allows" VariableState :: Partial => Some ( Ok ( ( key . clone ( ) , arg . clone ( ) ) ) ) , VariableState :: Unbound => Some ( Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name v ) , } , ) ) ) , } } else { None } } ) . collect :: < Result < Vec < _ > , _ > > ( ) } ) . transpose ( ) ? . unwrap_or_else ( Vec :: new ) ; // If there are no partial args or kwargs, return if partial_args . len ( ) + partial_kwargs . len ( ) == 0 { return Ok ( None ) ; } // TODO: temprorary fix--If there are partial args, they must be called on `role_allows` or `user_in_role` if let Value :: ExternalInstance ( external ) = self . deep_deref ( & object ) . value ( ) { if let Some ( repr ) = external . repr . clone ( ) { if repr . contains ( " " ) && ( name . 0 == " " || name . 0 == " " ) { if partial_args . len ( ) + partial_kwargs . len ( ) > 1 { // More than 1 partial arg results in error return Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name 0 ) , } ) ) ; } else if partial_args . len ( ) == 1 && partial_args [ 0 ] . 0 != 2 { // Non-resource partial arg results in error return Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name 0 partial_args [ 0 ] 0 ) , } ) ) ; } else if partial_kwargs . len ( ) == 1 && partial_kwargs [ 0 ] . 0 != sym ! ( " " ) { return Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name 0 partial_kwargs [ 0 ] 0 ) , } ) ) ; } let dot = op ! ( Dot object clone ( ) term ( value ( Call { name args kwargs maybe_kwargs } ) ) ) ; let constraint_term = op ! ( Unify value clone ( ) dot into_term ( ) ) . into_term ( ) ; return Ok ( Some ( constraint_term ) ) ; } } } // If the call wasn't to one of the specially-allowed methods, throw an error Err ( self . set_error_context ( field , error :: RuntimeError :: Unsupported { msg : format ! ( " " name ) , } , ) ) }
Check for partially bound or unbound variable arguments to an external call.
Check for partially bound or unbound variable arguments to an external call .
&self
object
&Term
field
&Term
value
&Term