Fix warnings and split Scope (#1902)

This commit is contained in:
Jonathan Turner 2020-05-27 16:50:26 +12:00 committed by GitHub
parent 9567c1f564
commit fa812849b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 141 additions and 148 deletions

View File

@ -13,7 +13,7 @@ use futures_codec::FramedRead;
use nu_errors::ShellError;
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
use nu_protocol::{Primitive, ReturnSuccess, Scope, Signature, UntaggedValue, Value};
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
use log::{debug, trace};
use rustyline::error::ReadlineError;
@ -870,7 +870,16 @@ async fn process_line(
trace!("{:#?}", classified_block);
let env = ctx.get_env();
match run_block(&classified_block.block, ctx, input_stream, &Scope::env(env)).await {
match run_block(
&classified_block.block,
ctx,
input_stream,
&Value::nothing(),
&IndexMap::new(),
&env,
)
.await
{
Ok(input) => {
// Running a pipeline gives us back a stream that we can then
// work through. At the top level, we just want to pull on the

View File

@ -368,7 +368,7 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
is_last: true,
},
name_tag: context.name.clone(),
scope: Scope::empty(),
scope: Scope::new(),
},
}
}

View File

@ -6,14 +6,16 @@ use crate::stream::InputStream;
use futures::stream::TryStreamExt;
use nu_errors::ShellError;
use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
use nu_protocol::{ReturnSuccess, UntaggedValue, Value};
use std::sync::atomic::Ordering;
pub(crate) async fn run_block(
block: &Block,
ctx: &mut Context,
mut input: InputStream,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<InputStream, ShellError> {
let mut output: Result<InputStream, ShellError> = Ok(InputStream::empty());
for pipeline in &block.block {
@ -52,7 +54,7 @@ pub(crate) async fn run_block(
return Err(e);
}
}
output = run_pipeline(pipeline, ctx, input, scope).await;
output = run_pipeline(pipeline, ctx, input, it, vars, env).await;
input = InputStream::empty();
}
@ -64,10 +66,11 @@ async fn run_pipeline(
commands: &Commands,
ctx: &mut Context,
mut input: InputStream,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<InputStream, ShellError> {
let mut iter = commands.list.clone().into_iter().peekable();
loop {
let item: Option<ClassifiedCommand> = iter.next();
let next: Option<&ClassifiedCommand> = iter.peek();
@ -78,13 +81,13 @@ async fn run_pipeline(
}
(Some(ClassifiedCommand::Expr(expr)), _) => {
run_expression_block(*expr, ctx, input, scope).await?
run_expression_block(*expr, ctx, it, vars, env).await?
}
(Some(ClassifiedCommand::Error(err)), _) => return Err(err.into()),
(_, Some(ClassifiedCommand::Error(err))) => return Err(err.clone().into()),
(Some(ClassifiedCommand::Internal(left)), _) => {
run_internal_command(left, ctx, input, scope)?
run_internal_command(left, ctx, input, it, vars, env)?
}
(None, _) => break,

View File

@ -6,22 +6,22 @@ use log::{log_enabled, trace};
use futures::stream::once;
use nu_errors::ShellError;
use nu_protocol::hir::SpannedExpression;
use nu_protocol::Scope;
use nu_protocol::Value;
pub(crate) async fn run_expression_block(
expr: SpannedExpression,
context: &mut Context,
_input: InputStream,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<InputStream, ShellError> {
if log_enabled!(log::Level::Trace) {
trace!(target: "nu::run::expr", "->");
trace!(target: "nu::run::expr", "{:?}", expr);
}
let scope = scope.clone();
let registry = context.registry().clone();
let output = evaluate_baseline_expr(&expr, &registry, &scope).await?;
let output = evaluate_baseline_expr(&expr, &registry, it, vars, env).await?;
Ok(once(async { Ok(output) }).to_input_stream())
}

View File

@ -115,7 +115,9 @@ async fn run_with_stdin(
let mut command_args = vec![];
for arg in command.args.iter() {
let value = evaluate_baseline_expr(arg, &context.registry, scope).await?;
let value =
evaluate_baseline_expr(arg, &context.registry, &scope.it, &scope.vars, &scope.env)
.await?;
// Skip any arguments that don't really exist, treating them as optional
// FIXME: we may want to preserve the gap in the future, though it's hard to say
// what value we would put in its place.
@ -509,7 +511,7 @@ mod tests {
let mut ctx = Context::basic().expect("There was a problem creating a basic context.");
assert!(
run_external_command(cmd, &mut ctx, input, &Scope::empty(), false)
run_external_command(cmd, &mut ctx, input, &Scope::new(), false)
.await
.is_err()
);

View File

@ -11,13 +11,20 @@ pub(crate) fn run_internal_command(
command: InternalCommand,
context: &mut Context,
input: InputStream,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<InputStream, ShellError> {
if log_enabled!(log::Level::Trace) {
trace!(target: "nu::run::internal", "->");
trace!(target: "nu::run::internal", "{}", command.name);
}
let scope = Scope {
it: it.clone(),
vars: vars.clone(),
env: env.clone(),
};
let objects: InputStream = trace_stream!(target: "nu::trace_stream::internal", "input" = input);
let internal_command = context.expect_command(&command.name);
@ -26,14 +33,14 @@ pub(crate) fn run_internal_command(
internal_command?,
Tag::unknown_anchor(command.name_span),
command.args.clone(),
scope,
&scope,
objects,
)
};
let mut result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
let mut context = context.clone();
let scope = scope.clone();
// let scope = scope.clone();
let stream = async_stream! {
let mut soft_errs: Vec<ShellError> = vec![];

View File

@ -35,7 +35,7 @@ impl UnevaluatedCallInfo {
it: &Value,
) -> Result<CallInfo, ShellError> {
let mut scope = self.scope.clone();
scope = scope.set_it(it.clone());
scope.it = it.clone();
let args = evaluate_args(&self.args, registry, &scope).await?;
Ok(CallInfo {

View File

@ -84,19 +84,20 @@ fn each(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
let (each_args, mut input): (EachArgs, _) = raw_args.process(&registry).await?;
let block = each_args.block;
while let Some(input) = input.next().await {
let input_clone = input.clone();
let input_stream = if is_expanded_it_usage(&head) {
InputStream::empty()
} else {
once(async { Ok(input) }).to_input_stream()
once(async { Ok(input_clone) }).to_input_stream()
};
let result = run_block(
&block,
&mut context,
input_stream,
&scope.clone().set_it(input_clone),
&input,
&scope.vars,
&scope.env
).await;
match result {

View File

@ -62,7 +62,6 @@ fn format_command(
let commands = format_pattern;
while let Some(value) = input.next().await {
let scope = scope.clone().set_it(value);
let mut output = String::new();
for command in &commands {
@ -74,7 +73,7 @@ fn format_command(
// FIXME: use the correct spans
let full_column_path = nu_parser::parse_full_column_path(&(c.to_string()).spanned(Span::unknown()), &registry);
let result = evaluate_baseline_expr(&full_column_path.0, &registry, &scope).await;
let result = evaluate_baseline_expr(&full_column_path.0, &registry, &value, &scope.vars, &scope.env).await;
if let Ok(c) = result {
output

View File

@ -89,7 +89,7 @@ impl WholeStreamCommand for KeepUntil {
let condition = condition.clone();
trace!("ITEM = {:?}", item);
let result =
evaluate_baseline_expr(&*condition, &registry, &scope.clone().set_it(item.clone()))
evaluate_baseline_expr(&*condition, &registry, &item, &scope.vars, &scope.env)
.await;
trace!("RESULT = {:?}", result);

View File

@ -89,7 +89,7 @@ impl WholeStreamCommand for KeepWhile {
let condition = condition.clone();
trace!("ITEM = {:?}", item);
let result =
evaluate_baseline_expr(&*condition, &registry, &scope.clone().set_it(item.clone()))
evaluate_baseline_expr(&*condition, &registry, &item, &scope.vars, &scope.env)
.await;
trace!("RESULT = {:?}", result);

View File

@ -50,17 +50,19 @@ impl WholeStreamCommand for Merge {
fn merge(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let scope = raw_args.call_info.scope.clone();
let stream = async_stream! {
let mut context = Context::from_raw(&raw_args, &registry);
let name_tag = raw_args.call_info.name_tag.clone();
let scope = raw_args.call_info.scope.clone();
let (merge_args, mut input): (MergeArgs, _) = raw_args.process(&registry).await?;
let block = merge_args.block;
let table: Option<Vec<Value>> = match run_block(&block,
&mut context,
InputStream::empty(),
&scope).await {
&scope.it,
&scope.vars,
&scope.env).await {
Ok(mut stream) => Some(stream.drain_vec().await),
Err(err) => {
yield Err(err);

View File

@ -50,7 +50,7 @@ impl WholeStreamCommand for AliasCommand {
let evaluated = call_info.evaluate(&registry).await?;
if let Some(positional) = &evaluated.args.positional {
for (pos, arg) in positional.iter().enumerate() {
scope = scope.set_var(alias_command.args[pos].to_string(), arg.clone());
scope.vars.insert(alias_command.args[pos].to_string(), arg.clone());
}
}
@ -58,7 +58,9 @@ impl WholeStreamCommand for AliasCommand {
&block,
&mut context,
input,
&scope,
&scope.it,
&scope.vars,
&scope.env,
).await;
match result {

View File

@ -90,7 +90,7 @@ impl WholeStreamCommand for SkipUntil {
let condition = condition.clone();
trace!("ITEM = {:?}", item);
let result =
evaluate_baseline_expr(&*condition, &registry, &scope.clone().set_it(item.clone()))
evaluate_baseline_expr(&*condition, &registry, &item, &scope.vars, &scope.env)
.await;
trace!("RESULT = {:?}", result);

View File

@ -90,7 +90,7 @@ impl WholeStreamCommand for SkipWhile {
let condition = condition.clone();
trace!("ITEM = {:?}", item);
let result =
evaluate_baseline_expr(&*condition, &registry, &scope.clone().set_it(item.clone()))
evaluate_baseline_expr(&*condition, &registry, &item, &scope.vars, &scope.env)
.await;
trace!("RESULT = {:?}", result);

View File

@ -62,14 +62,15 @@ fn update(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStr
tag,
} => {
let for_block = input.clone();
let input_clone = input.clone();
let input_stream = once(async { Ok(for_block) }).to_input_stream();
let result = run_block(
&block,
&mut context,
input_stream,
&scope.clone().set_it(input_clone),
&input,
&scope.vars,
&scope.env
).await;
match result {

View File

@ -67,10 +67,9 @@ fn where_command(
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let scope = raw_args.call_info.scope.clone();
let tag = raw_args.call_info.name_tag.clone();
let stream = async_stream! {
let tag = raw_args.call_info.name_tag.clone();
let scope = raw_args.call_info.scope.clone();
let (WhereArgs { block }, mut input) = raw_args.process(&registry).await?;
let condition = {
if block.block.len() != 1 {
@ -108,7 +107,7 @@ fn where_command(
while let Some(input) = input.next().await {
//FIXME: should we use the scope that's brought in as well?
let condition = evaluate_baseline_expr(&condition, &registry, &scope.clone().set_it(input.clone())).await?;
let condition = evaluate_baseline_expr(&condition, &registry, &input, &scope.vars, &scope.env).await?;
match condition.as_bool() {
Ok(b) => {

View File

@ -57,18 +57,21 @@ fn with_env(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputS
let stream = async_stream! {
let mut context = Context::from_raw(&raw_args, &registry);
let scope = raw_args
let mut scope = raw_args
.call_info
.scope
.clone();
let (WithEnvArgs { variable, block }, mut input) = raw_args.process(&registry).await?;
let scope = scope.set_env_var(variable.0.item, variable.1.item);
scope.env.insert(variable.0.item, variable.1.item);
let result = run_block(
&block,
&mut context,
input,
&scope.clone(),
&scope.it,
&scope.vars,
&scope.env,
).await;
match result {

View File

@ -14,7 +14,8 @@ pub(crate) async fn evaluate_args(
if let Some(positional) = &call.positional {
for pos in positional {
let result = evaluate_baseline_expr(pos, registry, scope).await?;
let result =
evaluate_baseline_expr(pos, registry, &scope.it, &scope.vars, &scope.env).await?;
positional_args.push(result);
}
}
@ -36,7 +37,8 @@ pub(crate) async fn evaluate_args(
hir::NamedValue::Value(_, expr) => {
named_args.insert(
name.clone(),
evaluate_baseline_expr(expr, registry, scope).await?,
evaluate_baseline_expr(expr, registry, &scope.it, &scope.vars, &scope.env)
.await?,
);
}

View File

@ -7,14 +7,16 @@ use log::trace;
use nu_errors::{ArgumentError, ShellError};
use nu_protocol::hir::{self, Expression, SpannedExpression};
use nu_protocol::{
ColumnPath, Primitive, RangeInclusion, Scope, UnspannedPathMember, UntaggedValue, Value,
ColumnPath, Primitive, RangeInclusion, UnspannedPathMember, UntaggedValue, Value,
};
#[async_recursion]
pub(crate) async fn evaluate_baseline_expr(
expr: &SpannedExpression,
registry: &CommandRegistry,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<Value, ShellError> {
let tag = Tag {
span: expr.span,
@ -31,14 +33,14 @@ pub(crate) async fn evaluate_baseline_expr(
Expression::Synthetic(hir::Synthetic::String(s)) => {
Ok(UntaggedValue::string(s).into_untagged_value())
}
Expression::Variable(var) => evaluate_reference(&var, &scope, tag),
Expression::Command(_) => evaluate_command(tag, &scope),
Expression::Invocation(block) => evaluate_invocation(block, registry, scope).await,
Expression::ExternalCommand(external) => evaluate_external(&external, &scope),
Expression::Variable(var) => evaluate_reference(&var, it, vars, env, tag),
Expression::Command(_) => unimplemented!(),
Expression::Invocation(block) => evaluate_invocation(block, registry, it, vars, env).await,
Expression::ExternalCommand(_) => unimplemented!(),
Expression::Binary(binary) => {
// TODO: If we want to add short-circuiting, we'll need to move these down
let left = evaluate_baseline_expr(&binary.left, registry, scope).await?;
let right = evaluate_baseline_expr(&binary.right, registry, scope).await?;
let left = evaluate_baseline_expr(&binary.left, registry, it, vars, env).await?;
let right = evaluate_baseline_expr(&binary.right, registry, it, vars, env).await?;
trace!("left={:?} right={:?}", left.value, right.value);
@ -59,8 +61,8 @@ pub(crate) async fn evaluate_baseline_expr(
let left = &range.left;
let right = &range.right;
let left = evaluate_baseline_expr(&left, registry, scope).await?;
let right = evaluate_baseline_expr(&right, registry, scope).await?;
let left = evaluate_baseline_expr(&left, registry, it, vars, env).await?;
let right = evaluate_baseline_expr(&right, registry, it, vars, env).await?;
let left_span = left.tag.span;
let right_span = right.tag.span;
@ -79,7 +81,7 @@ pub(crate) async fn evaluate_baseline_expr(
let mut exprs = vec![];
for expr in list {
let expr = evaluate_baseline_expr(&expr, registry, scope).await?;
let expr = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
exprs.push(expr);
}
@ -87,7 +89,7 @@ pub(crate) async fn evaluate_baseline_expr(
}
Expression::Block(block) => Ok(UntaggedValue::Block(block.clone()).into_value(&tag)),
Expression::Path(path) => {
let value = evaluate_baseline_expr(&path.head, registry, scope).await?;
let value = evaluate_baseline_expr(&path.head, registry, it, vars, env).await?;
let mut item = value;
for member in &path.tail {
@ -151,12 +153,17 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value {
}
}
fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<Value, ShellError> {
trace!("Evaluating {:?} with Scope {:?}", name, scope);
fn evaluate_reference(
name: &hir::Variable,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
tag: Tag,
) -> Result<Value, ShellError> {
match name {
hir::Variable::It(_) => Ok(scope.it.value.clone().into_value(tag)),
hir::Variable::It(_) => Ok(it.clone()),
hir::Variable::Other(name, _) => match name {
x if x == "$nu" => crate::evaluate::variables::nu(scope, tag),
x if x == "$nu" => crate::evaluate::variables::nu(env, tag),
x if x == "$true" => Ok(Value {
value: UntaggedValue::boolean(true),
tag,
@ -165,8 +172,7 @@ fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<V
value: UntaggedValue::boolean(false),
tag,
}),
x => Ok(scope
.vars
x => Ok(vars
.get(x)
.cloned()
.unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))),
@ -174,19 +180,12 @@ fn evaluate_reference(name: &hir::Variable, scope: &Scope, tag: Tag) -> Result<V
}
}
fn evaluate_external(
external: &hir::ExternalStringCommand,
_scope: &Scope,
) -> Result<Value, ShellError> {
Err(ShellError::syntax_error(
"Unexpected external command".spanned(external.name.span),
))
}
async fn evaluate_invocation(
block: &hir::Block,
registry: &CommandRegistry,
scope: &Scope,
it: &Value,
vars: &IndexMap<String, Value>,
env: &IndexMap<String, String>,
) -> Result<Value, ShellError> {
// FIXME: we should use a real context here
let mut context = Context::basic()?;
@ -194,7 +193,7 @@ async fn evaluate_invocation(
let input = InputStream::empty();
let result = run_block(&block, &mut context, input, &scope.clone()).await?;
let result = run_block(&block, &mut context, input, it, vars, env).await?;
let output = result.into_vec().await;
@ -208,9 +207,3 @@ async fn evaluate_invocation(
_ => Ok(UntaggedValue::nothing().into_value(Tag::unknown())),
}
}
fn evaluate_command(tag: Tag, _scope: &Scope) -> Result<Value, ShellError> {
Err(ShellError::syntax_error(
"Unexpected command".spanned(tag.span),
))
}

View File

@ -1,15 +1,16 @@
use crate::cli::History;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{Scope, TaggedDictBuilder, UntaggedValue, Value};
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
pub fn nu(scope: &Scope, tag: impl Into<Tag>) -> Result<Value, ShellError> {
pub fn nu(env: &IndexMap<String, String>, tag: impl Into<Tag>) -> Result<Value, ShellError> {
let tag = tag.into();
let mut nu_dict = TaggedDictBuilder::new(&tag);
let mut dict = TaggedDictBuilder::new(&tag);
for v in scope.env.iter() {
for v in env.iter() {
if v.0 != "PATH" && v.0 != "Path" {
dict.insert_untagged(v.0, UntaggedValue::string(v.1));
}

View File

@ -1,8 +1,9 @@
use futures::executor::block_on;
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::hir::ClassifiedBlock;
use nu_protocol::{Scope, ShellTypeName, Value};
use nu_protocol::{ShellTypeName, Value};
use crate::commands::classified::block::run_block;
use crate::commands::{whole_stream_command, Echo};
@ -58,10 +59,17 @@ async fn evaluate_block(
let input_stream = InputStream::empty();
let env = ctx.get_env();
Ok(run_block(&block.block, ctx, input_stream, &Scope::env(env))
.await?
.into_vec()
.await)
Ok(run_block(
&block.block,
ctx,
input_stream,
&Value::nothing(),
&IndexMap::new(),
&env,
)
.await?
.into_vec()
.await)
}
// TODO probably something already available to do this

View File

@ -102,6 +102,7 @@ pub(crate) use std::future::Future;
pub(crate) use std::sync::atomic::AtomicBool;
pub(crate) use std::sync::Arc;
pub(crate) use indexmap::IndexMap;
pub(crate) use itertools::Itertools;
pub trait FromInputStream {

View File

@ -24,6 +24,6 @@ fn to_row() {
"#
));
assert!(actual.out.contains("5"));
assert!(actual.out.contains('5'));
})
}

View File

@ -63,6 +63,8 @@ fn outputs_zero_with_no_input() {
}
#[test]
#[allow(clippy::unreadable_literal)]
#[allow(clippy::float_cmp)]
fn compute_sum_of_individual_row() -> Result<(), String> {
let answers_for_columns = [
("cpu", 88.257434),
@ -82,6 +84,8 @@ fn compute_sum_of_individual_row() -> Result<(), String> {
}
#[test]
#[allow(clippy::unreadable_literal)]
#[allow(clippy::float_cmp)]
fn compute_sum_of_table() -> Result<(), String> {
let answers_for_columns = [
("cpu", 88.257434),

View File

@ -387,6 +387,10 @@ impl Value {
_ => false,
}
}
pub fn nothing() -> Value {
UntaggedValue::nothing().into_untagged_value()
}
}
impl From<String> for Value {

View File

@ -1,4 +1,4 @@
use crate::value::{Primitive, UntaggedValue, Value};
use crate::value::Value;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@ -13,69 +13,19 @@ pub struct Scope {
pub env: IndexMap<String, String>,
}
impl Scope {
/// Create a new scope
pub fn new(it: Value) -> Scope {
Scope {
it,
vars: IndexMap::new(),
env: IndexMap::new(),
}
}
}
impl Scope {
/// Create an empty scope
pub fn empty() -> Scope {
pub fn new() -> Scope {
Scope {
it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
it: Value::nothing(),
vars: IndexMap::new(),
env: IndexMap::new(),
}
}
/// Create an empty scope, setting $it to a known Value
pub fn it_value(value: Value) -> Scope {
Scope {
it: value,
vars: IndexMap::new(),
env: IndexMap::new(),
}
}
pub fn env(env: IndexMap<String, String>) -> Scope {
Scope {
it: UntaggedValue::Primitive(Primitive::Nothing).into_untagged_value(),
vars: IndexMap::new(),
env,
}
}
pub fn set_it(self, value: Value) -> Scope {
Scope {
it: value,
vars: self.vars,
env: self.env,
}
}
pub fn set_var(self, name: String, value: Value) -> Scope {
let mut new_vars = self.vars.clone();
new_vars.insert(name, value);
Scope {
it: self.it,
vars: new_vars,
env: self.env,
}
}
pub fn set_env_var(self, variable: String, value: String) -> Scope {
let mut new_env_vars = self.env.clone();
new_env_vars.insert(variable, value);
Scope {
it: self.it,
vars: self.vars,
env: new_env_vars,
}
}
}
impl Default for Scope {
fn default() -> Scope {
Scope::new()
}
}

View File

@ -267,6 +267,7 @@ mod integration {
Ok(())
}
#[test]
#[allow(clippy::approx_constant)]
fn converts_the_input_to_float_using_the_field_passed_as_parameter() -> Result<(), ShellError> {
let run = plugin(&mut Str::new())
.args(

View File

@ -294,6 +294,7 @@ pub mod tests {
}
#[test]
#[allow(clippy::approx_constant)]
fn converts_to_float() -> Result<(), Box<dyn std::error::Error>> {
let mut strutils = Str::new();
strutils.for_to_float();