https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
ALL the Clippy Lints
熟悉rust的人都知道,rust社区提供了一个优秀的优化代码的编程工具,就是clippy。这个网站列举了所有的lints。
https://rust-lang.github.io/rust-clippy/master/index.html
在 Rust 中,可以使用 cargo 命令来执行静态检测,这被称为 cargo lint。它使用了一个名为 clippy 的官方代码检查工具。clippy 可以捕获潜在的错误、代码风格问题和性能反模式。
执行静态检测的命令如下:
1 | cargo clippy |
这个命令会对你的 Rust 代码进行静态分析,并输出潜在的问题和警告。
一些可选的命令行参数:
--all-targets: 检查所有目标(如库、测试等),而不仅仅是主要目标--all-features: 检查所有特性--tests: 检查测试代码--examples: 检查示例代码--benches: 检查基准测试代码-W <lint_name>: 允许控制哪些lint需要被启用或禁用
另外,你还可以将 clippy 集成到你的 CI/CD 流程中,以确保新的代码更改都能通过静态检测。
在项目的 Cargo.toml 文件中添加如下设置可以获得更严格的检查:
1 | [features] |
通过 cargo clippy 命令,你可以获得有用的建议来提高代码质量。这是 Rust 生态系统中推荐的最佳实践。
warning: unneeded return statement with ? operator
这个警告 warning: unneeded 'return' statement with '?' operator 是指在使用 ? 操作符的情况下,return 关键字是多余的。
在 Rust 中,? 操作符被用于传播错误。当它被应用于一个 Result 值时,如果该值是 Ok(x),它将返回 x;如果是 Err(err),它将从当前函数返回 Err(err)。因此,? 已经隐式地处理了返回操作。
例如,假设你有这样的代码:
1 | fn read_file() -> Result<String, io::Error> { |
这里的 return Ok(contents) 就是多余的,因为 ? 操作符已经隐含了对应的返回语义。你可以简化为:
1 | fn read_file() -> Result<String, io::Error> { |
这样的写法更加简洁,同时也避免了编译器的警告。
总的来说,解决这个警告的方法是:移除多余的 return 语句,让 ? 操作符显式地处理错误返回。这不仅使代码更加简洁,而且遵循了 Rust 的惯用写法。
warning: use of or_insert to construct default value
这个警告是指在使用 HashMap 的 or_insert 方法时,构造默认值的方式可能不是最佳实践。
在 Rust 中,当你想要从一个 HashMap 中获取一个键的值时,如果该键不存在,可以使用 or_insert 方法来插入一个新的值。例如:
1 | let mut map = HashMap::new(); |
这段代码在 key 不存在时,会插入一个新的空 Vec。
但是,警告建议你使用 or_default() 方法来代替手动构造默认值。or_default() 方法会自动为你构造该类型的默认值。对于 Vec来说,默认值就是一个空 Vec。
所以,你可以这样修改代码:
1 | let mut map = HashMap::new(); |
这样不仅代码更简洁,而且如果将来 Vec 的默认值发生变化,你也不需要更新代码。
总的来说,使用 or_default() 方法可以让你的代码更加简洁、类型安全,并且更容易维护。
https://github.com/electric-capital/crypto-ecosystems/pull/1158/files
但对有的项目,执行 cargo clippy 会编译失败
多试几次,貌似就可以了…(可能和网络有关吧)
warning: use of deprecated associated function chrono::NaiveDateTime::from_timestamp_opt: use DateTime::from_timestamp instead
这个警告是因为在 Rust 的 chrono 时间库中, chrono::NaiveDateTime::from_timestamp_opt 这个方法已经被弃用了。此方法用于从 Unix 时间戳创建 NaiveDateTime 实例,但现在推荐使用更新的 chrono::DateTime::from_timestamp 方法代替。
解决方式很简单,只需将代码中使用 from_timestamp_opt 的地方改为使用 from_timestamp 即可。具体做法如下:
1 | // 之前的做法 |
新的 from_timestamp 方法与被弃用的 from_timestamp_opt 方法的主要区别在于:
from_timestamp返回DateTime<Utc>类型,而不是NaiveDateTime。DateTime包含时区信息,而NaiveDateTime则不包含。from_timestamp在传入无效时间戳时会 panic,而from_timestamp_opt会返回Option。
如果你需要一个 NaiveDateTime 实例,可以从 DateTime 获取:
1 | use chrono::{DateTime, NaiveDateTime}; |
通过这种方式修改代码,可以消除编译器的弃用警告,并且代码更加现代化。
GPT4:
根据 cargo clippy 的警告,chrono::NaiveDateTime::from_timestamp_opt 函数已被弃用,并建议使用 DateTime::from_timestamp 替代。然而,这里有一个小问题:DateTime::from_timestamp 返回的是一个带时区的 DateTime 对象,而不是一个 NaiveDateTime 对象。这意味着你需要选择一个时区。
假设你希望继续使用 UTC 时区,你可以按照下面的方式修改你的函数:
1 | use chrono::{DateTime, Utc}; |
在这段代码中,我首先使用 NaiveDateTime::from_timestamp 来创建一个 NaiveDateTime 对象,然后使用 DateTime::<Utc>::from_utc 将它转换为一个带 UTC 时区的 DateTime 对象。这样可以保留原有代码的行为,同时避免使用已被弃用的
瞎扯啊…
rust中%a, %d %b %Y %H:%M:%S GMT时间格式是什么?
在Rust的chrono时间库中, %a, %d %b %Y %H:%M:%S GMT 这个时间格式字符串代表以下含义:
%a: 星期的缩写形式,如 “Mon”, “Tue”。%d: 月份的日期,用0补齐的两位数字,范围01-31。%b: 月份的缩写形式,如 “Jan”, “Feb”。%Y: 四位数字表示的年份。%H: 24小时制的小时数,用0补齐的两位数字,范围00-23。%M: 分钟数,用0补齐的两位数字,范围00-59。%S: 秒数,用0补齐的两位数字,范围00-60(60用于闰秒)。GMT: 时区标识符,表示格林威治标准时间。
因此,%a, %d %b %Y %H:%M:%S GMT 这个格式字符串代表的时间格式为:
1 | Wed, 07 Mar 2024 15:09:28 GMT |
它显示了以下信息:
- 星期几(缩写形式)
- 月份的日期
- 月份(缩写形式)
- 年份
- 24小时制的小时数和分钟数
- 秒数
- GMT时区
这种格式通常用于格式化HTTP日期头或其他需要遵循互联网日期/时间格式的场合。它使用英文缩写而不是数字,以方便跨语言环境的阅读和解析。
warning: writing &Vec instead of &[_] involves a new object where a slice will do
1 | warning: writing `&Vec` instead of `&[_]` involves a new object where a slice will do |
这个警告信息来自Rust编译器,指出代码中存在一个可能的改进点。具体来说,当你在函数签名或其他地方使用&Vec<T>类型作为参数时,而实际上使用&[T](一个切片的引用)就足够的情况,Rust编译器会给出这个警告。这个警告的主要目的是鼓励更灵活、更通用的代码编写方式。
原因
- 性能和灵活性:
&[T]表示一个借用的切片,它是一个指向连续数据的指针和数据长度的组合。使用&[T]比&Vec<T>更灵活,因为&[T]可以引用Vec<T>的全部或部分数据,也可以引用数组的一部分,或者任何连续存储的T类型的数据。这增加了函数的通用性和复用性。 - 避免不必要的对象创建:
&Vec<T>意味着你正在借用一个Vec<T>对象,而&[T]只是借用一段连续的内存。在某些情况下,使用&[T]可以避免创建新的Vec<T>对象,从而减少内存分配和提升性能。
示例
假设有一个函数打印数字的向量,以下是使用&Vec<T>和&[T]两种方式的对比:
使用
&Vec<T>(触发警告):1
2
3
4
5fn print_numbers(numbers: &Vec<i32>) {
for number in numbers.iter() {
println!("{}", number);
}
}使用
&[T](推荐方式):1
2
3
4
5fn print_numbers(numbers: &[i32]) {
for number in numbers.iter() {
println!("{}", number);
}
}
总结
当你看到这个警告时,考虑将函数签名中的&Vec<T>更改为&[T],以增加代码的灵活性和效率。这种做法遵循了Rust的零成本抽象原则,即尽可能地在不增加运行时开销的情况下提供抽象。
warning: use of a fallible conversion when an infallible one could be used
1 | warning: use of a fallible conversion when an infallible one could be used |
这个警告是由Rust的lint工具Clippy生成的,它指出你在代码中使用了一个可失败的转换(fallible conversion),即try_from,而在这种情况下,转换实际上是不可失败的(infallible)。这意味着你可以使用一个无法失败的转换方法,从而使代码更简洁、更清晰。
原因
在你的代码中,Pubkey::try_from(pod.address_config)尝试将pod.address_config(很可能是一个[u8; 32]类型)转换为Pubkey类型。根据警告信息,这个转换是不可能失败的,因为Pubkey显然可以直接从一个32字节的数组中构造而不会出错。这时使用try_from就显得不必要,因为try_from通常用于那些可能失败的转换,而这里的转换是绝对安全的。
解决方案
你应该使用From::from而不是Pubkey::try_from,因为前者是一个无法失败的转换。这样做可以消除不必要的错误处理代码,使代码更加简洁。
修改前的代码:
1 | pubkey: Pubkey::try_from(pod.address_config) |
修改后的代码:
1 | pubkey: Pubkey::from(pod.address_config) |
这样,你就遵循了Clippy的建议,使用了一个更加合适的转换方法。这不仅消除了警告,还提高了代码的清晰度和可维护性。
额外的说明
当你遇到这样的警告时,总是值得检查为什么一个看似可以失败的操作(如使用try_from)在这个上下文中被认为是不可失败的。这通常是因为类型系统和你的特定用例保证了转换的成功。理解这一点可以帮助你更好地利用Rust的类型系统和标准库提供的各种转换特性。
根据你之前提到的警告信息,转换Pubkey的过程是不可失败的(即,使用try_from是不必要的)。因此,我们可以直接使用From::from来进行转换,这样就不需要显式地处理任何错误了。
下面是改写后的代码:
1 | fn try_from(pod: &ExtraAccountMeta) -> Result<Self, Self::Error> { |
在这个改写版本中,我直接使用了Pubkey::from(pod.address_config)来代替Pubkey::try_from(pod.address_config).map_err(|_| ProgramError::from(AccountResolutionError::InvalidPubkey))?。这样做是基于之前的讨论:由于转换是不可失败的,我们就不需要包装错误处理了。这也意味着,你不需要map_err来转换错误,因为From::from不会产生错误。
这个改写的前提是你确信pubkey: Pubkey::from(pod.address_config)这一操作确实是不可失败的,这通常取决于Pubkey::from的实现和pod.address_config类型是否确实是[u8; 32]或兼容类型。如果Podkey::from对于输入类型是无条件成功的(如,它能处理任何长度为32的字节数组),那么这个改写就是安全的。
warning: use of a fallible conversion when an infallible one could be used
1 | warning: use of a fallible conversion when an infallible one could be used |
根据Clippy的警告,将u64转换为u128是一个不可失败的操作,因此推荐使用From::from而不是try_from。这是因为u128比u64有更大的表示范围,所以从u64到u128的转换永远不会失败。
你的原始代码使用了u128::try_from(...).ok()?,这里的.ok()?将结果转换为Option<u128>,如果转换失败则提前返回None。但由于这个转换是不可失败的,所以我们可以直接使用From::from进行转换,并且不需要处理任何潜在的错误。
改写后的函数应该像这样:
1 | pub fn owner_withdraw_fee(&self, pool_tokens: u128) -> Option<u128> { |
在这个版本中,我们直接使用u128::from(...)来转换self.owner_withdraw_fee_numerator和self.owner_withdraw_fee_denominator,这两个字段很可能是u64类型。这种方法既清晰又有效率,同时避免了不必要的错误处理代码。
warning: use of a fallible conversion when an infallible one could be used
1 | warning: use of a fallible conversion when an infallible one could be used |
这个警告出现的原因是因为你使用了一个可失败的转换方法(try_into),尝试将u64类型的值转换成u128类型的值。然而,从u64转换到u128实际上是一个不可失败的操作,因为u128的值域比u64大得多,任何u64的值都可以无损地转换为u128。因此,Clippy建议使用不可失败的转换方法,以简化代码并提高其可读性。
解决方案
你可以直接使用into方法替代try_into,这样就不需要错误处理了。以下是改进后的函数:
1 | fn to_u128(val: u64) -> u128 { |
注意,由于转换不会失败,函数的返回类型也从Result<u128, SwapError>更改为了u128。这样,你就不需要使用map_err来处理任何错误了,因为根本不会有错误发生。
这种改动不仅消除了Clippy的警告,也让代码更加简洁明了。
1 | warning: assigning the result of `Clone::clone()` may be inefficient |
Clippy的这个警告提示你,直接使用clone()来赋值可能是低效的。这是因为clone()方法会创建一个新的实例,并将其赋值给目标变量,这个过程可能包括分配新的内存。当目标变量已经是相同类型的实例时,使用clone_from()方法可以更高效,因为它可以重用目标实例的已有资源(如内存),减少资源分配的需要。
解决方案
根据Clippy的建议,你应该使用clone_from()而不是clone()。以下是改进后的代码:
1 | if let Some(path) = matches.get_one::<PathBuf>("serve-path") { |
在这里,args.serve_path.clone_from(path)会直接在args.serve_path上调用clone_from(),将path的值复制到args.serve_path中,而不需要创建一个新的PathBuf实例。这样,如果args.serve_path已经分配了足够的内存来存储新的值,它就可以重用这些内存,从而提高效率。
请注意,clone_from()方法的效率提升取决于具体类型和上下文。在一些情况下,当原始变量几乎没有预分配的空间或可以重用的资源时,使用clone_from()与clone()相比可能不会带来显著的性能改进。然而,遵循Clippy的建议通常是个好习惯,特别是在性能敏感的应用中,因为这可能会在复杂数据结构或大型集合的情况下带来优势。
warning: this else { if .. } block can be collapsed
1 | warning: this `else { if .. }` block can be collapsed |
warning: this lifetime isn’t used in the impl
1 | warning: this lifetime isn't used in the impl |
这个警告意味着在你的impl块中定义的生命周期'a并没有在实现的方法或关联类型中使用。Rust生命周期参数(如'a)的主要用途是为了标注引用的生命周期,以确保数据的使用是安全的。如果一个生命周期参数在实现中没有被用到,那么它就是多余的。
在你提供的代码中,impl<'a> IntoUrlSealed for String这部分声明了一个生命周期'a,但是在impl块的方法定义中并没有使用这个生命周期。这通常是因为String类型拥有它自己的数据,而不是借用外部数据,所以在这个上下文中使用生命周期是不必要的。
如何修改
你可以简单地移除生命周期注解,因为String类型的方法并不需要生命周期参数。修改后的代码如下:
1 | impl IntoUrlSealed for String { |
这样修改后,代码仍然能够正常工作,且不会触发clippy的警告。此修改保留了原有的功能,同时去掉了不必要的生命周期声明,使得代码更简洁、更清晰。
warning: this impl can be derived
1 | warning: this `impl` can be derived |
这个警告意味着你的impl Default可以通过Rust的自动派生(derive)功能来实现,而不是手动实现它。这样做可以简化代码,使其更加清晰易读。当Clippy提示这种类型的警告时,它通常建议使用#[derive(Default)]来自动生成Default的实现,前提是所有结构体字段本身也都实现了Default。
但在你的例子中,由于你使用了条件编译指令(#[cfg(feature = "gzip")]等),直接派生Default可能不会按预期工作,因为这些字段的默认值依赖于编译时的特性标志。
如何修改
你的情况稍微复杂一些,因为你想根据不同的编译特性来设置不同的字段值。如果所有的字段都实现了Default,且默认值都是true,你可以考虑修改结构体,为每个字段提供默认实现,并可能使用#[derive(Default)]。但是,由于使用了条件编译特性,每个字段的默认值只有在相应的特性被启用时才为true,这使得直接使用derive不太可行。
如果你确定需要根据不同的特性标志来条件编译字段,保持现有的手动实现可能是必要的,但是可以优化实现以避免警告。例如,你可以为结构体中的每个字段实现Default,让每个字段根据是否启用了相应的特性来决定它的默认值。
但根据你提供的代码和Clippy的警告,如果每个字段默认都是true,并且希望简化代码,你可能需要重新考虑设计。如果条件编译的逻辑对默认值有实际影响,手动实现Default可能是有意义的,但要注意解释为什么不能简单地使用derive。
最后,如果你确定手动实现是必需的(可能由于条件编译),并且想消除警告,考虑禁用该Clippy警告(如果这是在你控制范围内的话)。可以在文件顶部添加以下属性以忽略特定的Clippy警告:
1 |
这会禁用当前文件中的derivable_impls警告。然而,最好的做法是仔细评估是否真的需要手动实现Default,或者是否可以通过修改代码结构来利用Rust的derive功能。
warning: manual Range::contains implementation
1 | warning: manual `Range::contains` implementation |
这个警告是Rust的静态代码分析工具Clippy提示的,它建议使用Range::contains方法来简化代码。当你手动检查一个值是否位于两个值之间时,使用Range::contains可以使代码更简洁、易读。
在你的例子中,你正在检查变量c是否大于或等于0x20且小于0x7f。Clippy建议使用范围对象(0x20..0x7f)的contains方法来替代手动的比较。
原代码
1 | } else if c >= 0x20 && c < 0x7f { |
修改后的代码
1 | } else if (0x20..0x7f).contains(&c) { |
这样修改后,你的代码会变得更加简洁和符合Rust的惯用法。contains方法会检查指定的范围是否包含了给定的值。请注意,这里的范围是左闭右开的,即包括起始值0x20,不包括结束值0x7f,与原始条件逻辑一致。
warning: you seem to be trying to use match for an equality check. Consider using if
1 | warning: you seem to be trying to use `match` for an equality check. Consider using `if` |
这个警告指出,你的match表达式实际上只用于检查一个条件(即parse_error是否等于url::ParseError::RelativeUrlWithoutBase),而这种情况下使用if语句通常更为清晰和简洁。Clippy推荐将match表达式替换为if语句进行等值比较。
要解决这个警告,你应该按照Clippy的建议修改代码。假设parse_error是通过某种方式得到的url::ParseError类型的变量,你可以这样重写:
原始代码
1 | match parse_error { |
修改后的代码
1 | if parse_error == url::ParseError::RelativeUrlWithoutBase { |
请注意,由于url::ParseError::RelativeUrlWithoutBase是一个枚举变体,这种直接的比较要求ParseError实现了PartialEq trait。幸运的是,大多数Rust枚举,尤其是标准库和流行crate中的枚举,通常都实现了这个trait。如果你遇到了没有实现PartialEq的情况,可能需要考虑其他方法来比较,但这在实践中很少见。
使用if语句不仅可以满足Clippy的建议,提高代码清晰度,也使得代码逻辑更直接、易于理解。
warning: redundant pattern matching, consider using is_some()
1 | warning: redundant pattern matching, consider using `is_some()` |
这个警告意味着你在使用if let来检查Option是否是Some值时,实际上并不关心这个Some中的值。在这种情况下,使用is_some()方法会更加直接和简洁。
原始代码
1 | } else if let Some(_) = err.downcast_ref::<crate::error::BadScheme>() { |
修改后的代码
1 | if err.downcast_ref::<crate::error::BadScheme>().is_some() { |
这种修改使得代码更加简洁和直接。通过直接调用is_some()方法,你可以检查Option是否包含一个值,而不用编写用于匹配并忽略该值的模式。这种方法提高了代码的可读性,并且更符合Rust的惯用法。
warning: assigning the result of Clone::clone() may be inefficient
1 | warning: assigning the result of `Clone::clone()` may be inefficient |
这个警告的意思是,在你的代码中直接使用clone()方法并将其结果分配给一个变量可能是低效的。Rust的Clippy工具推荐使用clone_from()方法来提高效率。clone_from()方法会将目标变量直接更新为源变量的克隆,这通常比创建一个新的克隆然后分配它更有效率,尤其是在涉及到大型数据结构时。
原始代码
1 | *auth = update.clone(); |
修改后的代码
1 | auth.clone_from(update); |
通过这种方式修改你的if_no_auth函数中相关的代码,可以提高代码的效率。修改后,你的函数可能看起来像这样:
1 | fn if_no_auth(mut self, update: &Option<HeaderValue>) -> Self { |
通过使用clone_from(),当update是Some值时,auth会被更新为update的克隆,如果update是None,则auth也会被设置为None。这种方式避免了不必要的分配和潜在的效率低下问题。
warning: very complex type used. Consider factoring parts into type definitions
1 | warning: very complex type used. Consider factoring parts into `type` definitions |
这个警告意味着你在struct定义中使用了一个非常复杂的类型。Clippy建议将复杂的类型分解为更简单的type定义,以提高代码的可读性和可维护性。
原始代码
1 | struct Custom { |
解决方案
你可以通过定义一个新的类型别名来简化func字段的类型定义。这样做可以使代码更清晰,同时保持类型复杂性的封装。
1 | type ProxySchemeFunc = Arc<dyn Fn(&Url) -> Option<crate::Result<ProxyScheme>> + Send + Sync + 'static>; |
这种方式定义了一个新的type,名为ProxySchemeFunc,它是原先复杂类型的别名。这样,Custom结构体就变得更加清晰易读,同时仍然保留了原有的功能。通过这种重构,你可以更容易地理解和使用Custom结构体,特别是在涉及到复杂类型的情况下。
warning: single-character string constant used as pattern
1 | warning: single-character string constant used as pattern |
这个警告指出,你在使用.contains()方法时用了一个单字符的字符串常量作为搜索模式。Clippy建议,当搜索模式是单个字符时,使用字符类型(char)而不是字符串类型(&str),因为使用字符在性能上更优。
原始代码
1 | if platform_values.contains("=") { |
修改后的代码
1 | if platform_values.contains('=') { |
通过将"="改为'=',你使用了字符字面量而不是字符串字面量。这种修改可以提升性能,因为它避免了字符串模式匹配的一些额外开销,特别是在进行简单的字符查找时。
warning: the item Iterator is imported redundantly
1 | warning: the item `Iterator` is imported redundantly |
这个警告信息是Rust编译器提供的,指出在你的Rust代码中有一个不必要的导入(unused import)。具体来说,你在src/util/min_max.rs文件的第一行中显式导入了std::iter::Iterator,但这其实是冗余的,因为Rust的预导入模块(the prelude)已经包含了Iterator。
Rust的预导入模块自动导入了一些最常用的trait和类型,以方便开发者使用,而无需每次都显式导入。Iterator trait就是其中之一。因此,当你显式地导入Iterator时,编译器会告诉你这是冗余的,因为它已经通过预导入模块可用了。
这个警告本身不会阻止你的代码编译或运行,但它指示你可以简化你的代码。解决这个警告的方法是删除use std::iter::Iterator;这行代码。这样做不会影响你的代码功能,但会使代码更干净,遵循Rust的最佳实践。
编译器还提示说,这个警告是在#[warn(unused_imports)]这个属性下产生的,默认情况下这个属性是启用的,旨在帮助开发者识别和移除代码中未使用的导入,从而保持代码的整洁。
warning: direct implementation of ToString
1 | warning: direct implementation of `ToString` |
这个警告是由Rust的lint工具Clippy发出的,指出你直接为ParameterValue类型实现了ToString trait,而更推荐的做法是实现Display trait。在Rust中,ToString trait能够让任何实现了Display的类型自动拥有,因此直接实现Display通常是更好的选择。这样做不仅可以让你的类型支持转换为字符串,而且还能让它通过{}格式化参数在打印等场合使用。
解释
当你为一个类型实现了Display trait,ToString trait会通过Display自动实现,因此你无需直接实现ToString。这样做的好处是代码更简洁且更符合Rust的惯用法。
如何解决
要解决这个警告,你需要将ToString实现替换为Display的实现。基于你提供的代码片段,下面是一个示例修改:
1 | use std::fmt; |
这里,我们使用std::fmt模块中的Display和Formatter,以及fmt::Result。write!宏用于向提供的formatter写入格式化的字符串。这与你原来为ToString实现的to_string方法中使用的逻辑相似,只不过这次是实现Display trait,并通过write!宏输出。
将ToString替换为Display之后,你的类型依旧可以使用.to_string()方法,因为Rust标准库会为所有实现了Display的类型自动提供ToString的实现。这样,你不仅遵循了Rust的最佳实践,还保留了将类型转换为字符串的功能。
warning: the item ignore is imported redundantly
1 | warning: the item `ignore` is imported redundantly |
这个警告意味着在你的Rust代码中,通过use ignore::{self, WalkBuilder, WalkParallel, WalkState};这行代码进行的ignore模块导入是多余的。具体来说,当你写ignore::{self, ...}时,self关键字代表ignore模块本身。但在这种情况下,Rust编译器指出ignore模块已经通过其他途径(比如Rust的预导入机制,即prelude)被导入到当前作用域中了,或者在这个上下文中,ignore可能直接就是当前包(crate)的一部分。
解释
在Rust中,预导入(prelude)是一个包含了Rust标准库中多数常用功能的小集合,这个集合自动被每个Rust程序导入,以减少需要手动导入的常用类型和trait的数量。然而,通常来说,ignore库并不在预导入中,所以这个警告可能是由于你的项目结构或模块的特定设置导致的。
如何解决
你可以通过移除对ignore模块的显式自引用来解决这个问题。如果ignore是你的代码中直接使用的外部crate,那么这个警告可能是不正确的——这种情况下,它不会被预导入机制导入,除非有特殊的项目配置导致这种行为。
为了解决这个警告,你应该检查是否真的需要在这里显式引用ignore模块本身。如果你的代码中没有直接使用ignore模块(比如通过ignore::something()这样的方式调用),那么你可以安全地移除self:
1 | use ignore::{WalkBuilder, WalkParallel, WalkState}; |
如果这个警告是误报(可能由于特定的项目设置或其他原因),并且你确实需要这样的导入语句,考虑检查项目的配置或查看Rust社区的最佳实践和指南,看看是否有推荐的处理方式。然而,大多数情况下,简单地移除冗余的部分并根据编译器的指导进行代码调整即可解决这类警告。
cargo fmt
1 | warning: `/Users/fliter/.cargo/config` is deprecated in favor of `config.toml` |
这个警告信息是指在Rust的包管理器Cargo中,旧版本的配置文件.cargo/config已经被弃用,取而代之的是新的config.toml文件。
具体来说:
警告信息说明你的用户根目录
/Users/fliter下有一个.cargo/config的旧配置文件,这种格式已被废弃。新版Cargo使用的是
config.toml文件,这是一种更结构化、可读性更好的TOML格式配置文件。注意部分提醒,如果你需要兼容旧版本的Cargo(1.38或更早),可以创建一个符号链接,将
config链接到config.toml文件。
为了解决这个警告,你有两个选择:
创建一个新的
config.toml文件,通常位于~/.cargo/config.toml或项目根目录下。将原来config文件中的配置迁移到新文件。如果确实需要兼容旧版Cargo,可以创建符号链接:
1 | ln -s ~/.cargo/config.toml ~/.cargo/config |
这条命令在.cargo目录下创建一个名为config的符号链接,指向config.toml文件。
采取以上措施之后,下次使用Cargo就不会再看到这个警告了。
删除掉.cargo/config就行了
cargo fmt 和cargo fmt –check有何区别?
cargo fmt 和 cargo fmt --check 都是用于格式化 Rust 代码的命令,但它们有一些区别:
- 格式化行为
cargo fmt 会直接对源代码文件进行格式化,将代码格式调整到符合 Rust 官方代码风格指南。这个命令会直接修改源文件。
cargo fmt --check 则不会修改源文件,只会检查代码是否符合代码风格指南。如果代码格式有问题,它会输出需要修改的地方,但不会直接修改文件。
- 退出码
cargo fmt 在格式化完成后总是会返回 0 作为退出码。
cargo fmt --check 如果代码格式有问题,会返回非零的退出码,通常是 1。如果代码格式没有问题,则返回 0。这使得 cargo fmt --check 可以被用于持续集成环境中,检查代码格式并在格式有问题时中止构建过程。
- 输出
cargo fmt 在格式化代码时不会产生太多输出,除非发生错误。
cargo fmt --check 会输出需要格式化的代码行以及对应的问题,方便开发人员定位并修复。
总的来说,cargo fmt 用于直接格式化代码,而 cargo fmt --check 用于检查代码格式,并且更适合在持续集成环境中使用。大多数情况下,开发人员会先运行 cargo fmt --check 检查代码格式,解决所有格式问题后,再运行 cargo fmt 对代码进行实际格式化。
Improve Your Code With Linting
编写干净、惯用的代码并不容易。你需要考虑风格、约定、代码复杂性、性能等诸多因素。当一组开发者在同一个项目上工作时,问题变得更加复杂。幸运的是,我们有一个工具可以帮助我们写出更好的代码 — 我说的是代码检查工具(linters)。代码检查工具可以自动检查代码的风格、正确性、复杂性、代码气味等。在今天的视频中,我们将介绍如何利用代码检查来改善你的Rust代码。
在我们开始之前,请确保通过访问letsgetrusty.com/cheatsheet获取你的免费Rust速查表。说完这些,我的Rust同事Tommy将为大家解释如何在Rust中使用代码检查。
谢谢Bogdan。Rust编译器(称为rustc)内置了一系列代码检查,这些检查会在编译过程中进行评估。你可以通过运行”rustc -W help”或参考rustc手册来查看完整的检查列表。此外,这些检查被整合成几个组,我们稍后会在视频中讨论。
每个检查都被设置为一个级别。可用的级别有:allow(允许)、warn(警告)、force-warn(强制警告)、deny(拒绝)和forbid(禁止)。
- allow告诉检查工具忽略违反该检查的情况。
- warn告诉检查工具在违反该检查时产生警告。
- force-warn与warn相同,但不能被覆盖。
- deny告诉检查工具在违反该检查时产生错误。
- forbid与deny相同,但不能被覆盖。
让我们看看这些检查如何影响你的代码。这里有一个简单的Rust程序示例:我们有一个名为Point的结构体和一个名为get_random_point的函数。在main函数中,我们创建两个随机点并打印其中一个。
要运行rustc检查工具,我们可以编译程序或运行cargo check。运行cargo check后,我们看到三个警告:一个是关于未使用的变量bar,违反了unused_variables检查;一个是关于Point结构体中未使用的字段,违反了dead_code检查;还有一个是关于函数名不是蛇形命名法,违反了non_snake_case检查。这些警告之所以出现,是因为它们的默认级别被设置为warn。
然而,我们可以通过添加检查属性来覆盖这些检查的默认级别。例如,我们可以直接在Point结构体、get_random_point函数和bar变量上添加allow检查属性,或者在main.rs顶部添加整个crate级别的allow检查属性。这些检查级别的覆盖将影响crate中的所有代码。注意,在添加crate级别的属性时,必须在#号后使用感叹号。
如果我们再次运行cargo check,我们就不会看到任何警告了。
覆盖默认检查级别有几个原因:
在原型开发时,我倾向于禁用与未使用代码相关的检查,这样我就可以专注于处理编译时错误。这可以通过指定单个检查或检查组来实现。例如,我们可以将unused组中的所有检查级别更改为allow,这包括dead_code检查和unused_variables检查。
对于生产代码,你可能想将unused检查组的级别更改为deny,这样未使用的代码就会导致编译时错误。此外,你还可以将non_standard_style检查组的级别更改为deny。
做出这些更改后,运行cargo check将产生几个错误。要修复这些错误,我们需要将函数名更新为蛇形命名法,使用bar变量,并确保Point结构体的x和y字段被使用。
现在我们已经介绍了代码检查的基础知识,让我们讨论一下Rust自带的另一个工具,叫做Clippy。Clippy是一系列检查的集合,用于捕捉常见错误并改进你的Rust代码。它是rustc检查的超集,实际上它在内部运行cargo check,而且比rustc更加固执己见。当你通过rustup安装Rust时,Clippy也默认包含在内。
如果我们对之前的代码示例运行cargo check,我们不会看到任何警告。但是,如果我们运行cargo clippy,我们会得到一个警告,指出我们使用了被列入黑名单的变量名foo。
正如你所看到的,Clippy更加固执己见,这会导致更多的检查警告。Clippy还提供了一些额外功能。例如,你可以运行”cargo clippy –fix”来自动应用一些检查建议。此外,除了通过属性更改Clippy检查级别外,你还可以在一个名为clippy.toml的单独文件中配置检查级别。
要了解更多关于Clippy功能以及如何向Clippy添加新检查的信息,请查看Clippy的GitHub仓库。
如你所见,Rust为我们提供了出色的代码检查工具来改进我们的Rust代码。在你离开之前,请确保通过访问letsgetrusty.com/cheatsheet获取你的免费Rust速查表。说完这些,我们下次再见。
Linting Rust Code With Clippy CLI Rules 🤯🦀 Rust Programming Tutorial for Developers
大家好,我叫Trevor Sullivan,欢迎回到我的视频频道。非常感谢你们加入我们的另一个Rust编程教程系列视频。
在这个特定的视频中,我们将重点关注一个工具,你可以在Rust工作流程中使用它来编写更健壮和高性能的代码,而且你还可以通过使用这个工具来学习更多关于Rust编程语言的知识。这个叫做Clippy的工具通常包含在Rust安装中,当你使用rustup安装程序安装Rust工具链时,它包括了rustdoc CLI、cargo CLI和Rust编译器rustc。
Clippy是一个非常酷的工具,因为它能够检查你的代码文件,并就如何改进你的代码项目提出建议。最终,当你使用Clippy来帮助指导你编写Rust代码时,你会得到更多的代码一致性,可能会得到一些你甚至不知道可能的新Rust代码技术的建议,而且你还可以确保在团队环境中的一致性。当你开始有多个团队成员都在同一个项目上工作时,这是一个非常重要的事情。你知道,一个团队成员可能更喜欢某种语法或使用某种方法,但另一个团队成员可能使用不同的机制来完成同样的任务。因此,通过使用Clippy,它提供了这些护栏,以确保你的整个团队都在遵循相同的Rust代码编写最佳实践。
正如我提到的,Clippy是Rust工具链的一部分。然而,如果你安装的是最小版本的Rust工具链,那么这个组件可能没有被安装。事实上,如果你安装的是最小版本的工具链,它很可能没有被安装。但幸运的是,如果你使用的是rustup安装程序,你可以简单地指定你想要在你的Rust安装中添加Clippy组件,那就会在你的环境中安装Clippy,然后你就可以随时调用Clippy了。
你可以在命令行中使用Clippy,当你构建Rust代码时,但你也可以将Clippy作为CI/CD管道的一部分。所以,每当你的团队成员进行git commit然后git push到你的代码仓库时,作为在那个push事件期间被触发的CI/CD管道的一部分,你可以执行Clippy工具。你可以在配置文件以及命令行参数中设置一些配置选项,然后如果Clippy在你的代码中发现任何问题,你实际上可以中止你的管道的执行,让开发人员回去修复任何代码问题,然后继续更新,再次进行git commit和git push,并修复这些类型的问题。
所以你可以把Clippy作为一种学习工具,你可以把它作为一种把关工具(以一种好的方式,而不是坏的方式),你可以帮助确保你的团队正在编写一致的、高质量和高性能的代码。现在有超过650个lint规则。我知道Clippy文档书中说有600个lint规则,但如果你查看Clippy的开源仓库,你可以看到在他们最新版本的readme中,他们确实自豪地声称有超过650个lint规则可用。
当我们谈论linting时,linting基本上就是当一个软件工具检查你的源代码文件,并寻找任何可能的改进或你可能遇到的任何潜在错误。这有助于你尽早在开发生命周期中捕获错误。你真的不想在构建过程中可能花20分钟,然后才意识到你的代码中有一个问题。如果你能尽早从Clippy那里得到即时反馈会好得多,这样一旦你在代码中遇到某种警告或错误,你就可以立即回去修复它,推送更新的代码,并尽快得到反馈。
所以我强烈建议使用Clippy,你可能会想,作为一个Rust初学者,为什么我想引入更多的护栏?为什么我想引入更多的问题,当我已经在试图学习Rust编程语言,可能已经遇到了一堆障碍?好吧,再次强调,这将根据这些linting规则提供指导。这些规则不仅被配置为检测问题,还提供建议并加深你对这些特定问题的理解,这样下次你编写类似的代码时,你就可以以更好的方式编写代码。所以我实际上认为,在你的Rust学习周期中,从这些工具中得到这些错误和警告是一件积极的事情,因为你能够有一个工具为你提供那些护栏。所以把这看作是一种会伴随你,帮助你提供更好的Rust代码编写建议的东西,而不是把它看作是一种阻碍或阻挡你的东西,因为它实际上最终是在帮助你编写更好的Rust代码。
现在这650个lint规则是很多不同的规则,它们在Clippy中被分类成这些默认类别。我们有clippy::all, clippy::correctness, clippy::suspicious, clippy::style, clippy::complexity, clippy::performance相关的东西,默认情况下,每个这些类别都应用了某些警告或允许级别。例如,如果你看一些围绕cargo manifest文件的东西,那些默认情况下是被允许的,但如果你想让特定的规则被捕获为警告或实际上阻止执行并在你运行Clippy工具时出错,那么你可以把这里的默认级别从allow改为warn或deny。我们稍后会更详细地讨论这些级别,但基本上每个这些类别都被分解成这些针对你的代码中非常精确的建议的单独规则。
所以它会在你的代码中寻找某些模式,它会寻找某些方法调用,它会查看你传入函数的参数数量,或者也许你的函数代码有多长,诸如此类的事情。其中一些事情实际上也有可定制的参数。实际上有一个单独的配置文件,我们可以在Clippy中使用,来告诉它如何应用这些不同的规则。
如果我们看一下这个配置部分,这里有一个特殊的文件,你可以添加到你的项目中,叫做clippy.toml,或者你可以用.clippy.toml来隐藏它。它会在你的项目目录中寻找那个文件,或者你实际上可以指定一个环境变量来定位那个配置文件,或者你可以指定这个manifest目录,你的cargo manifest所在的位置。但默认情况下,它只会在你的shell指向的当前目录中查找。所以这是使用它的最简单方式,而不是必须设置这些环境变量中的一个。
但在这个配置文件内部,它基本上就是一个ini或toml类型的文件格式,但它实际上没有任何标题。所以你没有那些带有标题的方括号,就像你在cargo.toml文件中那样。我们所做的就是设置一个变量,我们将变量设置为某个值,你可以在实际lint的文档中找到所有这些输入配置选项或这些变量以及它们支持的值。
所以如果我们看一下这里的readme,然后点击这个链接去到linting规则页面,这会直接带我们到这个Clippy lint页面。这会向你展示所有这些单独的规则,如果你愿意,你实际上可以按组过滤它们。所以我们可以说我只想看与我的cargo.toml配置相关的东西,或者也许我想看与性能相关的东西。所以我’ll只点击none,然后包含performance组,正如你所看到的,这里有相当多的与性能相关的规则。
然后一旦你找到一个规则,比如说让我们看一下to_string,例如,如果你正在使用println!宏,你正在输入一个字符串,你在它上面调用to_string方法以便将其转换为字符串,这个规则基本上是在检查那个,并说嘿,你实际上不需要调用to_string,因为你传入println!宏的东西已经实现了Display trait,所以因此println!宏能够解析如何将那个对象输入作为字符串表示。所以基本上它只是建议你消除这个to_string方法调用,这将提供更高性能的代码。
现在正如我提到的,Clippy是Rust工具链的一部分,然而,如果你安装的是最小版本的Rust工具链,那么这个组件可能没有被安装。事实上,如果你安装的是最小版本的工具链,它很可能没有被安装。但幸运的是,如果你使用的是rustup安装程序,你可以简单地指定你想要在你的Rust安装中添加Clippy组件,那就会在你的环境中安装Clippy,然后你就可以随时调用Clippy了。
现在你可以在命令行中使用Clippy,当你构建你的Rust代码时,但你也可以将Clippy作为你的CI/CD管道的一部分。所以每当你的团队成员做一个git commit然后git push到你的代码仓库,作为在那个push事件期间被触发的CI/CD管道的一部分,你可以执行Clippy工具。你可以在配置文件以及命令行参数中设置一些配置选项,然后如果Clippy在你的代码中捕获到任何问题,你实际上可以中止你的管道的执行,让开发人员回去修复任何代码问题,然后继续更新,再次进行git commit和git push,并修复这些类型的问题。
所以你可以把Clippy作为一种学习工具,你可以把它作为一种把关工具(以一种好的方式,而不是坏的方式),你可以帮助确保你的团队正在编写一致的、高质量和高性能的代码。另一件很好的事情是Cargo可以实际上自动修复一些这些问题。不幸的是,我没有看到任何种类的具体性在这里来确定一个规则是否可以自动修复,所以你将不得不玩一下个别规则来弄清楚它们是否支持自动修复,但有一个叫做–fix的参数,你可以传递给cargo clippy命令,那将自动触发任何这些问题的修复,如果它们支持自动修复的话。
我们也有这些linting级别。我之前简要提到过这些,并说我们会更深入地看一下它们。有allow、warn、deny和none,但实际上还有几个其他级别。所以如果我们回去看一下Clippy文档,看一下我认为它在使用部分下面,也许让我们看看它是否在这里,让我快速搜索一下,搜索levels。
无论如何,这些级别允许我们指定像force_warn和force_deny这样的东西,后者也被称为forbid。我不完全确定它在文档中的哪里,但有一个force_warn和一个forbid选项,你也可以设置,那些在这个接口中没有显示,但你可以使用它们来基本上防止有人覆盖那些特定的规则。
现在你实际上如何启用这些规则呢?有两种不同的方式可以做到这一点。第一种是你可以直接进入你的源代码,使用一个属性来配置这些lint。另一件你可以做的事是实际上在clippy命令行上指定linting规则。所以当你运行cargo clippy来调用Clippy工具时,你实际上可以指定你想要它在你的代码中警告或拒绝访问的规则。
所以这个例子右在这里要向你展示如何基本上拒绝所有规则。这是一个属性语法,你可以在整个模块或整个crate上使用,如果你在你的lib.rs文件中指定的话。所以你可以使用这个基于属性的语法,但你也可以使用这个语法,我们可以用-A允许,也有一个–allow是拼出来的。我通常更喜欢使用拼出来的参数,因为如果你在读你的代码时,它们更清晰,因为-a是相当模糊的,那可能意味着很多不同的东西,它可能意味着all,它可能意味着allow,它可能意味着一大堆不同的东西。所以我通常喜欢把这些拼出来。
同样,–warn或-W是你如何指定警告级别,如果你想拒绝某些东西,你实际上可以使用-D或–deny,然后指定规则的名称。你会注意到,当你指定一个规则的名称时,它需要以clippy和一个双冒号作为前缀,然后你可以指定规则的名称。所以如果你在这个文档中查看lint列表,只要记住,如果你在命令行中使用它,你需要使用以clippy双冒号为前缀的lint名称。
无论如何,我们将看一下一些这些规则,以及我们如何将它们纳入
好的,我会继续翻译和整理剩余的内容:
默认情况下,它只会在您的shell指向的当前目录中查找。所以这是使用它的最简单方法,而不是必须设置这些环境变量之一,但在这个配置文件中,它基本上只是一个ini或toml类型的文件格式,但它实际上没有任何标题,所以您没有那些带有标题的方括号,就像在cargo.toml文件中那样。我们所做的只是设置一个变量并将变量设置为某个值,您可以在实际lint的文档中找到所有这些输入配置选项或这些变量以及它们支持的值。
所以如果我们看一下readme,然后点击这个链接到linting规则,那会直接带我们到这个Clippy lint页面,这将向您显示所有这些单独的规则,如果您愿意,您实际上可以按组过滤它们。所以我们可以说我只想看与我的cargo.toml配置相关的东西,或者也许我想看与性能相关的东西。所以我只需点击none,然后包括performance组,正如您可以看到的,这里有相当多的与性能相关的规则。然后一旦您找到一个规则,比如说让我们看一下to_string,例如,如果您正在使用println!宏,并且您正在输入一个字符串,并且您在其上调用to_string方法以将其转换为字符串,这个规则基本上是在检查这一点,并说嘿,您实际上不需要调用to_string,因为您传入println!宏的东西已经实现了Display trait,因此println!宏能够解析如何将该对象输入转换为字符串表示。所以基本上它只是建议您消除这个to_string方法调用,您的代码仍然会完全正常工作。
现在这是只抱怨未使用的变量,但让我们看看我们是否可以强制它失败。所以如果我做一个cargo然后clippy命令,那将调用linter,正如您可以看到的,当我用cargo clippy调用clippy时,它将查看我们在源文件中声明的这些基于属性的规则,它将解析这些,它将查找这些linting规则的任何配置选项,然后使用静态分析评估我的代码,以查看是否有任何问题,正如您可以看到的,它说错误此函数参数太多。它说规则表明我们想要七个,再次,这是默认值,我没有在我的clippy配置中定制它,但我们实际上有八个参数。
所以现在让我们说我想自定义参数数量,这将导致违反这个规则。另外,再快速提一下,如果我们在bash中做Echo $?,您可以看到我们得到一个退出代码101。所以如果您在CI/CD管道中,并且您在那里做自动化,您可以检查该退出代码,看看它是101还是非零,这将表明在clippy linting中发生了某种错误,然后您可以立即中止构建过程,中止CI/CD管道,如果您使用SaaS供应商做CI/CD并且按分钟付费,比如GitHub Actions或者可能是Circle CI或Travis CI之类的,这将为您节省大量CI/CD分钟。所以这是一种很好的方法来检测是否有任何问题。
我们也可以把这个改成warn,说不是deny而是我只想警告这个,然后如果我们警告,我们不会得到非零退出代码,我们只会得到零退出代码,但在标准输出中我们仍然会看到有一些建议。
所以现在我们要做的是自定义参数数量。这个too_many_arguments lint规则的默认值是七个参数,所以我们放了八个参数来违反规则,但是让我们说我们想自定义它,说我想要最多四个参数。
所以再次,我们将抓取这个配置选项,它允许我们自定义这个特定的too_many_arguments规则,我们将在我们的项目中创建一个新的配置文件,我们将其称为.clippy.toml,您不必在开头加上句点,它也会查找clippy.toml,然后我们需要做的就是粘贴那个设置并将其设置为我们想要的值。所以我们的函数最多可以有四个参数,如果我们违反了这一点,那么我们将对该问题发出警告或者我实际上会把它改回deny。
所以现在我们将做cargo clippy,正如您可以看到的,我们有八个,但它现在只想要四个。这就是我们如何将该自定义选项应用于这个lint规则。所以现在如果我消除这些额外的参数,我将把它们放在一个注释中,以防我需要把它们放回去。
现在我们可以从这里的输入中消除这些,现在这应该满足规则。所以如果我们再次做cargo clippy,您可以看到我们得到了关于未使用变量的警告,但我们不再得到警告或者说拒绝,而是说我们有太多参数的错误。当然,如果我们回去再添加第五个参数并重新运行cargo clippy,那么我们将再次得到该错误以及101退出代码。
所以这就是我们如何应用属性来拒绝整个crate的这个特定规则,因为#!适用于父级,所以main.rs的父级是crate本身,所以这应该适用于我们的整个crate,我们也可以将东西应用到单个实体。所以如果我们想这样做,比如说我们想允许未使用的变量,对吧?
所以让我们做一些像未使用的东西,我们将搜索未使用的参数,我想,让我们搜索参数或未使用的变量,也许,我没有看到那个显示出来,但有一个允许未使用变量的,我不确定那个可能实际上不是一个clippy规则,但让我们看看这里可能有的其他类型的警告,看看我们是否能找到另一个。
所以,我认为另一个实际上是to_string,所以让我们继续搜索to_string,我认为那将是一个警告,一个与性能相关的类别警告。所以让我们继续尝试在一个例子中使用这个。所以如果我们有一个实现了Display trait的类型,我们在其上调用to_string,它应该捕捉到那个作为一个警告,正如您可以看到的,这里底部没有配置部分,所以这个特定设置没有额外的配置选项。所以我们要做的就是定义什么是这个to_string。
所以我们将定义另一个测试函数,我们将说test_string,让我们也修复这个,我们将继续删除那个第五个参数,这样它就满意了。所以我们可以在这里说我们想允许未使用的变量,所以让我们说let x等于5,我们也可以使用参数作为输入,比如arg1是一个无符号16位整数。
正如您所看到的,我们得到了未使用的变量,未使用的参数,再次得到了未使用的变量。所以如果我们只想在这个特定函数上允许未使用的变量,我们可以只使用一个#而不带感叹号,这将直接应用于属性定义后面的项目。所以我们可以说allow,然后在这里指定unused_variables,我不认为这是一个clippy规则,因为它没有以clippy为前缀,我也在clippy文档中找不到它。所以请注意,我认为那个只是内置在rust中。
所以现在您可以看到那些警告立即消失了,如果我们在这里运行cargo clippy,那么您可以看到我们只得到函数test_string从未被使用,但我们不会得到那些未使用变量的警告,就像我们在上面的test_lint函数中得到的那样。
所以如果我们注释掉那个属性并重新运行cargo clippy,我们应该在test_string函数上得到一个未使用变量,而之前它只报告test_lint函数上未使用的参数或变量。所以它抱怨我们没有使用test_string函数上的参数arg1,它抱怨我们没有使用我们在test_string函数体内声明的x变量,但我们想测试的规则是这里的to_string规则,对吧?
所以我们要做的是继续做一个println!操作,让我们做println!,我们将指定花括号,然后我们将传入我认为x,我不确定它是否明确实现了Display,但我猜它可能实现了,我们也可以使用一个字符串值,比如”hello from rust Trevor”,然后我们将传入x,是的,那很好,它是一个字符串,然后我们可以在这里做.to_string。所以现在我们正在取一个字符串切片,我们实际上通过调用to_string方法将其转换为堆分配的字符串。
所以现在如果我们做cargo clippy,那么您应该看到这个警告,它说to_string被应用到一个已经实现Display trait的类型上。所以这又是一个与性能相关的东西,它说嘿,您实际上不需要这个to_string方法调用,所以继续消除它,您的代码仍然会完全正常工作,对吧?所以一旦我们在这里重新运行,我们不再得到那个警告,这有助于通过默认提供那个linting护栏来提高我们应用程序的性能。
再次说明,该特定规则的默认级别是警告,所以它不会默认允许它,但有一些东西默认是允许的,您可以为它们启用警告或拒绝操作,比如这里的这些。如果您只是按允许规则过滤,那么这些是默认允许的类型的东西,但您可以在配置中启用它们,您实际上可以设置一个警告属性或一个拒绝属性。
为了在命令行指定这些规则,这是第二种方法。到目前为止,我们已经看了应用于crate级别、父级别和个别函数级别或个别结构级别、枚举和traits等的基于属性的语法,但如果我们想在我们的CLI中包含其中一些规则,我们可以做cargo clippy,看一下帮助,然后我们可以警告、允许、拒绝或禁止我们代码中的某些东西,禁止将是最严格的,因为那将基本上忽略您有的任何覆盖,所以那是如果您想在代码中禁止某些东西的最严格选项,但让我们只说现在,我们想也许允许,让我们看看,让我们允许这里的to_string函数,对吧?
所以我们将再次做x.to_string,但这次我们将继续指定我们想在我们的clippy CLI中允许它,而不是将其指定为基于属性的语法。所以我们要做的是说cargo clippy,然后在这里放两个破折号,因为那将阻止任何参数被传递给cargo,两个破折号之后的任何东西都将被clippy本身解释,而不是cargo,所以我们要做的是说我们想也许允许clippy,然后它叫什么,让我们在这里对to_string警告做一个过滤。所以它叫做to_string_in_format_args,所以我们基本上想做clippy::然后to_string_in_format_args。
让我看看我能不能从某个地方复制那个,我只会在这里复制它,我们会点击那个按钮,然后我们会做clippy::然后粘贴那个,哦,当然,当我复制它时,它包含了前缀。所以现在如果我们运行这个,您可以看到我们没有得到那个特定的警告,如果我们运行时没有那个参数,我们确实得到这个警告,说to_string被应用到已经实现Display trait的类型,但如果我们用–allow运行,那将消除那个警告的出现。也如果我们想把那个警告改成拒绝,我们可以简单地指定–deny而不是allow,所以现在这将在clippy调用期间导致一个错误,那将早早地捕获那个规则,现在我们得到一个101退出代码。所以再次,我们可以中止我们的管道。
所以这些真的是应用事物的两种方式,我们可以在属性级别做到这一点,以获得整个crate的某种全局范围,我认为在模块范围内也可以工作,所以如果您有一个子模块,您可以将这个属性插入到那里,我想那可能会工作,然后我们也可以使用这个语法来应用到直接跟随的元素,当我说元素时,当然我指的是函数、traits、枚举、结构体等等。
好的,让我们看看clippy的快速修复或自动修复。你可能早些时候注意到,当我们做cargo clippy –help时,cargo CLI实际上有一个–fix选项。所以你要把这个传递给cargo而不是clippy,所以你要在双破折号之前放它,那将是一个传递给cargo的选项,双破折号之后的任何东西都会传递给clippy特别地。所以如果我们做cargo clippy –fix,然后在那之后插入我们的clippy选项,那么我们就可以应用
我理解您的要求。我会按照原文的顺序整理内容,使其更加合理通顺,同时保留所有细节,不会省略或总结任何内容。然后我会将整理后的内容翻译成中文。以下是整理和翻译后的内容:
让我们来看看Clippy的快速修复或自动修复功能。你可能注意到,当我们运行”cargo clippy –help”时,Cargo CLI实际上有一个”–fix”选项。你需要将这个选项传递给Cargo,而不是Clippy。也就是说,你要把它放在双破折号之前。双破折号之后的任何内容都会被传递给Clippy。
如果我们运行”cargo clippy –fix”,然后在后面添加我们的Clippy选项,我们就可以应用自动修复。让我们看看是否有一个自动修复可以移除这个to_string方法的调用。
目前的情况是,如果我们在这里使用deny,我们会在to_string这里得到一个错误,因为我们在命令行中将默认的警告改成了显式的deny。但现在,我们要在这些双破折号之前添加”–fix”。
你可以看到,默认情况下它会警告我们有未提交的更改。但是,很像发布操作(我们可能还没有讨论过向crates.io注册表发布crate),我们可以指定一个叫做”allow-dirty”的参数。这可以防止我们在运行这个命令时需要提交更改。所以我们可以直接说”allow-dirty”。
我认为这是传递给Cargo而不是Clippy的参数,所以让我们把它移到双破折号之前。我们把双破折号放在它后面,现在我们应该有一个修复了。
你可以看到,这自动修复了我们的代码。我们可以用Ctrl+Z来撤销这个更改,然后如果我把这个稍微往下移一点,重新运行cargo clippy命令,你可以看到它自动为我修复了这个问题。
我不必手动修复它,因为也许我的代码中有100或200个不同的地方不必要地调用了to_string,这将处理并修复所有这些实例,这样我就不必手动寻找并解决它们。这是一个真正的时间节省器,你可以通过Clippy CLI工具获得。
如你所见,它非常强大。这里有许多不同的规则,分布在这些不同的组中。这种分组真的很好,因为如果你想查找与性能相关的问题,比如你可能遇到了一些性能问题,想要专门解决性能问题,你可以只过滤这些基于性能的规则,看看你能找到什么。
让我清除一下那个搜索,所以这里所有的规则都是与性能相关的。我们可以对所有这些不同的规则运行Clippy,看看它们是否适用。此外,如果这些规则中的任何一个有配置选项,比如这个,我们也可以在我们的clippy.toml文件中指定这些选项。
我强烈建议你亲自动手使用Clippy。也许对一个现有的Rust项目运行Clippy,如果你已经开始构建自己的Rust项目,看看它会抛出什么样的警告或错误。
也要确保将Clippy纳入你的CI/CD工作流程中。如果你使用GitHub Actions、GitLab CI/CD或者可能是OneDev CI/CD,进入你的配置文件,将这个Clippy命令作为你流程中的早期步骤添加进去,以便尽早在你的管道中捕获这些错误,这样你就不用等待很长时间构建完成,然后才意识到你有一些问题。
强烈建议你玩玩Clippy,玩玩这些不同的规则,玩玩这些不同的配置选项。你可以使用CLI或者基于属性的语法来应用规则更改。如果你决定走CLI路线,当然你会在这里指定这些CLI参数,在你的CI/CD配置文件中,无论你在CI/CD管道中运行的是什么脚本,你基本上就是在你调用Clippy的CLI脚本中添加所有这些deny和allow参数。
然后你当然可以始终检查退出代码101,看看是否有问题,然后你可以中止管道,或者你可以只发送一封电子邮件或Slack消息给你的开发团队,表明Clippy捕获到了一些问题,然后如果你觉得这种方法可以接受的话,可以继续构建。但是,这完全可以根据你正在编写的每个Rust项目进行定制。
无论如何,我想这就是我想要涵盖的关于Clippy工具的所有内容。我强烈建议,特别是初学者使用它,因为它确实能帮助你编写更好的代码,帮助你更多地了解Rust语言和标准库,它只是一个很棒的工具,可以帮助提高你的Rust构建的效率。
再次,如果你从这个视频中学到了什么,请给这个视频点赞,请在下面留言,让我知道你的想法,并订阅频道,点击那个铃铛图标,这样你就能在新视频发布时收到通知。我很想听听你对整个播放列表的看法。感谢观看,我们很快会再见。保重。
hey guys my name is Trevor Sullivan and
welcome back to my video channel thanks
so much for joining me for another video
in our rust programming tutorial series
now the topic that we’re going to be
focusing on in this particular video is
actually a tool that you can use in your
rust workflow in order to write more
robust and higher performance code plus
you can actually learn more about the
rust programming language by using this
tool now typically this tool called
clippy is included with an installation
of rust when you use the rust up
installer in order to install your rust
tool chain which includes things like
the rust dock CLI the cargo CLI and the
rust compiler which is rust C now clippy
is a really cool tool because it is able
to kind of inspect your code files and
make recommendations on what you can
improve in your code project so
ultimately when you use clippy to help
provide guidance to you when you’re
writing your rust code you get more code
consistency you get recommendations
about maybe new techniques in your rust
code that you didn’t even know were
possible and you can also ensure
consistency across a team environment
this is a really important thing when
you start to have multiple team members
that are all working on a similar
project you know one team member might
prefer a certain syntax or they might
use a certain method but a different
team member might use a different
mechanism in order to accomplish the
same task and so by using clippy it kind
of provides these guard rails to make
sure that your entire team is on board
and following the same best practices
for writing rust code now as I mentioned
clippy is part of the rust tool chain
however if you installed the minimal
version of the rust tool chain then this
component may not have been installed in
fact it probably wasn’t installed if you
installed the minimal version of the
tool chain but thankfully if you’re
using the rust up installer here you can
simply specify that you want to add the
clippy component into your rust
installation and that’ll get clippy
installed in your environment and then
you can go ahead and call clippy anytime
that you want to now you can use clippy
at the command line while you’re
building your rust code but you can also
incorporate clippy as part of your CI CD
pipelines so anytime that one of your
team members does a git commit and then
get push up to your code repositories as
part of that CI CD pipeline that gets
kicked off during that push event you
can execute the clippy utility you can
set up some configuration options as
well in a configuration file as well as
command line parameters and then if
clippy catches any issues inside of your
code you can actually abort execution of
your pipeline and have the developer go
back and fix whatever code issue there
is and then go ahead and update do
another git commit git push and fix
those types of issues so you can use
clippy as kind of a learning tool you
can use it as a gatekeeping tool in a
good way not a bad way and you can help
just ensure that your team is writing
consistent and high quality and high
performance code now there are over 650
lints I know the clippy documentation
book here says 600 lengths but if you
check out the open source repository
here for clippy you can see that in
their latest version of their readme
they do boast having over 650 linting
rules available and when we talk about
linting linting is basically just when a
software utility inspects your source
code files and looks for any potential
enhancements that you could make or any
potential errors that you could run into
and this helps you to catch errors as
early in your development life cycle as
possible you don’t really want to get
you know maybe 20 minutes into a build
process and then realize later down the
line that you have an issue with your
code it would be a lot better to get
that immediate feedback from clippy
early on in the development process so
that as soon as you run into some kind
of warning or error inside of your code
you can go back fix that immediately
push the updated code and get that
feedback as quickly as possible so I
highly recommend using clippy and you
might be thinking as a rust beginner
well why do I want to introduce more
guard rails why do I want to introduce
more issues when I’m already trying to
learn the rust programming language and
maybe hitting a bunch of brick walls
well again this is going to provide a
guidance based on these linting rules so
the rules are configured to not only
detect issues but also to provide
recommendations and to deepen your
understanding of what those specific
issues are so that the next time that
you write similar code like whatever you
caught previously with one of these
linting rules you can write code in a
better way so I actually think that
getting these errors and warnings from
these utilities is a positive thing in
your learning cycle of rust because you
are able to have a tool that’s providing
those guard rails for you so look at
this as something that’s going to kind
of come alongside you and help provide
better recommendations on how to write
rust code rather than looking at it as
an inhibitor or something that’s
blocking you because it’s actually
helping you ultimately to write better
rust code now these 650 lints those are
a lot of different rules and they are
categorized into these default
categories in clippy so we’ve got clippy
all we’ve got clippy correctness we’ve
got suspicious style complexity
performance related things and by
default there are certain warning or
allow levels that are applied to each of
these categories so for example if you
look at something around the cargo
manifest files right those by Def
defaults are going to be allowed but if
you want specific rules to be caught as
warnings or actually block execution and
error out when you run the clippy
utility then you can change the default
level here from allow to maybe warn or
deny we’ll talk a little bit more about
those levels in just a moment but
basically each of these categories are
broken down into these individual rules
that Target very precise recommendations
inside of your code so it’ll look for
certain patterns in your code it’ll look
for certain method calls it’ll look at
the maybe the number of arguments that
you’re passing into a function or maybe
how long your function code is and
things of that nature and some of these
things actually have customizable
parameters on them too there’s actually
a separate configuration file that we
can use in clippy to kind of tell it how
to apply these different rules so if we
take a look at this configuration
section right here there’s a special
file that you can add into your project
called clippy.tomel or you can hide it
with Dot clippy.tomel and it’s going to
look for that file in your project
directory or you can actually specify an
environment variable for where to locate
that configuration file or you can
specify this manifest directory where
your cargo manifest is located but by
default it’s just going to look in the
current directory wherever your shell is
pointing to so that’s kind of the
easiest way to use it rather than having
to set one of these environment
variables but inside of this
configuration file it’s basically just
an ini or Tamil kind of file format here
but it doesn’t really have any headings
so you don’t have those square brackets
with the headings like you do in the
cargo.tomo file all we do is we set a
variable and we set the variable to a
certain value and you can find all of
these input configuration options or
these variables and the supported values
for them in the documentation for the
actual lints themselves so if we take a
look at the read me over here and then
click on this link to go to the linking
rules here that’ll take us directly to
this clippy lints page here and this is
going to show you all of these
individual rules and if you’d like to
you can actually filter them by group
here so we could say I would just want
to see things related to my cargo.tommel
configuration or maybe I want to see
things that are performance related so
I’ll just click on none and then include
the performance group right here and as
you can see there are quite a few
performance related rules right here and
then once you find a rule like maybe
let’s take a look at uh two string for
example so if you are using the print
line macro here and you are taking a
string as input and you call the
tostring method on it in order to
convert it to a string this rule is
basically checking for that and saying
hey it’s not necessary for you to call
tostring because the thing that you’re
passing in to this print line macro
already implements the display trait and
so therefore the print line macro is
able to decipher how to convert that
object input as a string representation
so basically it’s just going to
recommend that you eliminate this two
string method call and that will provide
higher performance code now another nice
thing about cargo is that it can
actually fix some of these issues
automatically unfortunately I didn’t see
any kind of specificity in here to
determine if a rule is automatically
fixable or not so you’ll kind of have to
play around with the individual rules to
figure out if they are supported for
automated fixing but there’s a parameter
called dash dash fix that you can pass
in to the cargo clippy command and that
will automatically trigger a fix for any
of these issues for you if they support
an automated fix also we’ve got these
linting levels so I mentioned these
briefly earlier and said we’d take a
deeper look at them there’s allow warn
deny and none but there’s actually a
couple of other levels as well so if we
go back and take a look at the clippy
documentation and take a look at I think
it’s under the usage section here maybe
let’s see if it’s in here let me just do
a quick search and search for levels
here
so in any case the levels allow us to
specify things like force Warn and force
deny it which is also known as forbid as
well I’m not entirely sure where that is
in the documentation here but there’s a
force worn and a forbid option that you
can set as well and those are not
displayed inside of this interface here
but you can use those to basically
prevent somebody from overriding those
particular rules now how do you actually
enable these rules well there’s really
two different ways that you can do this
number one is you can actually go
directly into your source code and you
can use an attribute in order to
configure these lints and the other
thing that you can do is actually
specify the linting rules on the clippy
command line so when you run cargo
clippy to invoke the clippy utility you
can actually specify which rules you
want it to either warn or deny the
access to in your code so this example
right here is going to show you how to
basically deny all rules this is an
attribute syntax that you would use
across an entire module or across an
entire crate if you are specifying that
in your lib.rs file so you can use this
attribute-based syntax but you can also
use this syntax down here where we can
allow with Dash capital A there’s also a
dash dash allow that’s kind of spelled
out I generally prefer to use the
spelled out parameters just because
they’re more clear if you’re reading
your code because Dash a is pretty
ambiguous that could mean a lot of
different things it could mean all it
could mean allow it could mean a whole
bunch of different things so I generally
like to spell these out also dash dash
warn or Dash capital W is how you can
specify a warning level and if you want
to deny something you can actually use
Dash capital D or dash dash deny and
then specify the name of the rule and
you’ll notice that when you specify the
name of a rule it does need to be
prefixed with clippy and then a double
colon here and then you can specify the
name of the rule so if you’re looking at
the list of lengths in this
documentation right here just remember
that you need to use the lint name
prefixed by clippy double colon if
you’re using it inside of the command
line when you run cargo clippy so in any
case we’re going to look at a couple of
these rules and how we can incorporate
them into our code and we’ll take a look
at the parameters on the cargo clippy
CLI tool so that you can understand how
it works in practice as well as the
automated fixes that we can apply to our
code in order to fix changes or fix
issues in our code without having to go
and manually seek out those issues and
fix them on a line by line basis which
can ultimately save you a lot of time
when you’re working on a large project
but before we jump into our example I
just wanted to invite you to subscribe
to my YouTube channel here at
youtube.com Trevor Sullivan I’m an
independent content creator so any kind
of support that you can provide to this
channel is extremely helpful in the
pinned comment below I’ll leave some
links that you can use as affiliate
links and you can optionally use those
to do some online shopping and if you
make a purchase through there I’ll get a
small portion of the proceeds of that
particular sale so please consider doing
that also you can go out to my channel
here and find the rust programming
tutorial playlist we’re up to 28 videos
so this will be video number 29 and
there’s a whole bunch of rust Concepts
inside of this playlist here that we go
really into depth and Hands-On with so
feel free to check out this entire
playlist here and you know pick up any
knowledge that maybe you have a gap on
if you need threading knowledge if you
need to learn about iterators and how to
kind of work with the different methods
on there if you want to learn about hash
maps and hash sets there’s a whole bunch
of different Topics in here so feel free
to go through this playlist also if you
learned something from this video please
leave a like on the video that helps to
kind of promote to this video in the
algorithm and also leave a comment down
below and just let me know what you
thought of this video the style and
format and also let me know what other
kind of rust topics you want to see on
my channel and in this playlist right
here so with that out of the way let’s
go ahead and spin up a brand new project
and we’ll take a look at how to use
clippy so I’m going to switch over to my
integrated development environment which
is Microsoft Visual Studio code I’m
running it on Windows 11 that’s my
development workstation locally but as
you probably have seen in my earlier
videos especially the first video I talk
about how to set up a remote development
environment against a remote Linux
server so I actually have a virtual
machine running with lexd which I have
another playlist series on setting up
Lex D on a bare metal Linux server and
this virtual machine is just running a
headless Ubuntu Server distribution
using the latest LTS distribution of
Ubuntu and I have vs code remotely sshed
into that virtual machine so when I run
a shell here and do use things like rust
C then this is actually going to be
running on a Linux distribution rather
than on my local Windows system and this
is really nice because it allows me to
kind of switch back and forth between
different systems and I have a
consistent development environment so if
I go use my laptop upstairs you know I
can just load up my SSH session that I
was working on on my development
workstation in my office and I can just
pick up where I left off so I’d strongly
recommend that you invest some time into
learning how to set up that remote
development environment because in the
long run it’ll make you a more
productive developer but as you can see
I have rust installed here I’ve got the
latest version of rust 1.72.1 and rust
up is how you typically install rust
especially on a Linux server and if we
take a look at our components here we
want to basically verify that clippy’s
installed so what we can do is say rust
up and then go into this component
context and then we can say list
installed and available components so
just do a rust up component list and
then if you do a shift Ctrl F I think or
maybe just control F in here and then
search for clippy you can see that the
cargo components installed the clippy
component is installed rust docks are
installed rust source is installed and
there are a bunch of components that I
don’t need on this particular system
that aren’t installed but any of these
bolded items here that have installed at
the end are going to be present on your
system if you want to inspect the file
system to verify that clippy is
installed then you can actually just go
to your home directory
so we’ll say dollar home and we’ll go
into the dot rust up folder here then we
can go into the tool chains folder right
here and you can see I’ve got the stable
tool chain I don’t have nightly
installed on this system and then if we
go into that specific tool chain version
we can take a look at bin and inside of
the bin directory you should see that
there’s a cargo Dash clippy binary that
you can execute so if we execute the
cargo CLI and then run clippy afterwards
then that’s going to be how we invoke
this utility so if we do cargo clip e
dash dash help you can see we’ve got
this dash dash fix parameter right here
that allows us to automate fixes in our
source code it also shows us how to use
this attribute here to allow or deny or
warn on certain linting rules in our
code and then these options right down
here are going to allow us to at the
command line when we actually run cargo
clippy we can specify warn allow deny
and forbid as additional customizations
for which rules we want to enable or
disable right and then don’t forget
about the configuration file we’ll take
a look at some specific configuration
options as we go through the individual
rules but if we do something like let’s
search for args down here and go to all
lint levels and we want to look for one
called the number of arguments
so if we take a look at I think it’s
number of arguments or argument count or
something like that too many arguments
so let’s do that two many arguments so
in this particular rule here you’re
basically just inspecting the number of
arguments in a function and it has this
configuration section so when you’re
looking at a lint rule for clippy you
want to look at this configuration
section and see if it specifies any
additional configuration options and
then these configuration options are
what you can place into that Tamil
configuration file specifically for
clippy and that will customize how this
specific rule executes against your code
so let’s go ahead and write some simple
code in a project so we’ll start by
creating a project directory in here
we’ll just do a maker and then specify a
folder like lint Dash test
and then we’ll go ahead and open that up
so I’ll do Ctrl K Ctrl o and we’ll open
up the lint test folder in our editor
which will reload the window and get us
connected to that specific project so
now we have this empty folder and we’ll
just do a cargo in it in this directory
and now we have our simple scaffolded
out binary project here you could also
do a cargo init and specify dash dash
lib if you want to create a library
instead with lib.rs but for now I’m just
going to go ahead and create a binary
application with a main entry point so
now what we can do is start by
specifying some rules in our code using
attributes so let’s actually use this
example right here of too many arguments
and let’s say that we want to prevent or
deny a build of our code if we have too
many arguments so we want to use the
deny attribute in our code so we do a
hashtag and then an exclamation point
and then we can say deny
and then inside of this deny attribute
we can specify which linting rules we
want to block the build on so in this
particular case we can just hit control
space and see a list of all of these
different rules right here and so we
want to use the two many arguments rule
so we’ll pass in clippy double colon and
then two many arguments and that way if
we have more than by default seven
arguments you can see right down here
the documentation says it defaults to
seven so if we have eight arguments in
our function definitions then that will
breach this Rule and cause an issue so
for starters before we actually apply
the customization Let’s do let’s declare
a function
called test lint and inside of the
function declaration here
let me just call it so that it’s not
complaining about us not calling it here
and inside of the function definition
we’re going to specify eight arguments
so we’ll say ARG one is a u8 and then
I’ll just duplicate that two three four
five six seven eight times and we’ll
just rename these to arg2
ARG three ARG four
ARG five
six seven and eight all right so now we
have eight input arguments here and of
course it expects eight inputs I’ll do
one two three four five six seven eight
and so now
I should ultimately be blocking the
build based on these arguments here now
it looks like I have a little syntax
error here so let’s see what’s going on
right curly brace I have a left one over
there I have a right one over there not
really sure what’s going on here let me
just do a cargo build and it looks like
we have an unclosed delimiter somewhere
so where is that oh I killed off the
right curly brace for main so let’s go
ahead and include that and so now we
should be getting an error or a warning
it’s indicating that we have too many
arguments here
now this is just complaining about
unused variables here but let’s see if
we can force it to fail so if I do a
cargo and then clippy command that’s
going to invoke the linter and as you
can see when I invoke clippy with cargo
clippy it’s going to look at these
attribute based rules that we’ve
declared in our source file here and
it’s going to parse those it’s going to
look for any configuration options for
those linting rules and then evaluate my
code using static analysis in order to
see if there’s any issues and as you can
see it says error this function has too
many arguments it says the rule
indicates that we want seven again
that’s the default I haven’t customized
that in my clippy configuration but we
actually have eight arguments
so now let’s say that I want to
customize the number of arguments that
are going to cause a breach of this rule
also one more thing really quick if we
do Echo dollar question mark here in
bash you can see that we get an exit
code of one zero one so if you’re in a
CI CD Pipeline and you’re doing
Automation in there you can just inspect
that exit code and see if it’s 101 or
non-zero and that will indicate that
there was some kind of error that
occurred in the clippy linting and then
you can just immediately abort the build
process abort the CI CD Pipeline and
that’ll save you a whole bunch of CI CD
minutes if you’re using a SAS vendor to
do CI CD and you’re paying by the minute
like with GitHub actions or maybe Circle
Ci or Travis CI something like that and
so that’s a really nice way to just kind
of detect if there were any issues also
we can just change this to warn and say
instead of denying I want to just warn
on that and then if we warn we’re not
going to get a non-zero exit code we’ll
just get a zero exit code but in the
standard output we’re still going to see
that that there was some recommendation
here
so now what we’re going to do is to
customize the number of arguments so the
default for this too many arguments lint
rule was seven arguments so we put eight
arguments to breach the rule but let’s
say that we wanted to customize that and
say I want a maximum of about four
arguments
so again we’re going to grab this
configuration option right here that
allows us to customize this specific
rule for too many arguments and we’ll
create a new configuration file in our
project here we’ll call it dot clippy
dot Tamil and you don’t have to put the
period at the beginning it’ll look for
clippy.tomel as well and then all we
need to do is paste in that setting and
set it to the value that we want so our
functions can have a maximum of four
parameters and if we breach that then
we’re going to warn on that issue or
I’ll actually change it back to deny
so now we’ll do cargo clippy and as you
can see we have eight but it wants only
four now so that’s how we apply that
customization option to this lint rule
so now if I eliminate these extra
arguments here and I’ll just put them in
a comment in case I need to put them
back
now we can eliminate these from the
inputs here
and now this should satisfy the rule so
if we do cargo clippy again you can see
that we’re getting warnings about unused
variables but we’re no longer getting
the warning or the denial rather the
error saying that we have too many
arguments of course if we went back and
added ARG number five again and re-ran
cargo clippy then we are going to get
that error along with the 101 exit code
so that’s how we can apply the attribute
for denying this particular rule to the
entire crate because the hashtag
exclamation point applies to the parent
so main.rs is parent is the crate itself
so this should apply to our entire crate
and we can also apply things to
individual entities as well so if we
want to do that let’s say maybe we want
to allow unused variables right
so let’s do something like unused and
we’ll search for
unused argument I think
let’s do a search for argument or unused
variable Maybe
and I’m not seeing that show up here but
there is one for allowing unused
variables
I’m not sure maybe that one’s not
actually a clippy rule but let’s check
out some other types of warnings that we
might have right here and see if we can
find another one
so uh I think another one is actually
the two string so let’s go ahead and
search for tostring right here and I
think that that was going to be a
warning a performance related category
warning so let’s go ahead and try to use
this inside of an example so if we have
a type that implements the display trait
and we call tostring on it it should
catch that as a warning and as you can
see there’s no configuration section
here at the bottom so there’s no
additional configuration options for
this particular setting so what we’re
going to do is just Define
what is this two strings so we’ll Define
another test function here we’ll say
test string and let’s also fix this
we’ll go ahead and remove that fifth
argument there so that that’s Happy
so what we can say down here is that we
want to allow unused variables so let’s
say let x equal five we could also use
arguments as inputs like ARG one is a
unsigned 16-bit integer
and so as you can see we get unused
variable unused argument and unused
variable again right down here so if we
want to allow unused variables only on
this particular function here we can
just use a hashtag without the
exclamation point and that’s going to
apply to the item directly following the
attribute definition so we could say
allow
and then specify unused variables down
here and I don’t think this is a clippy
rule because it doesn’t get prefixed
with clippy here and I also couldn’t
find it in the clippy docs here so just
be aware that that one I think is just
built into rust here so now you can see
that those warnings immediately go away
if we run cargo clippy here then you can
see we just get function test string is
never used but we don’t get those unused
variable warnings like we do for this
function called test lint up here
so if we comment out that attribute and
rerun cargo clippy we should get an
unused variable here on the test string
function now and previously it was only
reporting on unused arguments or
variables on the test lint function so
it’s complaining that we’re not using
the argument ARG one on the test string
function and it’s complaining that we’re
not using the X variable that we
declared inside of the test string
function body but the rule that we
wanted to test out was the tostring rule
right down here
so what we’ll do is go ahead and just do
a print line
operation here let’s do print line we’ll
specify curly braces and then we’ll pass
in I think X I’m not sure if it
explicitly display implements display
but I’m guessing it probably does we
could also just use a string value like
hello from rust Trevor and then we’ll
pass in X yeah that’s fine it’s a string
and then we can do dot two string here
so now we’re taking a string slice and
we’re actually converting it into a heap
allocated string by calling the two
string method on it so now if we do
cargo clippy then you should see this
warning right here that says two string
was applied to a type that already
implements the display trait so this is
uh again a performance related thing
that’s saying hey you don’t actually
need this tostring method call here so
go ahead and eliminate it and your code
will still work perfectly fine right so
once we rerun this here we no longer get
that warning and that’s helping to
improve the performance of our
application by providing that linting
guard rail by default again the default
level for that particular rule is to
warn so it’s not going to allow it by
default but there are some things that
are allowed by default that you can
enable warnings or deny operations for
such as these right here
if you just filter by the allow rules
right here then these are types of
things that are be allowed by default
but you can enable them in your
configuration you can actually set a
warning attribute or a deny attribute so
in order to specify these rules at the
command line that’s kind of the second
way so far we’ve taken a look at the
attribute based syntax here that applies
at the crate level the parent level and
the individual function level or
individual struct level enums and traits
and that kind of thing but if we want to
include some of these rules in our CLI
here
we can do cargo clippy take a look at
the help and then we can warn allow deny
or forbid certain things inside of our
code and the 4-bit is going to be the
most strict because that’s not that’s
going to basically ignore any overrides
that you have so that’s uh that’s kind
of the most strict option if you want to
forbid things in your code but let’s
just say that for now
we want to maybe allow
let’s see let’s allow the tostring
function right here
so we’ll do x.2 string again but this
time we’re going to go ahead and specify
that we want to allow it in our clippy
CLI rather than
specifying it as an attribute based
syntax here
so what we’ll do is say cargo clippy and
then put dash dash here because that
will prevent any arguments from being
passed to Cargo anything after the dash
dash will be interpreted by clippy
itself not cargo and so what we want to
do is say we want to maybe allow
the clippy and then what’s it called
let’s do a filter on two string warnings
here so it’s called two string in format
args so we want to basically do clippy
double colon and then two string in
format args
so let’s see can I copy that from
somewhere here I’ll just copy it here
we’ll click that button and then we’ll
do clippy double colon and paste that in
oh of course it when I copied it
included the prefix there so now if we
run this
you can see that we don’t get that
particular warning if we run without
that parameter we do get this warning
saying that two string was applied to
the type that already implements the
display trait but if we run with the
dash dash allow here that will eliminate
that warning from popping up also if we
wanted to change that warning into a
deny we could simply specify dash dash
deny instead of allow and so now this is
going to cause an error during the
clippy invocation and that’ll catch that
rule early and now we get a 101 exit
code so again we can abort our pipeline
so those are really the two ways to
apply things we can do it at the
attribute level for kind of a global
scope here across the entire crate we
can do it I think that works at the
module scope as well so if you have a
sub module you could plug this attribute
into there I think that would probably
work and then we can also use this
syntax here in order to apply to the
element directly following and when I
say element of course I’m referring to
functions traits enums structs and
things of that nature
all right so let’s take a look at the
quick fixes or the automated fixes with
clippy so one of the things you might
have noticed from earlier is that when
we do cargo clippy dash dash help the
cargo CLI actually has a dash dash fix
option so you want to pass this into
cargo not into clippy so you want to put
it before the Double Dash and that’s
going to be an option that gets past a
cargo anything after the Double Dash
gets passed to clippy specifically so if
we do cargo clippy dash dash fix and
then plug in our clippy options after
that then we can apply automated fixes
so let’s see if there’s an automated fix
that’ll remove this invocation of the
tostring method
so right now the way things currently
stand is that if we run with a deny here
we’re going to get this error on
tostring here
because we changed it from a default
warning into an explicit deny on our
command line but now we’re going to go
right before these double dashes right
here we’re going to apply dash dash fix
to that and as you can see by default
it’s going to warn us about uncommitted
changes but very similar to doing a
publish operation which I don’t think
we’ve covered yet publishing crates to
the crates.io registry we can specify
this parameter here called allow dirty
and this will prevent us from needing to
commit our changes with running this
command so we can go ahead and just say
allow
dirty
I think that’s something we passed a
clippy not cargo so let no it is
actually cargo so let’s move that before
the Double Dash is here
we’ll put the Double Dash after that and
now we should hopefully have a fix here
so as you can see that automatically
fixed our code we can do control Z to
undo that change and then if I just
bring this down a little bit here and
rerun the cargo clippy command you can
see that it automatically fixed that
issue for me so I don’t have to fix that
because maybe I’ve got 100 or 200
different spots in my code where I was
calling tostring unnecessarily that’ll
take care of fixing all of those
instances for me so that I don’t have to
go manually seek them out and resolve
them so that’s a real Time Saver that
you get with the clippy CLI tool so as
you can see it is pretty powerful here
there’s lots of different rules that are
spread across these different groups
right here so this is really nice that
it’s grouped because if you want to look
for performance related issues if maybe
you’re having some performance issues
and you want to try to resolve
specifically performance issues you can
just filter by these performance-based
rules here and see what you can find let
me just clear that search and so all of
these rules right here are performance
related and we can just run clippy
against all these different rules and
see if they apply and also if any of
these rules have configuration options
like this one here we can also go ahead
and specify those inside of our
clippy.tomel file so feel free to play
around with clippy in fact I strongly
encourage you to get some Hands-On time
with clippy maybe run clippy against an
existing rust project if you’ve already
started building your own rust project
and just see what kind of warnings or
errors it throws also make sure that you
incorporate clippy into your CI CD
workflows as well if you use using
something like GitHub actions or gitlab
CI CD or maybe onedev CI CD go into your
configuration files and add this clippy
command as an early step in your process
to catch these errors as early as
possible in your pipelines so that
you’re not waiting a long time for the
build to complete and only then realize
that you have some issues so strongly
encourage you to play around with clippy
play around some of these different
rules play around with some of these
different configuration options you can
use the CLI or you can use the
attribute-based syntax in order to apply
the rule changes so if you decide to go
the CLI route of course you would be
specifying these CLI parameters
in here in your CI CD configuration file
whatever script it is that you’re
running in your CI CD pipeline you’d
basically just add in all these deny and
allow parameters inside of your CLI
script that you’re calling clippy with
and then of course you can always check
for that exit code of 101 to see if
there is an issue or not and then you
could either abort the pipeline or you
could just maybe send an email or a
slack message to your development team
indicating that clippy caught some
issues and then maybe proceed with the
build if you’re comfortable with that
approach but again it’s entirely
customizable to each and every project
that you are writing in Rust so in any
case I think that’s everything that I
wanted to cover around the clippy
utility I strongly encourage especially
beginners to use it because it really
does help guide you on writing better
code it helps you learn more about the
rust language and the standard library
and it’s just a great tool to have in
your back pocket to help improve the
efficiency of your rust builds so again
if you learned something from the this
video please leave a like on this video
please leave a comment down below let me
know what you thought of it and
subscribe to the channel click on that
Bell icon so that you get notifications
when new videos are published and I’d
love to hear your thoughts in General on
this entire playlist thanks for watching
and we’ll see you soon take care
[Music]
so I was curious about which lens rust
programmers actually use in their
programs if you’re not aware you can
annotate your code with uh extra lint
from either the rust compiler or clippy
to be make your code extra
strict so I thought a good way to do
that would be to download every crate
and go and look so I did that that
conveniently there’s a crate called get
all crates made by the famous David tln
uh and it’s perfect for doing research
on every crate and
crates.io once we’ve downloaded
everything the next step is to extract
and search through all the
crates eventually we get a tsv file and
we can use command line tools to extract
the top lens let’s dig into this list
because there are some really
fascinating things in here in the top
spot is deny missing docks now this is a
really nice lint to see at the top deny
missing docs will prevent the compiler
from compiling code where there are any
missing public items without
documentation next on the list is forbid
unsafe code forbid is an extra level
above deny which makes it impossible for
crate authors to opt in to unsafe or
whichever lint uh on a caseby casee
basis so they can’t annotate any
specific item with
allow it’s not a perfect guarantee but
it’s as close as we can
get deny warnings takes the third place
and this is an interesting one because
it’s one I personally don’t
recommend we are promoting all warnings
to erors here and this is on the surface
a very very good thing it means that our
code is very strict however it also
prevents the ability for you to
automatically upgrade your code to a new
version of rust if a new lint is uh
sorry a new warning is introduced to the
language in a in the next version uh
suddenly your CI system will break
without manual intervention so I don’t
think think that is something that
should be added automatically to every
crate let’s not go through the rest of
the list but I would actually like to
point out one more which is missing
debug implementations I think this is
quite useful because it biases you to
think about how your users are accepting
your API we want to make things as easy
for people consuming our crate as
possible and that would mean
implementing traits like hash equality
or partial equality OD uh and debug uh
as frequently as
possible before ending the video I would
just like to show you how to access more
information about each of these lints so
you can make your own choices there are
web pages for both the rust SE lints and
the clippy lint you also have the option
of the command line
uh that’s rust
C- capital W help uh will give you the
very very long list of rust seed lens
for
example I hope this has been a fun and
informative look at clippy lint and rust
SE lint I wish you all the best for your
rust programming Journey my name is Tim
clicks and I am on the planet to build a
better Planet you’re welcome to like
subscribe and and suggest future videos
I’m always interested in your ideas take
care goodbye
Advice for #rustlang devs: Lints to add to your crates
好的,我会按照您的要求整理内容并翻译为中文。以下是整理和翻译后的内容:
我很好奇Rust程序员在他们的程序中实际使用哪些lint。如果你不知道的话,你可以用来自Rust编译器或Clippy的额外lint来注释你的代码,使你的代码更加严格。我认为一个好方法是下载每个crate并查看,所以我这样做了。方便的是,有一个名为get-all-crates的crate,由著名的David tln制作,它非常适合对crates.io上的每个crate进行研究。
一旦我们下载了所有内容,下一步是提取并搜索所有的crates。最终我们得到一个tsv文件,我们可以使用命令行工具来提取最常用的lint。让我们深入研究这个列表,因为其中有一些非常有趣的东西。
在榜首的是deny_missing_docs。看到这个lint排在首位真是太好了。deny_missing_docs会阻止编译器编译任何缺少文档的公共项目的代码。
列表中的下一个是forbid_unsafe_code。forbid是比deny更高一级的限制,它使得crate作者不可能在个别情况下选择使用unsafe或其他任何lint。他们不能用allow注释任何特定项目。这不是一个完美的保证,但这是我们能得到的最接近的保证。
deny_warnings排在第三位,这是一个有趣的lint,因为这是我个人不推荐的一个。我们在这里将所有警告提升为错误,这表面上看是一件非常好的事情。它意味着我们的代码非常严格。然而,它也阻止了你自动将代码升级到新版本Rust的能力。如果在下一个版本中引入了一个新的警告,你的CI系统会在没有人工干预的情况下突然中断。所以我认为这不应该自动添加到每个crate中。
我们不会逐一讨论列表中的其余内容,但我想再指出一个,那就是缺少debug实现。我认为这是非常有用的,因为它让你倾向于思考你的用户如何接受你的API。我们希望让使用我们crate的人尽可能容易,这意味着要尽可能频繁地实现像hash、equality或partial equality、Ord和debug这样的traits。
在结束视频之前,我想向你展示如何获取关于这些lint的更多信息,这样你就可以做出自己的选择。Rust SE lint和Clippy lint都有网页。你也可以选择使用命令行,rustc -W help会给你一个非常长的Rust SE lint列表。
我希望这是一个有趣且信息丰富的Clippy lint和Rust SE lint介绍。我祝愿你在Rust编程之旅中一切顺利。我叫Tim McNamara,我的使命是建设一个更好的地球。欢迎你点赞、订阅并提出未来视频的建议。我一直对你的想法感兴趣。保重,再见。
Prettier/ESLint to Biome: The Lightning-Fast Rust-Based Tool!
so PR is that great tool that makes our
projects clean and tidy either when
saving a file on your code editor or
like before each commit your one
prettyer to make your code formatted and
looks clean or maybe on CI for testing
and checking if the code is actually
formatted the right way but have you
ever actually thought about preter and
the performance issues around prer so do
you actually think that prettier is fast
enough if you think prettier is pretty
performance and pretty good W the cre of
prer actually doesn’t think that and
thinks the opposite about prier that’s
actually pretty slow and in fact he put
actually a
$10,000 Bounty for somebody or some tool
to claim and actually pass 95% of Pier’s
test cases there’s been a huge debate
about that and actually going forward
guro the you know CEO Verso in here
actually claimed and actually added
another 10K to that so he’s like
personally matching he added another 10K
so he be became like 20K and eventually
a couple of other added a couple of
boxes to reach the
22.5k from different sponsors in here
and matter of fact actually Alura
created a specific web page for it for
the Bounty and for the prices and for
actually submitting different solutions
from different people and that actually
gave the community a lot of chances to
actually win the prize and they started
competing by creating tools thinking out
of the box trying to make prer faster
and so much actually happened during
those days but eventually we have a
winner technically in the last week
biome if you just scroll a little bit
down in here so the solutions that were
accepted is biome JS which is the new
tool chain that is for lanting and
formatting that was written completely
from scratch on Rust and it makes huge
difference when it comes to Performance
compared to prettier and yes it passed
the 95% test cases that were sent by
prier so throughout the years we’ve all
been using prier for actually formatting
our Javas scrip Json typescript react
code throughout the years and it’s been
great so far had so many features so
much support by the community and
everything actually has one issue as any
other JS tool JS Library which is
performance so biome was completely
written on run to tackle that
performance issues and actually have a
lot of performance benefits compared to
prettier and to see the actual prettier
case study in here I’m going to go ahead
and run a quick command in here which
you can actually use prier to format and
actually fix any formatting issues on
the weback reposter you see in here
we’ve got the weback repo which is
cloned from GitHub the whole open source
repos 3 with everything so I’m just
going to go ahead and tell they to go
ahead and look for any JavaScript files
out of that repo and actually format it
using pretty I’m going to see how fast
it’s going to do so there you go we’re
going to run the benchmarking here of
course I’m going to use hyperon which is
a really cool tool for benchmarking and
it’s going to run that a couple of times
to get a median time and there you go so
the mean time in here for actually using
prettier to format and actually fix any
issues inside of the whole weback
repository for all the JavaScript files
inside of that one it took around 2
seconds which it might seem a little
slow but it actually is not in the word
of JavaScript and web development
anything more than 1 second is quite a
lot while in the other hand if you look
into biome biome is an open- Source tool
that allows you to do both formatting
and linting which means you’re going to
replace both prettier or like or normal
format that you can actually use and
it’s going to replace something like es
lint which is a linter with one single
tool and biome does them both and the
really nice thing and awesome part about
biome that I really really love is
actually it gives you everything go
gives you both format and a Lin in with
one two without that much of
configuration you don’t need to install
like hundreds of packages to get es lint
working with typc and stuff like that
everything works out of the box
everything is easy to set up and most
importantly it’s not going to you or
make you insane to set up the tool and
start actually formatting and Lin in
your project so if you get started in
here you’re going to find the
installation in here of course you can
go and install it using any package
manager in here mpm and everything and
the configuration itself you can use the
CLI is going to put biome dojon which is
the main file that’s going to hold all
the configuration both the scre here for
linter and for the formatter as well and
for the usage you simply just go ahead
and do MPX or you can just use yourn
volume in here you do volume formats you
give you the files all whole project and
you do it dash dash right to go ahead
and fix any issues and write them to the
files the same thing goes for the link
in here we just use Link we give it the
files and it’s going to give us a really
nice colored and very straightforward
output or you can also use checkin here
which most of the time is going to be
used for the CI that’s going to do
formatting and Linkin files and it’s
going to organize the import for you and
for all the vs code lers out there biome
is available as a V Code extension
that’s going to actually give you the
all superpowers that you were used to
have have and get by using the prettyer
extension as well so for example I have
my portfolio projects in here and for
example let’s say we’re going to go
ahead and migrate from prettyer into BJs
so here first thing of course you do
just go ahead and install BJs in here
make sure to install the binary locally
and not globally because globally is
going to cause a lot of issues it’s
you’re going to have like version
inconsistencies and a lot a lot of
problems so make sure for every single
project you install bu them locally for
each projects inside of the node modes
of each projects in here the next thing
you want to do is actually stop the
configuration so you can copy the
configuration where yarn DLX BJs BM and
you do in nit and this we go ahead and
actually create for you this Json file
for the all the configuration formatter
of course you’re going to use this for
formatting as well and for the liner as
well all the rules all the configuration
is going to be in one single place now
to use the prettier vs code extension
properly just go ahead and install the
extension in here and of course for
those of you who already use prer in
here you can just go ahead and disable
prettier for me I’m going to just
disable it for workspace cuz I’m not
willing to disable it for everything a
lot of project are actually using pretty
right now and after reloading in here
you go back to any file in here for
example you can do the command pallet
you choose format documents and it’s
going to prompt you that oh you don’t
have a default format a setup you can go
ahead and put a one in here you can do
configure and you can go ahead from the
top choose biome so you do biome JS
biome you click on that one and now you
clearly here down here you can see biome
as our form matter if you click this
actually going to use biome for example
I can do indentation in here I can close
and actually going to put everything for
me in here as I need it uh for example
you can just you know add that for
example you can click ahead and save and
the format is going to happen
immediately so as simple as that you can
just go and set up biome and of course
the configuration that’s going to
actually rely on and use is the
configuration that you’re have in here
inside of the biome Json so for example
I have like white line width in here to
be 80 indent style want it to be space
for example for JavaScript I want to use
the format for like the quot I want to
use only single quotation and I only
want to use the trailing Comm and for ES
five formatting and inside of the
package.json in here I can go ahead and
add a new one let do like for example
biome uh check for example in here and
it can just go ahead and use volume and
it can just go ahead and do check and
make sure you choose the the fold that
you want to actually Linton format which
for our case is the SRC and here after
you run the check you’re going to find
all the issues for example it’s telling
you oh you can’t use this function use
this typescript and it’s going to do all
the linin in the word for you as C in
here it gives you like oh we found five
errors and checked 149 files in 19
millisecond all right so let’s go ahead
and actually Benchmark BM versus prer
and another plugin called prettier
paraller which actually uses multi
threaded prer and actually runs them
concurrently to get a faster formatting
so here we have actually a file I
actually clone the whole BJs repost from
GitHub which has a benchmark folder in
here and actually has a really nice
script in here that actually allows you
to Benchmark and customize it however
you you want so here iscl you can like
specify for the format or different
reposters you can use whether you want
to use like web pack reposter in here
for Benchmark here or not I’ve commented
that code by the way and I’ve actually
added specifically next juice in here
because it’s a very gigantic reposter
has a lot of jobs crep on typ code and
especially for the packages in here has
a lot of packages like if you look at
the repository in here has a tremendous
amount of packages in here inside of the
packages folder with next next s swc MDX
so much so I’m going to go and actually
benchmark all the prettier prettier
parallel and biome js on the next GS
reposter in here and see which one is
actually faster now of course bi is
actually claiming to be 25 faster than
prier 20 times faster than parallel prer
and like around two times faster than
dprint and by the way for those of you
who doesn’t know about dprint dprint is
another rust base format that is
actually pretty basic compared to prer
but it’s actually still pretty fast so
simply here I’m going to use node to
actually run our scripts in here of
course here is going to actually build
biome from source and actually start
ascl in here is actually benchmarking
you know examples of like nextjs and the
nextjs packages and everything and there
you go we have the results so for Bome
in here finished like in 5 seconds and
he finished whole next gson with all the
packages are inside examples and
benchmarks and everything so it’s like
in only 5 seconds in here this is like
the mean time for biome and biome
actually run five times faster than the
biome single threaded because biome of
course it es R so it’s like multi-
threaded but of course we can actually
go and use bi single threaded which
going to mimic the same behavior as PR
because PR uses no GS and no GS is
single threaded so you got the point so
it’s still like Bome normally the mild
thread version is like five times faster
than single threaded version and it’s
like 563 which isn’t like too much of a
difference between the single threaded
and the parallel puor in here which
actually uses concurrent threads to run
that one so that’s actually pretty good
but compared to pretor itself is
actually like 10 times faster which is
crazy compared to like you know we’ve
gotten here the whole next us repository
which is a huge repository now in the
other hand in here we did actually go
ahead and run the linter as well so I
actually go ahead and Benchmark bu
linter with es to see how fast it is so
for example you see Benchmark one es
Benchmark 2 biome in here and bium
single threaded and in summary in here
you can clearly see that volum run like
4.3 times faster than biome single
threaded and seven times faster than
normal es slint so still biome is
beating both prer and Es slint at every
aspect even single threaded but hey
likely for us PR’s actually taking an
initiative to go ahead and speed up and
make PR your Faster by actually hiring
Fabio who’s like an open source
Enthusiast about performance and
everything and he’s actually doing some
researches and he put this really nice
block Post in here that explains how per
Works what are you know the the
approaches make prettier faster so this
is a really good initiative and I’m
pretty sure prer is going to become a
lot faster in the near future so I’m I’m
really looking forward to that but
anyway guys thanks you for watching hope
you guys enjoyed and catch you hopefully
in the next ones
我理解您的要求。我会整理原文内容使其更加连贯通顺,同时保留所有细节不做省略或总结,然后将其翻译成中文。以下是整理并翻译后的内容:
PR(Prettier)是一个很棒的工具,可以让我们的项目保持整洁有序。无论是在代码编辑器中保存文件时,还是在每次提交之前,或者在CI过程中进行测试和检查,它都能让代码格式化并保持整洁。但你有没有想过Prettier的性能问题?你认为Prettier够快吗?
如果你认为Prettier的性能很好,那么你可能会惊讶地发现,Prettier的创建者实际上并不这么认为。他们认为Prettier相当慢,事实上,他们甚至提供了一个10,000美元的悬赏,给任何能够通过95%Prettier测试用例的人或工具。
这引发了一场大讨论,随后Vercel的CEO Guillermo Rauch也加入进来,他个人再追加了10,000美元,使总奖金达到了20,000美元。最终,其他几个赞助商也加入进来,总奖金达到了22,500美元。
为了管理这个悬赏,Astro创建了一个专门的网页,用于展示奖金、价格和提交不同解决方案。这给了社区很多机会去赢得奖金,他们开始竞相创建工具,跳出框框思考,试图让Prettier变得更快。
在过去的几周里,发生了很多事情,但最终我们有了一个技术上的赢家:Biome。如果你往下滚动一点,你会看到被接受的解决方案是Biome JS,这是一个全新的用于代码检查和格式化的工具链,它完全用Rust重写,在性能方面比Prettier有了巨大的提升。是的,它通过了Prettier设定的95%的测试用例。
多年来,我们一直使用Prettier来格式化我们的JavaScript、JSON、TypeScript和React代码。它一直很棒,有很多功能,得到了社区的大力支持。但和其他JavaScript工具和库一样,它有一个问题:性能。Biome完全用Rust重写,就是为了解决这个性能问题,与Prettier相比,它在性能方面有很大的优势。
让我们来看看实际的Prettier案例研究。我将运行一个快速命令,使用Prettier来格式化并修复webpack仓库中的任何格式问题。这里我们有从GitHub克隆的整个开源webpack仓库。我将让它查找仓库中的所有JavaScript文件并使用Prettier进行格式化。我们来看看它的速度有多快。
我们将使用hyperfine进行基准测试,这是一个很酷的基准测试工具。它会运行几次以获得中位时间。结果显示,使用Prettier格式化并修复整个webpack仓库中所有JavaScript文件的问题平均需要约2秒。在JavaScript和Web开发的世界里,这可能看起来不是很慢,但任何超过1秒的操作都算是相当慢的了。
另一方面,如果你看看Biome,它是一个开源工具,允许你同时进行格式化和代码检查。这意味着你可以用一个工具替代Prettier(或其他格式化工具)和ESLint(代码检查工具)。我真正喜欢Biome的一点是,它不需要太多配置就能给你所有功能。你不需要安装数百个包来让ESLint与TypeScript等工作,一切都开箱即用,设置简单,最重要的是,它不会让你为了设置工具而发疯。
如果你开始使用Biome,你会发现安装很简单。你可以使用任何包管理器安装它。配置也很简单,你可以使用CLI来创建biome.json文件,这个文件将包含所有的配置,包括代码检查器和格式化器的配置。
使用也很简单,你只需运行npx biome format,给它文件或整个项目,然后使用--write选项来修复任何问题并将其写入文件。对于代码检查也是一样,你只需使用lint命令。它会给你一个漂亮的彩色输出,非常直观。你也可以使用check命令,这通常用于CI,它会进行格式化、代码检查和导入排序。
对于VS Code用户来说,Biome有一个可用的扩展,它会给你所有你习惯使用Prettier扩展时的超能力。
让我们以我的投资组合项目为例,看看如何从Prettier迁移到Biome。首先,你需要安装Biome。确保在本地安装二进制文件,而不是全局安装,因为全局安装可能会导致版本不一致等问题。对于每个项目,确保在项目的node_modules中本地安装Biome。
接下来,你需要设置配置。你可以运行yarn dlx biome init来创建配置文件。这将为你创建一个JSON文件,包含所有的配置,包括格式化器和代码检查器的配置。所有的规则和配置都在一个地方。
要在VS Code中正确使用Biome扩展,只需安装扩展,然后禁用Prettier扩展(如果你之前使用的是Prettier)。之后,你可以使用命令面板选择”Format Document”,它会提示你设置默认格式化程序。选择Biome,然后你就可以开始使用了。例如,你可以更改缩进,保存文件时格式化会立即发生。
配置文件(biome.json)允许你设置各种选项,比如行宽、缩进样式、引号类型等。你还可以在package.json中添加脚本来运行Biome的检查。
现在让我们对Biome、Prettier和prettier-plugin-organize-imports(一个使用多线程并发运行Prettier的插件)进行基准测试。我们将使用Next.js仓库进行测试,因为它是一个非常大的仓库,包含大量的JavaScript和TypeScript代码。
结果显示,Biome在5秒内完成了整个Next.js仓库(包括所有包、示例和基准测试)的格式化。这比单线程版本的Biome快5倍,比Prettier快10倍,比prettier-plugin-organize-imports稍快一些。
我们还对Biome的代码检查器与ESLint进行了基准测试。结果显示,Biome的运行速度比单线程版本快4.3倍,比普通的ESLint快7倍。
虽然Biome在各个方面都超过了Prettier和ESLint,但Prettier团队也在采取行动提高性能。他们雇佣了Fabio(一个热衷于性能的开源爱好者)来研究如何让Prettier更快。他写了一篇很好的博客文章,解释了Prettier的工作原理以及提高性能的方法。这是一个很好的举措,我相信在不久的将来,Prettier会变得更快。
总之,希望你们喜欢这个内容,我们下次再见!
P99 CONF 2023 | How Database Tricks Sped up Rust Linting Over 2000X by Predrag Gruevski
[Music]
hi welcome to the session on speeding up
rust linting using database tricks my
name is predi gry and I firmly believe
everything can be a
database I’m the author of the rust
linter caros samver checks as well as
the trust Vault query engine that powers
it the problem we’re solving today is
the dependency upgrades aren’t Fearless
yet rust’s package manager cargo assumes
that all libraries always adhere to
semantic versioning when this assumption
is violated the consequences can be
painful users builds are broken and
maintainers have to scramble to publish
fixes fortunately this works well most
of the
time however more than one in six of the
top 1,000 rust crates have violated sver
at least once the causes of this are
complex and human error is not one of
them if you’d like like to learn more
you can check out the blog post at the
link at the bottom of the
slide cargos amver is a lter that
prevents accidental breaking changes
it’s designed to run right before
publishing new version at which point it
scans the public API to compare it
against the previous version’s API
liking any changes that are not in line
with the intended version bump it’s
gotten a fair bit of community adoption
and the cargo team hopes to merge it
into cargo
itself the initial version of cargo sver
was published a little over a year ago
and it was not the fastest it’s rtime
scaled as o of N squared with Library
size fortunately most libraries are
small so this wasn’t a huge performance
problem over time it started being
adopted in some bigger libraries as well
it added about an extra minute to their
publish pipeline but this was worth it
because they were also at higher risk of
accidental breaking
changes Unfortunately n squ is The Sweet
Spot of poorly scaling algorithms it’s
fast enough to make it to production and
slow enough to cause a problem once it
gets there predictably it did cause a
problem at one point the team working on
the AWS SDK for rust attempted to use
cargo sver checks at which point they
found that it took more than 5 hours to
sver check their crate this was of
course unacceptable and not useful the
optimizations I’m going to describe in
this talk allowed us to take those 5
hours and turn them into 7.7 seconds
more than 2300 times faster and the
benefit wasn’t limited to gigantic
crates smaller libraries saw
improvements as well instead of adding
an extra minute to the published
pipelines now we can sver check most of
them in well under 1
second in the rest of this talk I’d like
to convince you that sver linting is
just database querying in Disguise and
then I’d like to show you how we can use
an API to optimize those database
queries let’s use a simple example say
we remove a public function from a
library API this is of course a breaking
change and if we run cargo sver checks
it will helpfully point that out it says
that a publicly visible function is no
longer importable by its prior path and
it gives us the name of the function and
its previous location in our source
code the way this is implemented under
the hood is via query we look for
functions that existed in the previous
version of the API but no longer exist
in the new version if we represented
this as a diagram it would look
something like this we have a pair of
versions that we’re considering and for
each function in the old version we look
up its importable path then attempt to
match it to a function in the new
version but at the same path if no such
function exists then we found our
breaking
change a naive execution of this query
would be N squared it would consider all
pairs of functions between the old
version and the new version of the code
we have n functions on the left and N
functions on the right and an O of one
check to see if their paths are a match
this is how the initial version of cargo
sver checks worked our goal here is to
implement an optimization called
predicate pushdown which looks just like
adding a database
index given that we’re looking for a
specific function by path we can look up
the corresponding function in the new
version in O of one using an index we’re
going to do this n times across each of
the functions in the old version so the
total runtime here would be o of
n the entire 2300 time speed up is just
three instances of predicate push down
across the various queries in cargo sver
checks so if all we’re doing is adding
some indexes what a challenge here it
turns out that handling sver in a way
that doesn’t cause false positives
everywhere requires seeing like a
compiler because we have to solve for
could the new code possibly work for
example say a method got removed from
some type it’s possible this isn’t a
breaking change for example the method
might have moved to a trait that that
type also implements correctly handling
this case requires compiler likee logic
we have to implement algorithms like
trait resolution name resolution and so
on and that makes SQL not a great fit
even if you ran a complex ETL pipeline
the size of the resulting tables would
mean that all hope of good performance
goes out the window at the same time
declarative queries are a necessity the
best data source we have is called rust
do it’s a tool that comes with rust that
allows us to get machine readable
representations of Library
apis unfortunately its format is UN lab
it has breaking changes in more or less
every rust release every 6 weeks we have
to make sure we don’t have to rewrite
every query for every new version of
rustock because that sounds like a
recipe for maintainer Burnout it’s
entirely
unsustainable in an Ideal World we’d
have declarative queries over a fixed
data model instead of writing them to
load data from a specific Json path that
might change every 6 weeks we would
write them to do things like look up
functions by name which is the same
thing no matter which rust version we’re
using if we were to draw an architecture
diagram it would look something like
this we have our lter at the top and all
the different formats we need to support
on the bottom in between there is a
layer that connects the two we’ll wrap
all the formats we need to support in
little pieces of code called adapters
which understand all of the format
specific logic needed to extract the
data we need all of our lenting business
logic is represented as queries that
describe the kinds of breaking changes
we’re looking for and in between we have
a query engine that knows how to turn
those queries into requests for data the
adapters know how to look
up the query engine we’re using is
called trustfall and it’s a little bit
unusual if you’ve used postgress or
sqlite you might have heard the terms
foreign data wrappers or virtual tables
these are ways for the databases to
query data that they stored outside of
their storage system unfortunately this
feature is a secondary Focus for these
databases which means that it’s often
Limited in the capabilities that it has
and the kinds of optimizations it can
perform foreign data is a primary focus
of trustfall its idea is to represent
data is a virtual graph where vertices
of properties and edges whose data might
come from any kind of data
source that allows it to have an
expressive quer language over all kinds
of data sources that are not
traditionally considered databases such
as rest apis or collections of files on
S3 the ideas behind trustfall have been
heavily battl tested in production over
7even years across a variety of
different data sources the engine is
written in Rust and the adapters can be
written in Rust python JavaScript or web
assembly if you’d like to learn more
about trustfall itself check out my talk
called how to query almost
everything you can also head over to our
web playgrounds where you can try
running trustful queries over the half
news rest API or the apis of a variety
of rust
crates okay we can query the database
how do we optimize
let’s take a look at how trust Falls
optimizations API allows us to do
optimizations like predicate
pushdown we can split query
optimizations into two categories the
first is optimizations that are
independent of the data source these are
things like lazy evaluation we don’t
have to worry about these too much
because trustfall applies them
automatically they’re always
on the second kind is optimizations that
are more situational they’re dependent
on the underlying data source they’re
things like caching batching and
predicate push down and they have to be
implemented by the adapter based on
information provided by trust Falls
optimization API we’re trying to
implement predicate pushdown so that’s
the kind of optimization we’ll be
looking
at let’s look at a few examples we’ll
start with something simple and we’ll
work our way up to the full predicate
pushdown optimization that is in cargo
sus let’s first look up all functions
and their paths in the
crate as a diagram it would look
something like this with we start with
the crate we look up all the functions
contained within and for each function
we look up its importable
path in trustfall syntax that looks
something like this we start with the
crate we look at all the items in the
crate which includes functions structs
enums and so on WE filter down to only
functions discarding everything else we
look up The importable Path of which
there might be zero one or more than one
we output The Path property and if we
felt like adding any more query CLA es
we could put them between any pair of
curly braces
here okay that’s the query sorted out
let’s look at the adapter we’ll
specifically look at the code for
loading the items in the given
crate the adapter might have a function
like resolve crate items which takes two
parameters the vertex that represents
the crate whose data we loading and a
hints value that represents the
optimization API we’re going to come
back to that in a minute the exact
details of the rust do format are not
relevant here so let’s let’s assume we
already have a function that loads all
of the items given a crate even though a
query is returning only functions it’s
safe to return all kinds of items here
applying filters is trust Fall’s
responsibility so it will take care to
discard everything that isn’t a
function now that we got that working
let’s try looking for a function at a
specific import path to do this we just
add a filter directive to our query that
says that the Path property must be
equal to this query parameter called
path because the query parameter is
fixed at query time we can use an index
lookup to speed this up but it turns out
that building an API that supports this
well is pretty hard to do that API has
multiple objectives that are in ttention
with each other we want it to have a
high ceiling so that any optimization
can be built but we also want it to have
a low barrier to entry so that
optimizations are easy and it doesn’t
require a PhD to build one we also want
this API to be very stable we want to be
able to continue evolving trustfall
without breaking every everyone’s
optimizations at this point one might
say why not just expose trust Falls
internal query representation but as it
turns out just ends up being a
loadbearing word here let’s take a look
at something similar that happened in
the go ecosystem a few months ago a user
requested that the compiler team
stabilize their internal representation
unfortunately that intermediate
representation changes often and is what
allows the go compiler to continue
evolving over time exposing and
stabilizing these internals would be a
serious hindrance to the team’s efforts
so they decided to reject this proposal
as
infeasible the same would be true of
trustfall so instead we decided to take
a different approach we decided to build
an optimization API that allows adapter
to ask structured questions about the
behavior of the query they are currently
executing these are questions like is
the importable path Edge used at this
location in the query or is the Path
property required to have a specific
value here
this satisfies all three of our
objectives it covers all of the
optimizations that we could think of it
allows optimizations to reuse trust
Falls Machinery instead of rolling their
own and it allows us to not expose our
internals which means that they can
continue to change freely without
breaking everyone’s
optimizations let’s get back to the
query that loads functions at a specific
and portable path and use this
optimizations API to apply predicate
push down this is the code we wrote
previously and it’s still correct
remember remember applying the filter is
trust Fall’s job however it is slow it
will take o of n to look up the function
at that
path let’s say that we have an index
over importable paths let’s check if we
can apply it to apply the index we need
to check if the importable path Edge is
being used by the query and if so we
need to check if the Path property has a
value that is known at query
time If so trust will give us candidate
values for the Path property and we can
use the those candidates to apply an
index
lookup with this implementation the
query can find the function we’re
looking for by applying the index in O
of one instead of going through all of
the items in O of n now we’re ready to
implement the full optimization the
cargo samver uses let’s look for
functions that no longer exist at their
prior path as before this is the diagram
for that query however remember that
applying filters is trust Fall’s job so
we don’t have to worry about the part
where we say the function must not exist
instead we can simplify and just look
for functions that are at the same path
as the one in the old crate this case is
a little bit trickier than before
instead of the path being a single value
known at query time this time it’s only
known dynamically because it changes for
every function that we
check let’s look at the code for the
same Edge one more time this is the code
we had before it’s still correct but it
is slower than necessary because it will
fall back to using the slow path since
it can’t use the index at the moment
let’s fix that
we’ll ask trustfall if the Path property
has a dynamically known value and if so
trustfall will tell us that it can
generate candidate values but it might
need to evaluate more of the query first
we’ll tell it to go ahead and do that
and once we get the candidate values
we’ll apply the index lookup as
before with this implementation our
query can once again use the index and
look up the corresponding function in O
of one instead of scanning through all
of the functions in O of N and with that
success we’ve implemented predicate push
down this sver lint now runs an O of n
instead of O of n^ s and most
importantly this was entirely done using
a stable API we never needed to access
any trustfall internals that might break
as trustfall
evolves so what is optimizing like this
bu us it buys us a few obvious things
like better user experience lower energy
use and support for larger use cases
like giant code bases or research of
sver compliance across a wide range of
crates but it also Prov us something non
obvious it allows us to proactively look
for bugs in our
implementation as part of our sver study
we scanned more than 14,000 crate
releases and in the process found more
than a dozen bugs in cargo sver checks
in a sense performance made it cheap to
find our own bugs before our users found
them in the big picture there are two
takeaways here the first one is that
many workloads are just database
querying in
disguise with trustfall anything can be
a database and we can have declarative
querying over any kind of data source
our business logic should not be tied to
our optimizations and that will allow us
to have more robust more flexible more
performant
code the second is that we don’t have to
pick between flexibility or performance
we can have both at the same time
foreign data wrappers can be quite fast
if we designed for that from day one and
having access to good optimization apis
means that we have precise control over
the execution of our declared
queries I believe this is an
underexplored design space so stay tuned
you can follow me on social media and I
also have a Blog you might want to check
out please play around with the
trustfall query engine and let me know
what you think happy
[Music]
querying
当然,我会按照您的要求整理和翻译这段内容。以下是整理后的中文翻译,我尽量保留了所有原文内容,不进行总结或省略:
[音乐]
大家好,欢迎来到这场关于使用数据库技巧加速Rust代码检查的讲座。我叫Predrag Gruevski,我坚信一切都可以是数据库。我是Rust代码检查工具cargo-semver-checks的作者,也是支持它的TrustFall查询引擎的作者。
今天我们要解决的问题是依赖升级还不够无忧。Rust的包管理器cargo假设所有库都始终遵守语义化版本控制(semver)。当这个假设被违反时,后果可能很严重:用户的构建会被破坏,维护者不得不匆忙发布修复。幸运的是,这种情况大多数时候都运作良好。然而,在排名前1000的Rust crate中,超过六分之一至少违反过一次semver。造成这种情况的原因很复杂,并不仅仅是人为错误。如果你想了解更多,可以查看幻灯片底部链接的博客文章。
cargo-semver-checks是一个防止意外引入破坏性变更的代码检查工具。它被设计为在发布新版本之前运行,此时它会扫描公共API并与之前版本的API进行比较,检查任何与预期版本升级不符的变更。它已经得到了社区的广泛采用,cargo团队希望将其合并到cargo本身中。
cargo-semver-checks的初始版本是在一年多前发布的,当时它的速度并不是最快的。它的运行时间随着库的大小呈O(n²)增长。幸运的是,大多数库都很小,所以这并不是一个大问题。随着时间的推移,它开始被一些更大的库采用。它为它们的发布流程增加了大约一分钟的额外时间,但这是值得的,因为这些库也面临着更高的意外引入破坏性变更的风险。
不幸的是,O(n²)是性能不佳算法的甜蜜点。它足够快可以投入生产,又足够慢可以在大规模使用时引发问题。可以预见,它确实在某个时候引发了问题。AWS SDK for Rust团队尝试使用cargo-semver-checks时发现,对他们的crate进行semver检查需要超过5个小时。这当然是不可接受的,也没有实用价值。
我将在这个讲座中描述的优化允许我们将这5个小时缩短到7.7秒,速度提升了2300多倍。而且这个优化不仅限于巨大的crate,较小的库也看到了改进。现在,我们可以在远低于1秒的时间内对大多数库进行semver检查,而不是在发布流程中增加额外的一分钟。
在接下来的讲座中,我想说服你们semver代码检查其实就是数据库查询的伪装,然后我想向你们展示我们如何使用API来优化这些数据库查询。
让我们用一个简单的例子来说明。假设我们从库的API中删除了一个公共函数。这当然是一个破坏性变更,如果我们运行cargo-semver-checks,它会很有帮助地指出这一点。它会说一个公开可见的函数不再能通过其先前的路径导入,并给出函数的名称和它在我们源代码中的先前位置。
这在底层是通过查询来实现的。我们查找在API的先前版本中存在但在新版本中不再存在的函数。如果我们用图表来表示,它看起来会像这样:我们有一对正在考虑的版本,对于旧版本中的每个函数,我们查找其可导入路径,然后尝试在新版本中匹配相同路径的函数。如果不存在这样的函数,那么我们就发现了一个破坏性变更。
这个查询的朴素执行将是O(n²)的。它会考虑旧版本和新版本代码之间所有函数的配对。我们在左边有n个函数,右边有n个函数,还有一个O(1)的检查来看它们的路径是否匹配。这就是cargo-semver-checks最初版本的工作方式。
我们的目标是实现一种称为谓词下推的优化,它看起来就像添加一个数据库索引。鉴于我们正在通过路径查找特定函数,我们可以使用索引在O(1)时间内查找新版本中对应的函数。我们将对旧版本中的每个函数执行n次这样的操作,所以总运行时间将是O(n)。
整个2300倍的速度提升仅仅是在cargo-semver-checks的各种查询中应用了三次谓词下推。
那么,如果我们所做的只是添加一些索引,挑战在哪里呢?事实证明,以不会到处引发误报的方式处理semver需要像编译器一样的视角,因为我们必须解决新代码是否可能工作的问题。例如,假设某个类型的方法被移除了。这可能不是一个破坏性变更,比如该方法可能已经移到了该类型也实现的一个trait中。正确处理这种情况需要类似编译器的逻辑。我们必须实现诸如trait解析、名称解析等算法。这使得SQL不太适合。即使你运行了复杂的ETL管道,结果表的大小也意味着所有对良好性能的希望都会化为泡影。
同时,声明式查询是必要的。我们拥有的最佳数据源是名为rustdoc的工具。它随Rust一起提供,允许我们获得库API的机器可读表示。不幸的是,它的格式是不稳定的。它在每个Rust版本中都有破坏性变更,大约每6周一次。我们必须确保不需要为每个新的rustdoc版本重写每个查询,因为这听起来像是一个导致维护者精疲力尽的方案。这完全不可持续。
在理想世界中,我们会有固定数据模型上的声明式查询。我们会编写查询来做诸如按名称查找函数这样的事情,无论我们使用哪个Rust版本,这都是一样的。我们不必编写查询来从可能每6周就改变的特定JSON路径加载数据。
如果我们要画一个架构图,它看起来会像这样:我们在顶部有我们的代码检查工具,在底部有我们需要支持的所有不同格式。在中间有一层连接两者。我们将所有需要支持的格式包装在称为适配器的小段代码中,这些适配器理解提取我们需要的数据所需的所有特定于格式的逻辑。我们所有的代码检查业务逻辑都表示为描述我们正在寻找的破坏性变更类型的查询。在中间,我们有一个查询引擎,它知道如何将这些查询转换为数据请求,而适配器知道如何查找。
我们使用的查询引擎叫做TrustFall,它有点不寻常。如果你使用过PostgreSQL或SQLite,你可能听说过外部数据包装器或虚拟表这些术语。这些是数据库查询存储在其存储系统之外的数据的方法。不幸的是,这个特性对这些数据库来说是次要的关注点,这意味着它在功能和可以执行的优化类型方面往往受到限制。
外部数据是TrustFall的主要关注点。它的想法是将数据表示为一个虚拟图,其中顶点有属性,边的数据可能来自任何类型的数据源。这允许它对传统上不被认为是数据库的各种数据源(如REST API或S3上的文件集合)有一个富有表现力的查询语言。TrustFall背后的想法在生产环境中经过了7年多的严格测试,跨越了各种不同的数据源。引擎是用Rust编写的,适配器可以用Rust、Python、JavaScript或WebAssembly编写。
如果你想了解更多关于TrustFall本身的信息,可以查看我的演讲”如何查询几乎所有东西”。你也可以前往我们的网络游乐场,在那里你可以尝试在Hacker News REST API或各种Rust crate的API上运行TrustFall查询。
好的,我们可以查询数据库,那么我们如何优化呢?
让我们看看TrustFall的优化API如何允许我们进行诸如谓词下推之类的优化。我们可以将查询优化分为两类:
第一类是独立于数据源的优化。这些是像惰性求值这样的东西。我们不必太担心这些,因为TrustFall会自动应用它们。它们总是开启的。
第二类是更具情况性的优化。它们依赖于底层数据源。它们是诸如缓存、批处理和谓词下推之类的东西,必须由适配器基于TrustFall优化API提供的信息来实现。我们正在尝试实现谓词下推,所以这就是我们将要关注的优化类型。
让我们看几个例子。我们将从简单的开始,然后逐步深入到cargo-semver-checks中完整的谓词下推优化。
首先,让我们查找crate中的所有函数及其路径。作为图表,它看起来会像这样:我们从crate开始,查找其中包含的所有函数,对于每个函数,我们查找其可导入路径。
在TrustFall语法中,它看起来像这样:我们从crate开始,查看crate中的所有项(包括函数、结构体、枚举等),然后过滤只保留函数,丢弃其他所有内容。我们查找可导入路径(可能有零个、一个或多个),然后输出Path属性。如果我们想添加更多查询子句,我们可以把它们放在任何一对大括号之间。
好的,查询已经解决了,让我们看看适配器。我们将特别关注加载给定crate中的项的代码。适配器可能有一个像resolve_crate_items这样的函数,它接受两个参数:表示我们正在加载数据的crate的顶点,以及表示优化API的hints值。我们稍后会回到这个问题。rustdoc格式的确切细节在这里并不重要,所以让我们假设我们已经有一个给定crate加载所有项的函数。即使查询只返回函数,在这里返回所有类型的项也是安全的。应用过滤器是TrustFall的责任,所以它会负责丢弃所有不是函数的内容。
现在我们已经让它工作了,让我们尝试在特定的导入路径查找一个函数。为此,我们只需在查询中添加一个过滤器指令,说明Path属性必须等于这个名为path的查询参数。因为查询参数在查询时是固定的,我们可以使用索引查找来加速这个过程。
但事实证明,构建一个支持这一点的API是相当困难的。该API有多个相互冲突的目标:我们希望它有一个高天花板,以便可以构建任何优化,但我们也希望它有一个低门槛,以便优化易于实现,不需要博士学位就能构建一个。我们还希望这个API非常稳定。我们希望能够继续发展TrustFall,而不会破坏每个人的优化。
在这一点上,有人可能会说,为什么不直接暴露TrustFall的内部查询表示呢?但事实证明,”直接”这个词在这里是至关重要的。让我们看看几个月前在Go生态系统中发生的类似情况。一个用户请求编译器团队稳定他们的内部表示。不幸的是,这种中间表示经常变化,正是它允许Go编译器随时间继续发展。暴露和稳定这些内部结构会严重阻碍团队的努力。所以他们决定拒绝这个不可行的提议。
对TrustFall来说也是如此。所以我们决定采取不同的方法。我们决定构建一个优化API,允许适配器询问有关他们当前执行的查询行为的结构化问题。这些问题包括:在查询的这个位置是否使用了importable_path边?或者Path属性是否需要在这里有一个特定的值?
这满足了我们的所有三个目标。它涵盖了我们能想到的所有优化。它允许优化重用TrustFall的机制,而不是自己重新实现。它允许我们不暴露我们的内部结构,这意味着它们可以继续自由变化,而不会破坏每个人的优化。
让我们回到在特定可导入路径加载函数的查询,并使用这个优化API来应用谓词下推。这是我们之前写的代码,它仍然是正确的。记住,应用过滤器是TrustFall的工作。然而,这种方法速度很慢,查找特定路径的函数需要O(n)的时间。
假设我们有一个基于可导入路径的索引。让我们检查是否可以应用它。要应用索引,我们需要检查查询是否使用了importable_path边,如果是,我们需要检查Path属性是否在查询时有已知的值。如果是这样,TrustFall会给我们Path属性的候选值,我们可以使用这些候选值来应用索引查找。
有了这个实现,查询可以通过应用索引在O(1)时间内找到我们要找的函数,而不是在O(n)时间内遍历所有项。
现在我们准备实现cargo-semver-checks使用的完整优化。让我们寻找那些在先前路径上不再存在的函数。和之前一样,这是该查询的图表。然而,记住应用过滤器是TrustFall的工作,所以我们不必担心说函数必须不存在的那部分。相反,我们可以简化为只查找与旧crate中相同路径的函数。
这种情况比之前稍微复杂一些。路径不是在查询时就知道的单一值,而是动态知道的,因为它对我们检查的每个函数都会改变。
让我们再看一下same_edge的代码。这是我们之前的代码,它仍然是正确的,但比必要的慢,因为它目前无法使用索引,会退回到使用慢路径。让我们来修复这个问题。
我们会问TrustFall,Path属性是否有动态已知的值。如果是,TrustFall会告诉我们它可以生成候选值,但可能需要先评估更多的查询。我们会告诉它继续这样做,一旦我们得到候选值,我们就像之前一样应用索引查找。
有了这个实现,我们的查询又可以使用索引,在O(1)时间内查找对应的函数,而不是在O(n)时间内扫描所有函数。就这样,我们成功了!我们实现了谓词下推。这个semver检查工具现在运行时间是O(n)而不是O(n²)。最重要的是,这完全是使用稳定的API完成的。我们从未需要访问可能随着TrustFall的发展而破坏的任何TrustFall内部结构。
那么,这样的优化给我们带来了什么?它带来了一些显而易见的好处,如更好的用户体验、更低的能源使用,以及对更大用例的支持,比如巨大的代码库或对大范围crate的semver合规性研究。但它还为我们提供了一些不那么明显的东西:它允许我们主动寻找我们实现中的bug。作为我们semver研究的一部分,我们扫描了超过14,000个crate发布版本,在这个过程中发现了cargo-semver-checks中十多个bug。在某种意义上,性能使得在用户发现它们之前找到我们自己的bug变得便宜。
从大局来看,这里有两个要点:
第一个是,许多工作负载其实就是伪装的数据库查询。有了TrustFall,任何东西都可以是数据库,我们可以对任何类型的数据源进行声明式查询。我们的业务逻辑不应该与我们的优化绑定,这将允许我们拥有更健壮、更灵活、性能更好的代码。
第二个是,我们不必在灵活性和性能之间做出选择。我们可以同时拥有两者。如果我们从一开始就为此设计,外部数据包装器可以非常快。而且,有了良好的优化API,意味着我们可以精确控制我们声明性查询的执行。
我相信这是一个未被充分探索的设计空间,所以请继续关注。你可以在社交媒体上关注我,我也有一个博客,你可能想看看。请试用TrustFall查询引擎,让我知道你的想法。祝你查询愉快!
[音乐]
Ruff: Faster Python Linting With Rust
https://github.com/astral-sh/ruff
[双字] {Ruff, Flake8, Pylint}速度对比测试
foreign
and welcome to today’s webinar organized
by jetbrains I’m Paul Everett python
developer Advocate I’ll be your hosts
for a great great webinar we were joking
behind scenes just a few minutes ago how
every webinar is great I say this every
time this one’s going to be great the
topic for today’s webinar is rough
faster python linting with rust the word
linting is like just like 57 other
things that we’re going to talk about
today today’s guest is Charlie Marsh the
creator of rough yes rough which is very
quickly become a usable
powerful fast lint or used by important
projects
and a vehicle for new thinking but what
is rough what isn’t rough today we have
Russ Creator the prolific Charlie Marsh
Charlie started hiring us and web
developer at the Khan Academy yes the
one you’re thinking of uh most recently
a staff software engineer at Spring
Discovery doing interesting rust plus
python plus ml platform work and now
currently working full time on rough
welcome Charlie
thank you thanks so much for uh for
having me I mean you know this but I’m a
big pie charm user and pycharm fan
um so it’s it’s very cool to be here and
I appreciate the opportunity to talk
with you both and the audience about
what we’re also talking about by the way
uh talk python episode with you
interviewed recently and I listened to
that whole thing thinking oh my gosh we
get to have him in like three weeks from
now
um also joining my uh advocacy colleague
Vitaly bragalevski last time we hosted
Vitaly it was JavaScript
but I think this topic of rust might be
a little more interesting for you
well I uh hi Paula I love all
programming languages but of course rust
is a little bit more appealing to me you
know so thank you for for having me here
it’s safe to say you cover the advocacy
for our rust plug-in right yeah that’s
true all right great the Deborah thing
around for us yep uh as FY uh FYI we did
an interview with Charlie on the pie
charm blog recently the answers are
really intriguing if you get a chance go
read it
um get us a little bit oriented Charlie
what is rough and why does it matter
so Ruff is uh a what I call an extremely
fast uh python winter
um so uh it’s a python winter written in
Rust uh that’s designed to be extremely
performant
um so if you’re familiar uh with other
static analysis tools in the python
ecosystem other linters
um like uh flight gate or or pipe flakes
or pie code style or Pilot um there’s a
lot of of tools out there and these are
all static analysis tools that look at
your code and try to identify problems
or potential problems
um so rough fits into a similar category
of tooling so it it looks at your source
code priced and tie issues
and tries to do so extremely extremely
quickly hopefully
um and unlike some of those other tools
although some tools do this it will also
try to fix a lot of those issues for you
so in addition to being a linter it also
does this sort of Auto fixing and code
transformation process which can really
help speed development and help you
spend less time worrying about the
things that you want to enforce in an
automated way
that’s a good way to put it I come from
Front End world and so a lot of this is
happening in fact I think you were
inspired a little bit by the tooling
going on in the front end World Doug
Farrell says over in chat he agrees that
the interview with you on talk python
was great he said it may that talk
python interview made him switch a work
project from Pilot to rough
oh very cool I appreciate it well that
was my yeah that was my first time ever
on a podcast so I guess this isn’t a
podcast but I’m now a veteran and uh
hopefully this is you know is even
smoother no that was a lot of fun and I
appreciate that thanks uh Russ comes in
I think tied with python as most loved
language what is it about rust in
general or for this topic that you find
compelling
yeah totally so um
you know it’s interesting like I I don’t
know if a year ago I really would have
seen myself like becoming someone who
wrote a lot of rust code
um like I’m not like a you know a
quote-unquote like systems programmer or
anything like that
um you know I like I I’ve worked on a
lot of different kinds of projects but
um like most of my career has been in
like JavaScript or typescript or python
um or you know some like Java and blah
blah
um but I’ve I’ve written almost no C
maybe like a little bit in college and
I’ve I don’t think I’ve ever written the
line of C plus plus
um and so uh like I don’t think I’m like
a supernatural fit to become like a huge
rust person
um which is
uh maybe like one of the bigger
endorsements I can give for rust itself
is like if I can do it like I think like
a lot of people can learn and really uh
like become productive with rust
um and the thing I would say about
like working in Rust having done a lot
of python is it really like
opens up the space of like things that
you can build and like the
characteristics of your program
um like I don’t think like everything I
said this in the in the Q a like you
know I don’t believe that all software
should be written in Rust
um but you know if you want to build
something that’s you know extremely
extremely performant
um or satisfy some of these other
characteristics
um it’s just very hard to do that in
Python for example and so like learning
rust opens up this space of like
Solutions and software that you can
build that would otherwise be somewhat
um inaccessible
and
you know I wouldn’t say like I actually
it’s really like not easy to learn rust
in my opinion like it I I don’t know at
least I found it
um I found it challenging um like you
really have to think about problems like
very very differently
um
好的,我会按照您的要求原原本本地整理内容,并翻译成中文,不会遗漏或省略任何内容。以下是整理和翻译后的内容:
欢迎来到今天由JetBrains组织的网络研讨会。我是Paul Everett,Python开发者倡导者,我将是您今天精彩网络研讨会的主持人。我们在幕后开玩笑说每次网络研讨会都很棒,我每次都这么说,但这次真的会很棒。今天网络研讨会的主题是”用Rust实现更快的Python代码检查”。”代码检查”就像我们今天要讨论的其他57件事一样。
今天的嘉宾是Charlie Marsh,Ruff的创建者。是的,Ruff已经很快成为一个可用的、强大的、快速的代码检查工具,被重要项目使用,也是新思维的载体。但Ruff是什么?Ruff不是什么?今天我们邀请到了多产的Ruff创建者Charlie Marsh。Charlie曾在可汗学院(没错,就是你想的那个)担任高级网络开发人员,最近在Spring Discovery担任高级软件工程师,从事有趣的Rust加Python加机器学习平台工作,现在全职从事Ruff工作。欢迎Charlie。
Charlie: 谢谢,非常感谢邀请我。你知道的,我是PyCharm的忠实用户和粉丝,所以能来这里很酷,我很感谢有机会与你们和观众讨论我们正在讨论的内容。顺便说一句,我最近在Talk Python播客上接受了采访,我听了整个采访,心想:哇,我们三周后就能见到他了。
Paul: 我的倡导同事Vitaly Bragarevsky也加入了我们。上次我们邀请Vitaly时讨论的是JavaScript,但我想这次关于Rust的话题对你来说可能更有趣。
Vitaly: 你好Paul,我喜欢所有编程语言,但当然Rust对我来说更有吸引力。谢谢你邀请我来。
Paul: 可以说你负责我们Rust插件的倡导工作,对吧?
Vitaly: 是的,没错。
Paul: 好的。顺便说一下,我们最近在PyCharm博客上对Charlie进行了采访,回答非常有趣,如果有机会去读一读。
Charlie,给我们简单介绍一下,什么是Ruff?为什么它很重要?
Charlie: Ruff是我所说的一个极其快速的Python代码检查工具。它是用Rust编写的Python代码检查工具,旨在实现极高的性能。如果你熟悉Python生态系统中的其他静态分析工具,其他代码检查工具,比如Flake8、Pyflakes、pycodestyle或Pylint,有很多这样的工具,它们都是静态分析工具,用于查看你的代码并试图识别问题或潜在问题。Ruff属于类似的工具类别,它会查看你的源代码,找出问题,并试图非常非常快速地做到这一点。
与一些其他工具不同,尽管有些工具也这样做,它还会尝试为你修复许多这些问题。因此,除了是一个代码检查工具外,它还执行这种自动修复和代码转换过程,这可以真正帮助加速开发,让你花更少的时间担心那些你想以自动化方式强制执行的事情。
Paul: 这是个很好的说法。我来自前端世界,所以那里发生了很多这样的事情。事实上,我认为你在某种程度上受到了前端世界正在进行的工具开发的启发。聊天室里的Doug Farrell说他同意你在Talk Python上的采访很棒,他说那次Talk Python采访让他把一个工作项目从Pylint切换到了Ruff。
Charlie: 太酷了,我很感激。那是我第一次参加播客,我猜这不是播客,但现在我已经是个老手了,希望这次能更顺利。那次很有趣,我很感激。
Paul: Rust与Python并列成为最受欢迎的语言。总的来说,或者对于这个主题,你认为Rust有什么吸引人的地方?
Charlie: 是的,完全是。你知道,这很有趣,比如一年前我真的不会认为自己会成为一个写很多Rust代码的人。我不是所谓的”系统程序员”之类的。我做过很多不同类型的项目,但我职业生涯的大部分时间都在使用JavaScript、TypeScript或Python,或者一些Java之类的。我几乎没写过C,可能在大学里写过一点,我想我从来没写过一行C++。
所以,我不认为我天生就适合成为一个Rust狂热者。这可能是我能给Rust本身的最大endorsement之一,就是如果我能做到,我认为很多人都可以学习并真正变得擅长使用Rust。
关于使用Rust工作,我要说的是,在做了很多Python之后,它真的打开了你可以构建的东西的空间,以及你的程序的特性。我在Q&A中说过,我不相信所有软件都应该用Rust编写。但是,如果你想构建一些极其高性能的东东,或者满足一些其他特性,在Python中做到这一点就非常困难。所以,学习Rust打开了这个解决方案和软件的空间,否则这些东西会somewhat难以接近。
我不会说学习Rust真的很容易,至少我发现它很有挑战性。你真的必须非常非常不同地思考问题。
—1—
uh and I still think they’re
I I don’t even know that I would claim
to be like a good rust programmer right
like I think I’m like a productive Russ
programmer and like I know how to work
in the language
um but
for me it’s like I can now write
software that I like otherwise wasn’t
really able to write and like felt
really scary and inaccessible to me and
so that’s part of why I love rust is
like it
um once I got into the right model I
felt like I could build like all these
amazing things
um and uh I think the community is
really great like there are tons of
really high quality
um crates which are like the third party
libraries or the things that you would
install from Pi Pi
um you know there’s like a lot of people
building like incredible open source
stuff to leverage
um and uh it’s once you get over
some of the initial hurdles around like
the borrow Checker
um
it’s just like really fun it’s a really
fun language to work in um you want to
comment on the comment on two parts of
that one the the point about it’s not
that easy to get into but also this idea
that it’s becoming tooling for other
languages like JavaScript or python or
whatever
do you want to comment on either one of
those points
was that to me or typical oh
yeah that’s that’s that’s really the
case for both communities we have I
think I think we have many many people
who try to rewrite their tooling to rust
uh but uh by the way I uh I want to ask
Charlie can can you give us like several
short reasons uh
why choose rust for your next project
okay can you can you give us something
like that yeah yeah so I think
um
I’ll talk specifically I guess about
python or some of this will be specific
to python so so one is like performance
right
um like it’s definitely possible to
write like really slow arrest programs
like it’s not like whatever you do in
Russia is going to be super fast
um but it does like change I guess like
the ceiling or the floor however you
look at it of like how fast your program
can be and like the kinds of things that
you can do that are just harder to do in
a in a language like python um
uh I think for python
the like rust python interoperability
um is really good and that’s actually
that was actually my entry point to rest
um I was working at Spring and we were
um we had this big at least by my
standards like python monorepo um
because we were doing all this
scientific Computing
um and
I spent a lot of time like trying to
make parts of that fast
um because like ultimately what I was
responsible for was like building sort
of the infrastructure and the developer
tools that a lot that are like machine
learning researchers and data scientists
were using and so I was trying to like
make all those you know like libraries
and tools really really fast
um and
you know we spent time like optimizing
some of that stuff in Python but
eventually we took some of those systems
and moved them into rust and so for
example like it’s sort of a stupid
example but it had a really big impact
we had like a a library that just
downloads files from cloud storage
um as quickly as possible and um we were
working with computer vision so it was
all like Imaging data so very very
common like you know thousands of times
a day right we’d like download terabytes
and terabytes of image data to like um
uh machines in the cloud and
the built-in Google libraries were
really slow and so we wrote like our own
like python thing that used like
multi-processing and
that was like faster but we kept like
running into bugs
um and then eventually we actually moved
that to rust so it was a rust Library
whose sole responsibility was just like
download files from cloud storage like
really really quickly
and uh in Python you can there’s this
really great tooling ecosystem around
these libraries called like Pi 03 and
Maturin and these let you take your rust
code and actually call it from python or
take your rust
um
package and publish it to Pi Pi that’s
actually what refuses so rough is
written completely in Rust there’s
actually like no Python and we publish
it to Pi Pi and we do that through this
this tool called Maturin which is part
of that Pi O3 ecosystem
so you know we started doing this and
like
um more and more of our sort of low
level you know Primitives you like move
them into rust and would call them from
Python and that was like to me that was
like oh this is like a superpower we can
like take this stuff and like move it
into Russ and then the callers the
people who are actually using those
libraries like have no idea that it’s
written in Rust and like don’t have to
even think about that like that’s
amazing
好的,我将继续整理并翻译剩余的内容:
我甚至不知道自己是否可以称得上是一个优秀的Rust程序员。我认为我是一个高效的Rust程序员,我知道如何使用这门语言。对我来说,现在我可以编写以前真的无法编写的软件,那些对我来说感觉很可怕和难以接近的软件。这就是我喜欢Rust的部分原因,一旦我进入正确的模式,我感觉我可以构建所有这些令人惊叹的东西。
我认为Rust社区真的很棒,有大量高质量的crates,这些就像是第三方库或者你会从PyPI安装的东西。有很多人在构建令人难以置信的开源stuff来利用。一旦你克服了一些初始障碍,比如借用检查器(borrow checker),它就是一个非常有趣的语言,用起来真的很有趣。
Paul: 你想评论一下这两点吗?一是它不容易入门,二是它正成为其他语言如JavaScript或Python的工具?
Vitaly: 是的,这确实适用于两个社区。我认为我们有很多人试图用Rust重写他们的工具。顺便说一下,我想问Charlie,你能给我们几个简短的理由,说明为什么要为下一个项目选择Rust吗?
Charlie: 好的,我想我会具体谈谈Python,其中一些会特定于Python。首先是性能,对吧?当然,写出非常慢的Rust程序也是可能的,不是说你在Rust中做的任何事情都会超快。但它确实改变了你的程序可以有多快的上限或下限,以及你可以做一些在Python这样的语言中更难做到的事情。
对于Python来说,Rust和Python的互操作性真的很好,这实际上是我进入Rust的切入点。我在Spring工作时,我们有一个很大的Python单体仓库,因为我们在做所有这些科学计算。我花了很多时间试图让其中的部分变快,因为我最终负责的是构建很多机器学习研究人员和数据科学家使用的基础设施和开发者工具,所以我试图让所有这些库和工具真的很快。
我们花时间在Python中优化了一些东西,但最终我们把一些系统移到了Rust中。举个有点愚蠢但影响很大的例子,我们有一个库,它只是尽可能快地从云存储下载文件。我们在处理计算机视觉,所以全是图像数据,非常常见,每天会从云中的机器下载数以太字节计的图像数据数千次。内置的Google库真的很慢,所以我们写了自己的Python东西,使用了多进程,这更快了,但我们一直遇到bug。最后我们实际上把它移到了Rust,所以它是一个Rust库,唯一的职责就是非常非常快地从云存储下载文件。
在Python中,有一个非常棒的工具生态系统,围绕着这些叫做PyO3和Maturin的库。这些让你可以拿你的Rust代码,实际上从Python调用它,或者把你的Rust包发布到PyPI。这实际上就是Ruff所做的。Ruff完全用Rust编写,实际上没有Python,我们把它发布到PyPI,我们通过这个叫Maturin的工具来做,它是PyO3生态系统的一部分。
所以,你知道,我们开始这样做,越来越多的底层原语,我们把它们移到Rust中,然后从Python调用它们。对我来说,那就像是一种超能力,我们可以把这些东西移到Rust中,然后那些调用者,实际使用这些库的人,完全不知道它是用Rust写的,甚至不用考虑这一点,这太神奇了。
—2—
um and that was a lot of the inspiration
for rough is I was like
can I build a linter in Rust that from
the user’s perspective like feels like
it’s written in Python like they don’t
need to have rust installed they don’t
need to know that it’s not written in
Python so it’s a very long way of saying
that like the interoperability between
rust and python specifically
it’s really good and so you can write
you know rough is not the only project
that does this you can write rust code
and make it feel like a python tool or
feel like a python Library
um which is which is great for users
because I think if rough if you had to
install rust to use rough uh very few
people would be using it and so the
ability to distribute like software that
way I think is really powerful
um yeah uh it’s interesting that was the
original superpower of python was moving
things to C and it’s interesting seeing
a new generation of that moving things
to rust it’s either
um it might be it tomorrow so uh one of
the Python old stirs has an article
about okay you want to speed something
up do you do it in C python or rust
and the conclusion is basically rust do
it do it for science on if it really is
very little
um and I guess uh Samuel Colvin is just
a few months ahead of you on that same
tool chain converting things in pedantic
to rust that’s right there there is a
bit of a trend for this now look real
quick so we can get to the demos but you
have a bigger vision for Ruff and your
work than just lenting right yeah
um
yeah I mean I you know I
I’m always hesitant to like commit to
stuff publicly just because things take
time right and like I don’t want to
create too much of a sense of
expectations but like
you know the dream
for rough
um is really to have like an integrated
tool chain
um and for static analysis at least
um and we’ve actually like maybe to to
give an example of what rough is today
like rough actually bundles a lot of
functionality that is split today
between lots of other tools so
um you know Ruff was originally modeled
after flake 8 so which is another Python
linter and that has some built-in set of
rules but what we did over time is we
started to take more and more of these
other popular static analysis tools and
actually just like build them into Ross
and when I say build them into into
rough I mean like we actually just like
rewrote big parts of them in Russia like
added into the project so
um uh you know like Pi docile which
checks stock strings that’s typically
distributed as a separate tool but rough
actually just like implements all of
that logic um Pi upgrade
um eyesore like all these other tools
um rough can actually do like
you know pretty much
what those tools can do
um so many of the tools do so many of
the same things what file changed on
disk
um it’s actually yeah so that’s actually
a funny thing because like so much of I
think you’d be surprised like how much
of rough’s code is like
finding the files to check
um finding the configuration resolving
the configure settings
um telling the user like what happened
like giving user feedback
um and like as we built Out rough we
have all this like
sort of like generic like winter or like
static analysis infrastructure of like
find all the python files like resolve
the pi project.com all files like figure
out what’s a first party import first
which is what’s a third party import and
so being able to like share all that
infrastructure is actually like speeds
up development a lot
um and
you know the other thing I will answer
your original questions the other thing
I like to point out about like the sort
of like bundling of doing more things
with one tool is that um it’s actually
can be a lot more performant
um because right now if you’re running
like five or six uh disparate tools
um
they might all have to do like a bunch
of repeated work that’s hard for them to
share and so uh for example like if
you’re passing your python files to like
five different tools and they’re all
reading the file parsing the AST oh yeah
traversing the AST maybe they do their
own like parsing logic
um that’s a lot of duplicated work and
so in rough
we parse the file one time right and
then all those tools like use that same
representation and we walk over the AST
one time and we you know do the right
checks in all the right places so you
can actually like share a lot of
infrastructure which both speeds up
development but also makes the tool much
faster
um and uh
that to me has been like a big
accelerant of like building more stuff
into rough like it’s it’s not that hard
for me to like add a new tool to to
rough because we already have a lot of
those abstractions built in related and
keep it quick because we do need to get
to the demo but the question
um are you not worried about the
maintenance cost of re-implementing all
those rules
uh uh I am I mean I think I would be
wrong not to sure um
uh but I do think that you get some
leverage out of having like a common
foundation so like we have one
abstraction for
um
like figuring out if if uh a variable is
a ref uh well sorry way to say this like
if we need to know if you have some
variable and it’s represents an import
of a certain thing from a certain file
like this happens all the time like if
we need to know if you know list is the
list import from the typing module and
maybe it was imported under an alias
maybe type the typing module is imported
under Alias there’s like all these
different ways that reference could be
to to list or not
um
we have like one way to do that and like
so many rules use it and so we don’t
have to implement like import tracking
like five or ten times we should be once
yeah
but the conclusion just say it’s your
original question and we’ll move on
I want rough to become like an
integrated uh winter Auto formatter and
potentially also a type Checker although
that’s the part that I admittedly know
the least about
um yeah but I just think that like
bundling the stuff together makes all
the tools potentially like more
performant and sure and stronger
um like we have to worry about
formatting in a bunch of places in rough
anyway and so integrating in Auto
formatter like actually makes that much
easier
um and
um I think it kind of Builds on the
strengths of what we’re already doing to
like push in that direction but all
those things take time sure okay let’s
go ahead and jump into the slides I’ll
go through them fast everybody wants you
not me
so uh with that in mind we like to make
this conversation this webinar is
conversational as possible as you can
already tell so if you have any
questions you’ll see me looking over
this way that’s where I’m looking at the
chat go ahead and ask them we’ll answer
them and Charlie will take some breaks
every now and then at the first break my
wonderful colleague will take the
comments and questions for that one so
whatever you have go ahead and ask them
usually the first question is is this
being recorded yes it’s being recorded
it’s YouTube they record everything so
this will be available basically
immediately right after the first uh
after the end of this
don’t be the first one to ask is this
being recorded
um we let’s see so that takes care of us
getting situated
we’re all set up with kind of the
background information everybody wants
to see a demo Charlie give us a walk
through rough
yeah let’s do it so um
I I want to like anchor this uh demo
around an existing project
and I don’t really have any like open
source repos right now that are big
enough to make rough like really
interesting so uh for the sake of
picking something like sort of
uncontroversial we’re going to use C
python so we’re going to look at using
rough on the C python code base
um I actually tend to use C python for
kind of a lot of things
um as the name suggests like a lot of C
python is written in C but by lines of
code it’s about two-thirds python I
think
um and it contains a lot of like very
diverse code
um you can just imagine there’s like a
lot of different stuff going on and so
it tends to be a good code base for like
testing and benchmarking and all that
kind of stuff
um so uh this is the C python code base
and here I just have my
um my terminal on the right um we’re
mostly going to be using Ralph from the
CLI but we’ll also look a little bit
about at using it within the editor and
I’ll talk a little bit about the at the
end about sort of other ways to like
install and use rough
um so the first thing that we’ll do is
we’ll just create a virtual environment
um and we will install rough
um now I sort of talked about this
before but like this in itself
is like a pretty cool thing right so
this tool is like written in Rust but I
just installed it right with Pip and
there was no like build step or anything
um you can install rough uh you know
just with Pip install rough um and we
did we pre-build these what are called
Wheels um and send them off to Pi Pi so
in almost all cases you don’t actually
need to do anything it just downloads
that and sets it up
um
so uh we have rough installed and let me
just move this around so we have rough
installed
um now what’s like the natural first
thing to do
um it I would say read the docs but that
wouldn’t really make for a great webinar
um so instead uh I think the first thing
we’ll do is we’ll just run it
um and uh
I guess like two observations from just
running rough over all the code in C
python so first
um it completes in like I don’t know a
couple hundred milliseconds which is
very cool
um but uh we have a lot of existing
errors right we have
um
18603 uh lint violations
um Ruff is telling us that about 2500 of
them can be automatically fixed but that
leaves a lot of errors and
so uh I want to mix I want to start
bringing that number down but before we
do that let’s try and make sense of like
what Ruff is doing and why it’s useful
on a slightly smaller scale so I’ll just
take this last file here which is I
don’t know some file in C Python and
I’ll just run her off over that file
alone and I’ll open it up over here
so um this is like some sort of
um webassembly build script that’s
included as part of C Python and when we
run uh rough over that file and it Flags
two potential issues
um and it tells us where those issues
are and a description of like what the
violation is
um so what’s actually just like jump I’m
going to close this let’s actually just
jump to
um that line 76. so we’re looking at
this error here and it says on line 76
we have an F string without any
placeholders
so if we look over here that’s this line
in Python we have these sort of format
strings and
um they’re designed to use these
placeholder Expressions where values get
um
好的,我将继续整理并翻译剩余的内容:
这也是Ruff的很多灵感来源。我在想,我能不能用Rust构建一个代码检查工具,从用户的角度来看,感觉就像是用Python写的?他们不需要安装Rust,不需要知道它不是用Python写的。这是一个很长的方式来说明Rust和Python之间的互操作性特别好,所以你可以写Rust代码,让它感觉像一个Python工具或Python库。
这对用户来说很棒,因为我认为如果使用Ruff需要安装Rust,很少有人会使用它。所以以这种方式分发软件的能力我认为是非常强大的。
Paul: 有趣的是,这曾经是Python的原始超能力,把东西移到C语言。现在看到新一代把东西移到Rust也很有趣。Python的一个老手写了一篇文章,说如果你想加速某些东西,你是用C、Python还是Rust来做?结论基本上是用Rust来做,为了科学而做,如果真的很少的话。我猜Samuel Colvin在同样的工具链上比你早了几个月,把pedantic中的东西转换成Rust。
Charlie: 是的,现在确实有这种趋势。
Paul: 快速说一下,这样我们就可以进入演示了,但你对Ruff和你的工作有一个比单纯代码检查更大的愿景,对吧?
Charlie: 是的。我总是很犹豫公开承诺什么,因为事情需要时间,我不想创造太多期望。但是对Ruff的梦想真的是有一个集成的工具链,至少对于静态分析来说是这样。实际上,Ruff已经捆绑了很多功能,这些功能今天分布在许多其他工具之间。
Ruff最初是模仿Flake8的,Flake8是另一个Python代码检查工具,它有一些内置的规则集。但随着时间的推移,我们开始采用越来越多这些其他流行的静态分析工具,实际上就把它们构建到Ruff中。当我说构建到Ruff中时,我的意思是我们实际上用Rust重写了它们的大部分,并添加到项目中。
比如pydocstyle,它检查文档字符串,通常作为一个单独的工具分发,但Ruff实际上实现了所有那些逻辑。pyupgrade、isort,所有这些其他工具,Ruff实际上可以做这些工具能做的几乎所有事情。
许多工具做了很多相同的事情,比如哪些文件在磁盘上改变了。你可能会惊讶,Ruff的代码有多少是用来查找要检查的文件、找到配置、解析配置设置、告诉用户发生了什么、给用户反馈等。当我们构建Ruff时,我们有所有这些通用的代码检查或静态分析基础设施,比如找到所有Python文件、解析pyproject.toml文件、弄清楚什么是一方导入和什么是三方导入。能够共享所有这些基础设施实际上大大加快了开发速度。
另一件我想指出的关于将更多功能捆绑到一个工具中的事情是,它实际上可能更高效。因为现在如果你运行5或6个不同的工具,它们可能都要做一堆重复的工作,很难共享。例如,如果你把Python文件传给5个不同的工具,它们都要读取文件、解析AST、遍历AST,可能还要做自己的解析逻辑,这就是大量重复的工作。而在Ruff中,我们只解析文件一次,然后所有这些工具使用相同的表示,我们只遍历AST一次,在所有正确的地方做正确的检查。所以你实际上可以共享很多基础设施,这不仅加快了开发速度,还使工具变得更快。
对我来说,这一直是在Ruff中构建更多功能的一个大加速器。对我来说,向Ruff添加一个新工具并不那么困难,因为我们已经有了很多内置的抽象。
Paul: 相关的,简短回答一下,因为我们确实需要进入演示,但问题是:你不担心重新实现所有这些规则的维护成本吗?
Charlie: 我确实担心,如果我说不担心那就错了。但我确实认为,有一个共同的基础可以获得一些优势。比如,我们有一个抽象来确定一个变量是否是某个东西的引用。比如我们需要知道如果你有一个变量,它代表从某个文件导入的某个东西,这种情况经常发生。比如我们需要知道list是否是从typing模块导入的list,可能它是以别名导入的,可能typing模块本身是以别名导入的,有很多不同的方式这个引用可能指向list或者不是。
我们有一种方法来做这个,很多规则都使用它,所以我们不需要实现导入跟踪5次或10次,只需要实现一次。
但总结一下你最初的问题,我们继续往下说:
我希望Ruff成为一个集成的代码检查器、自动格式化工具,可能还包括类型检查器,尽管这是我承认我最不了解的部分。我只是认为,把这些东西捆绑在一起可能会使所有工具更高效、更强大。无论如何,我们都必须在Ruff的很多地方处理格式化问题,所以集成一个自动格式化工具实际上使这变得更容易。我认为这kind of建立在我们已经在做的事情的优势上,朝那个方向推进,但所有这些事情都需要时间。
Paul: 好的,让我们继续看幻灯片,我会快速浏览,每个人都想看你而不是我。
所以,考虑到这一点,我们希望这次对话,这次网络研讨会尽可能具有对话性,你已经可以看出来了。如果你有任何问题,你会看到我往这边看,那是我在看聊天窗口,继续问吧,我们会回答,Charlie会时不时休息一下。在第一次休息时,我出色的同事会处理那时的评论和问题,所以无论你有什么问题,继续问吧。通常第一个问题是”这是否被录制了?”是的,它被录制了,这是YouTube,他们记录一切,所以这将在结束后基本上立即可用。
不要成为第一个问”这是否被录制了”的人。
好了,这就解决了我们的情况介绍。我们都准备好了背景信息,每个人都想看演示。Charlie,给我们演示一下Ruff。
Charlie: 好的,让我们开始吧。我想把这个演示围绕一个现有的项目进行。我现在没有任何足够大的开源仓库来让Ruff真正有趣,所以为了选择一些无争议的东西,我们将使用CPython。我们将看看在CPython代码库上使用Ruff。
我实际上经常用CPython做很多事情。顾名思义,CPython的很多代码是用C写的,但按代码行数计算,大约三分之二是Python。它包含了很多不同的代码,你可以想象有很多不同的东西在进行,所以它往往是一个很好的代码库,用于测试和基准测试等。
这是CPython代码库,这里我有我的终端在右边。我们主要会从命令行使用Ruff,但我们也会看一下在编辑器中使用它,最后我会谈一下其他安装和使用Ruff的方式。
首先,我们将创建一个虚拟环境,然后安装Ruff。我之前提到过,这本身就是一件很酷的事情。这个工具是用Rust写的,但我刚刚用pip安装了它,没有任何构建步骤。你可以用pip install ruff来安装Ruff。我们预先构建了这些所谓的wheels,并把它们发送到PyPI,所以在几乎所有情况下,你实际上不需要做任何事情,它只是下载并设置好。
我们已经安装了Ruff。现在,自然要做的第一件事是什么?我想说阅读文档,但那不会真的成为一个很棒的网络研讨会。所以相反,我认为我们要做的第一件事就是运行它。
从在CPython上运行Ruff,我们可以观察到两点。首先,它在几百毫秒内就完成了,这非常酷。但是,我们有很多现有的错误,我们有18,603个lint违规。Ruff告诉我们约2,500个可以自动修复,但这仍然留下了很多错误。
所以,我想开始减少这个数字,但在我们这么做之前,让我们试着理解Ruff在做什么,为什么它在更小的规模上有用。我将只取这里的最后一个文件,这是CPython中的一个文件,我将只在那个文件上运行Ruff,然后在这里打开它。
这是作为CPython一部分的某种WebAssembly构建脚本。当我们在那个文件上运行Ruff时,它标记了两个潜在的问题,它告诉我们这些问题在哪里,以及违规的描述。
让我们跳到第76行。我们看到这个错误说在第76行有一个没有任何占位符的f-string。如果我们看这里,这是Python中的这一行。我们有这些格式字符串,它们被设计用来使用这些占位符表达式,值会被插入其中。
—3—
uh evaluated and inlined into the string
and here we have an F string that
doesn’t have any of those placeholder
Expressions so it’s equivalent to just
you know removing that F prefix
um
that’s the first error uh the second if
we go down to line 601 is that we’re
binding this
um
uh socket connection to a variable s
that’s not used so this is equivalent to
just actually like removing that binding
entirely
um now this process uh that we went
through of like
talking through the code and trying to
understand what the issues do or what
the issues are
um rough can actually help with that in
like a couple interesting ways
so first of all we actually ship
um like embedded documentation with
rough so here we have this f541
violation which was the half string with
no placeholders I’ll just jump back to
that up here if we ask rough to tell us
about that rule
um
we actually ship with this sort of
markdown based documentation that tells
you this is a rule that came from PI
flakes
um it can always be automatically fixed
this is what the rule is here’s some
um I’ll just make this bigger for now
here’s some explanation of like why it
is a problem and here’s an example of
what it looks like before and what it
looks like after the fix
and uh
also useful is that if we run rough with
the show Source option it’ll actually go
through the process that we just went
through of showing us the exact lines of
code that are problematic so this is
this install native over here and
telling us how we might fix it
um so those are useful but of course
rough can also actually just fix the
errors for us so I just ran rough uh
with the dash dash fix flag and if we
look at the diff it removed that F
prefix and it got rid of that variable
binding uh I’m I’m sorry for
interrupting you but I just yeah I just
had that moment everyone has like did
you act did that actually run
it was so fast that you think it was
like in
dry run mode or something yeah yeah no
it actually ran
um and uh like I said it fixed the two
errors so now if we run rough over that
file right we’re not getting any
violations because the violations have
been fixed
um
so that’s like running rough over this
one file and like looking at the errors
and sort of understanding what they are
and how we might want to fix them
um but what we want to do right is right
off over this entire code base and get
it to a point at which we can actually
start like fixing errors and enforcing
these rules as we add new code to the
project
so
um the way that we’re going to do that
is uh through two strategies so one is
that
um we’re going to use rough to
automatically fix as many errors as we
can
and two we’re going to change rough’s
configuration to
better match what we actually want to
enforce and
accommodate all the existing errors that
we have in this project
um so uh all of rough’s configuration
um is done through
uh toml files
so here I just created a pi project.com
file
um rough also supports a rough.tomo file
if you’re not using pi project.tamil but
um this is sort of uh very common uh way
to express configuration for python
tools now
um
and uh a couple cool things I like to
point out about like I don’t know like
configuring tools is like an extremely
boring topic but um I think that like
rough does uh at least one very cool
thing here which pycharm also handles
really well which is that we ship
um a schema
for all of Russ configuration
and so if you open a pi product.com I’ll
file
um you know in your pycharm instance and
you type tool dot rough will
autocomplete and that’s not anything
that I’ve done
like as the user of rough to configure
this
um it’s purely because
we as the creators of the tool ship this
schema and pycharm picks that up and so
uh we actually get like Auto completion
and embedded documentation for all of
the configuration options in Roth
um which is I think like extremely
useful
um and uh we’re going to rely on that a
little bit here so like I said I haven’t
done anything special to configure a pie
chart for this
um uh it just picks this up uh poetry
also does this a little bit
um it’s not that common I wish it were
more common
um but uh we do have it rough which is
really useful
um
so what I want to do is we’re going to
start like changing the configuration of
rough a little bit but to do that let’s
actually just go back to oh sorry
I had a syntax error there
let’s actually go back to just running
rough and so
um like I said we have 18 600 errors and
if we just kind of look through there’s
like a lot of repeated
um issues and we might decide that like
we actually just don’t care that much
about enforcing those rules for now so
let’s go ahead and ignore them
so another way to look at this data is
we have this Dash test statistics flag
which will tell us all the rules and how
many violations we have in our existing
code so for example we have like 3 500
line like line length violations where
the lines of the code are too long so
let’s just like ignore those for now
um oops is e501
um we have a lot of violations around
having like multiple statements on one
line again I’m just going to ignore
those for now just to oops uh what was
it e701
um I’m just going to ignore those for
now just to like try to get the code
into a good State
um or try to get rough into a good State
um so we’re down to 13
000 errors from
whatever we started with which was a lot
more than that
um
you know if we look through there’s like
a couple more things that we might want
to
um
ignore so for example like
I’m just going to go ahead and ignore
um
all the test files
um which let’s just say that we don’t
care about renting those for now I also
know in advance that there’s a couple
other things like
um this file here uses a bunch of
um
sort of like magical Global stuff I’m
just going to skip it for the purpose of
the demo
um
and I’m just going to try and get rough
so now we’re down to 2700 errors which
is a lot more manageable
um and let me just for the purpose of
time to ignore a couple more things
so I’ve reduced the errors a lot sort of
by cheating by like turning off rules
that we don’t care about and ignoring
files that we don’t care about uh which
on the one hand is kind of cheating for
a demo but it’s also
um
like what you need to do is like tailor
rough to your project especially when
you’re coming into like a big new
project
um a lot of what you need to do is um
figure out what settings make sense for
you but there are two tricks that we can
use now
um to uh
to sort of um get our code into a state
where we can start enforcing rules so
the first is that we can just run
um fix over the entire project so that
fixed 495 errors and if we look at what
it changed
okay
um a couple of examples
here we had a dictionary where these
keys were repeated so it just removed
the second key
um
this role variable was not being used
anywhere so ref just removed the
assignment
um
uh etc etc sort of inverting the orders
of conditions to match have Aid
standards all that kind of stuff
removing unused Imports so these are
just rules that rough can can fix on its
own
um
the other I’m just going to commit this
um I don’t know whatever I’m just going
to commit this for the purpose of having
a clean get diff because the other thing
that we can do now
is let’s just go ahead and actually tell
Ruff to ignore all of those existing
errors
um I think this is like a really cool
trick
um so if we run rough with ADD no QA
what it’ll do is it’ll actually just add
these ignore comments to all of the
lines that had errors
um and uh that’s really useful because
now when we run rough we don’t have any
errors right
um and over time as we add new code
we will be required to enforce the rules
because new code won’t have this
comments and over time uh we can
actually like remove these comments as
we go and change code and refactor and
so we now have we’re often like a clean
State
um where from here we can start
enforcing rules we can start going
through and like fixing these issues and
like trying to understand which ones we
care about
um HR let’s take a take a break there
that no QA thing is freaking Magic
it’s cool right number of times I’ve
wanted that
the other thing is
kind of force that these comments are
actually required so if you add a no QA
to a line that doesn’t need it rough
will tell you that it’s unnecessary so
rough can like add all this to your
existing code and then as you fix issues
it can also tell you actually that’s not
needed anymore
um which uh I don’t know I think is like
a pretty pretty helpful workflow for for
a big new code base okay eventually is
going to give some comments and then I’m
going to process a bunch of questions
okay uh yeah Hannah writes uh now I want
to check out trust that’s great I think
that’s what we’re here for
yeah
yeah so so yeah Charlie just just
promotes Russ in a very good way so
thank you very much
um yeah of course yeah and then people
people here are just happy about the the
speed of uh
so it it’s really great and it’s really
just just just great and we have several
comments about that and then also
um
people say thanks people like that and
people like webassembly
so oh yeah
yeah yeah so we um
I guess one interesting thing that I
didn’t I mean I can just pull this out
because it’s
kind of cool
um
no hey don’t worry about it we’ll we’ll
process and ask you them one at a time
for example there was a comment from
pavilas who mentioned about plug-in
support you have an opinion about
plugins don’t you
I do have an opinion about plugins
um so
so right now rough does not support
plugins
um and instead what we’ve done is we’ve
basically implemented plugins as part of
rough that you can turn on and off and
um I’ll talk about some more of those in
a second
um I do eventually want rough to support
plugins
um
but it introduces like some technical
problems or some technical challenges
rather and it also
it sort of imposes some constraints on
the project because a nice thing about
rough right now and part of the reason
that we’re able to move
I think like pretty quickly is that we
don’t have much of a public API like the
public API is that command line
interface that I’ve been using but
everything else like inside of rough
like we can change dramatically because
there’s no one else depending on it and
so if I want to change like the lint
rule API or anything or like the AST
like how the asp’s model like anything
like that like we can all change it in
one place and like and like actually
just do that refactoring in all the
plugins so like in some sense or
rough is still like early right as a
project and I do want it to have it will
have a stable public API that will that
should include plugins
um but for now it’s a little bit of an
intentional thing to keep the project
sort of hermetic in this way where we
can like really control
um like how it’s being used just because
of some of the benefits it gives for us
to like ship quickly and adapt as we
learn about what it’s hard to predict
should be beforehand you gotta it is
yeah yeah I mean actually like I wanted
to do plugins earlier it’s sort of funny
and like I started on this path of like
building plugins into rough
because it’s pretty hard to do with Russ
yeah
um and so I was like okay what’s the
first plugin I need to like make this
usable for people all right I’ll just
implement it and then okay wait some
people need this I’ll just implement it
and so
you know what started as a arguably is a
bug like has now become like a feature
um and uh
a lot of people I actually find that out
like bundling
resonates pretty strongly with people
like there are a lot of people who are
like it’s great that rap is fast but
like that’s actually not important to me
and what’s useful is like that I replace
10 tools with rough
um and just the Simplicity of learning
one API in the tool installing one thing
hey before going to the next question uh
Vitaly do you want to comment on Rust
and plug-ins and Charlie’s Theory
okay so I I kind of know the answer to
this but I’ll let you answer it uh Eric
asks what’s the rationale for
integrating with rust python instead of
C Python’s AST module I know there’s a
discussion in a ticket what’s your
latest thinking and explain the role of
rust python in rough
yeah yeah that’s great so um rust python
is a really cool project
um
in some ways it’s like it’s like even
like way more ambitious than rough
because what they’re actually trying to
do or what they’ve what they’ve done you
know to a certain degree is
um build a new python interpreter and
runtime yeah in Rust
um and so rust python isn’t just
um like rough uses rust Python’s AST
parser so when we need to take python
source code and turn it into that tree
of okay here’s an import statement
here’s a function call
um we use the rust python parser which
takes the python source code and gives
us back this structured object that
tells us what the program consists of
um
but rust python is more than that parser
like in Rust python they use the parser
and then they actually execute the code
and like you know blah blah blah and we
just use the parser piece
um
the
I think there are like a couple reasons
why we use the rust python
parser
um as opposed to the C python parser
um the first is that it’s just the way I
did it when I first
and so that’s what we do the second
though is that um I think
uh the technical integration is a lot
easier
um because it’s it’s like we’re just
using another Library as opposed to
having to think about sea to rust
um
like the sort of foreign function
interface of like calling between CD and
rust
um and the other is that
um
it’s a lot like if you’re working on
rough and you’re writing Rusk it’s a lot
easier to
um
我会按照您的要求整理内容,使其变得合理通顺,并翻译为中文。我会尽量保留原文的所有内容,不做省略或总结。以下是整理并翻译后的内容:
uh被评估并内联到字符串中。这里我们有一个F字符串,它没有任何占位符表达式,所以它等同于只是删除那个F前缀。
这是第一个错误。第二个错误,如果我们下到601行,是我们将这个socket连接绑定到一个未使用的变量s上。这等同于完全移除那个绑定。
现在,我们刚刚经历的这个过程,就是通过代码并试图理解问题是什么或问题在哪里,Ruff实际上可以通过一些有趣的方式来帮助我们。
首先,我们实际上随Ruff一起发布了嵌入式文档。这里我们有这个f541违规,就是那个没有占位符的f-string。我’ll只是跳回到上面。如果我们让Ruff告诉我们关于那个规则的信息,我们实际上发布了这种基于markdown的文档,告诉你这是一个来自PyFlakes的规则。它总是可以自动修复。这就是规则的内容。这里有一些解释,说明为什么它是一个问题,这里有一个例子,展示了修复前和修复后的样子。
另外有用的是,如果我们用show Source选项运行Ruff,它实际上会经历我们刚刚经历的过程,向我们展示确切的有问题的代码行。这是这里的install native,告诉我们如何修复它。
这些都很有用,但当然Ruff也可以为我们实际修复错误。我刚刚用–fix标志运行了Ruff,如果我们看一下diff,它移除了那个F前缀,并去掉了那个变量绑定。对不起打断你,但我刚刚有了每个人都会有的那种时刻,就像你真的运行了吗?它太快了,以至于你以为它是在dry run模式或类似的模式下运行。是的,它确实运行了。
就像我说的,它修复了两个错误。所以现在如果我们在那个文件上运行Ruff,我们不会得到任何违规,因为违规已经被修复了。
所以这就像在这个文件上运行Ruff,看看错误是什么,以及我们可能如何修复它们。但我们真正想做的是,对这整个代码库运行Ruff,并让它达到一个我们实际上可以开始修复错误并在我们向项目添加新代码时强制执行这些规则的状态。
我们将通过两种策略来做到这一点。一是我们将使用Ruff自动修复尽可能多的错误。二是我们将改变Ruff的配置,以更好地匹配我们实际想要执行的内容,并适应我们在这个项目中已有的所有现有错误。
所有Ruff的配置都是通过toml文件完成的。这里我刚刚创建了一个pyproject.toml文件。Ruff也支持ruff.toml文件,如果你不使用pyproject.toml的话。但这是表达Python工具配置的一种非常常见的方式。
我想指出的几个很酷的事情,关于像,我不知道,配置工具是一个非常无聊的话题,但我认为Ruff至少做了一件非常酷的事,PyCharm也处理得很好,那就是我们发布了Ruff所有配置的模式。
所以如果你在你的PyCharm实例中打开一个pyproject.toml文件,你输入tool.ruff,它会自动完成。这不是我作为Ruff的用户为配置这个做的任何事情。它纯粹是因为我们作为工具的创造者发布了这个模式,PyCharm就会捕捉到它。所以我们实际上得到了Ruff所有配置选项的自动完成和嵌入式文档。
我认为这非常有用。我们将在这里稍微依赖一下这个。就像我说的,我没有做任何特别的事情来为这个配置PyCharm。它只是捕捉到了这个。Poetry也做了一点这个。它不是那么常见,我希望它更常见。但我们确实在Ruff中有它,这真的很有用。
所以我想做的是,我们要开始稍微改变Ruff的配置,但要做到这一点,让我们实际上回到只是运行Ruff。
就像我说的,我们有18600个错误,如果我们只是看一下,有很多重复的问题,我们可能会决定我们实际上现在并不那么在意执行这些规则。所以让我们继续忽略它们。
查看这些数据的另一种方式是,我们有这个–statistics标志,它会告诉我们所有的规则以及我们在现有代码中有多少违规。例如,我们有大约3500个行长度违规,代码行太长。所以让我们暂时忽略这些。哎呀,是E501。
我们有很多关于在一行上有多个语句的违规。我再次暂时忽略这些。哎呀,是什么来着?E701。我只是暂时忽略这些,只是为了尝试让代码进入一个好状态。或者说,尝试让Ruff进入一个好状态。
所以我们从原来的不管多少错误减少到了13000个错误。
你知道,如果我们看一下,还有一些我们可能想要忽略的东西。例如,我只是要继续忽略所有的测试文件。我们暂时不关心运行这些。我也提前知道还有一些其他的东西,比如这个文件使用了一堆魔法全局变量,为了演示的目的,我就跳过它。
我只是要尝试让Ruff…现在我们减少到2700个错误,这要容易管理得多。让我为了时间考虑再忽略几个东西。
我通过作弊大大减少了错误,通过关闭我们不关心的规则和忽略我们不关心的文件。这一方面对于演示来说有点作弊,但另一方面,这也是你需要做的,就是为你的项目定制Ruff,特别是当你进入一个新的大项目时。你需要做的很多事情就是弄清楚什么设置对你有意义,但现在我们可以使用两个技巧来让我们的代码进入一个可以开始执行规则的状态。
第一个是我们可以在整个项目上运行fix。这修复了495个错误。如果我们看看它改变了什么…好的。
这里有几个例子。这里我们有一个字典,这些键被重复了,所以它只是移除了第二个键。这个role变量在任何地方都没有被使用,所以Ruff只是移除了赋值。等等等等,颠倒条件的顺序以匹配PEP 8标准,所有这些东西,移除未使用的导入。这些只是Ruff可以自己修复的规则。
我只是要提交这个。我不知道,不管怎样,我只是要提交这个,目的是为了有一个干净的git diff。因为我们现在可以做的另一件事是,让我们继续实际告诉Ruff忽略所有那些现有的错误。
我认为这是一个非常酷的技巧。所以如果我们用–add-noqa运行Ruff,它实际上会给所有有错误的行添加这些忽略注释。
这真的很有用,因为现在当我们运行Ruff时,我们没有任何错误。随着时间的推移,当我们添加新代码时,我们将被要求执行规则,因为新代码不会有这些注释。随着时间的推移,我们实际上可以在我们继续修改代码和重构时移除这些注释。所以现在我们有了Ruff处于一个干净的状态。
从这里开始,我们可以开始执行规则,我们可以开始检查这些问题并尝试理解我们关心哪些。HR,让我们在这里休息一下。那个noqa的东西简直是魔法。
是的,很酷吧?我想要这个的次数…另一件事是,这些注释实际上是必需的,所以如果你在一行不需要的地方添加了noqa,Ruff会告诉你它是不必要的。Ruff可以给你现有的所有代码添加这些,然后当你修复问题时,它也可以告诉你实际上不再需要那个了。
我不知道,我认为这对于一个新的大代码库来说是一个相当有帮助的工作流程。好的,最后会给出一些评论,然后我会处理一堆问题。
是的,Hannah写道,现在我想检查一下Ruff。那很好,我想这就是我们在这里的原因。
是的,所以Charlie只是以一种非常好的方式推广Ruff。所以非常感谢你。
是的,当然。然后人们在这里只是对Ruff的速度感到高兴。所以它真的很棒,真的只是很棒,我们有几条关于这个的评论,然后还有人说谢谢,人们喜欢它,人们喜欢WebAssembly。
是的,我们…我想一件有趣的事情,我没有…我的意思是,我可以把这个拿出来,因为它很酷。
不,别担心,我们会一个一个地处理并问你问题的。例如,Pavelas评论了关于插件支持的问题。你对插件有看法,对吗?
我确实对插件有看法。所以现在Ruff不支持插件。相反,我们基本上实现了插件作为Ruff的一部分,你可以打开和关闭。我稍后会谈到更多这些。
我最终确实想让Ruff支持插件。但它引入了一些技术问题或者说技术挑战,它也给项目施加了一些限制。因为Ruff现在的一个好处,也是我们能够移动得相当快的部分原因是,我们没有太多的公共API。公共API就是我一直在使用的命令行界面,但是Ruff内部的其他所有东西,我们都可以大幅改变,因为没有其他人依赖它。所以如果我想改变lint规则API或任何东西,或者像AST,像AST的模型,像任何那样的东西,我们都可以在一个地方改变它,并且实际上在所有插件中做那个重构。
所以在某种意义上,Ruff作为一个项目仍然是早期的,我确实想让它有一个稳定的公共API,这应该包括插件。但现在,这有点是一个故意的事情,让项目以这种方式保持封闭,我们可以真正控制它是如何被使用的,只是因为它给我们带来的一些好处,可以快速发布和适应,因为我们了解到事先很难预测应该是什么样子。
你明白了吗?是的,是的。我的意思是,实际上我想更早地做插件,这有点有趣。我开始走上这条用Rust构建插件到Ruff的路,因为用Rust做这个相当困难。
所以我想,好吧,我需要什么第一个插件来让这对人们有用?好,我就实现它。然后好吧,有些人需要这个,我就实现它。所以你知道,开始时可以说是一个bug,现在已经成为一个特性。
很多人,我实际上发现,喜欢捆绑。这与很多人产生了强烈的共鸣。有很多人说,Ruff快速很好,但这对我来说实际上并不重要。有用的是我用Ruff替换了10个工具。
仅仅是学习一个API工具的简单性,安装一个东西。在进入下一个问题之前,Vitaly,你想评论一下Rust和插件以及Charlie的理论吗?
好的,所以我有点知道这个问题的答案,但我会让你来回答,Eric问,选择集成Rust Python而不是CPython的AST模块的理由是什么?我知道在一个ticket里有讨论。你最新的想法是什么?能解释一下Rust Python在Ruff中的角色吗?
是的,是的,这很好。所以Rust Python是一个非常酷的项目。在某些方面,它甚至比Ruff更有野心,因为他们实际上试图做的,或者他们已经做到的,你知道,在某种程度上,是用Rust构建一个新的Python解释器和运行时。
所以Rust Python不仅仅是…像Ruff使用Rust Python的AST解析器。所以当我们需要获取Python源代码并将其转换为那棵树时,这里是一个import语句,这里是一个函数调用,我们使用Rust Python解析器,它接收Python源代码并给我们返回这个结构化对象,告诉我们程序由什么组成。
但Rust Python不仅仅是那个解析器,在Rust Python中,他们使用解析器然后实际执行代码,诸如此类。我们只使用解析器部分。
—4—
go and understand and like change the
rust code in Rust Python and so we
actually like contribute a lot of
compatibility improvements to breast
python like people who work on rough
often will go and and you know send PRS
unrest Python and so like having all the
Tooling in one language
um is really helpful
um now if we use the C python AST that
might like I don’t imagine that we would
need to change a lot of things like
because that’s actually the reference
implementation but I think that like
using one language ecosystem all the way
down that stack is actually like pretty
helpful
and uh it’s cool to be able to like
support Russ Python and Russ python
supports rough and all that let’s go on
to the next one uh I provided a link to
the ticket on about let you talk about
it when they saw you fixing things they
said hey this isn’t letting this is
getting into Black’s territory so I
linked oh yeah the ticket
where you talk about how you feel about
it and then the black and the blue both
came into the discussion about it you
want to just say a couple of sentences
how you feel about that
yeah totally so um
so rough like rough is always designed
to be used
um
Ruff was was designed to be used
alongside black
um but doesn’t it doesn’t have to be
um but we do you know the way that we
Implement Auto fixing
um we always try and do it in a way
that’s like compatible with black
in most cases
um
I guess one like funny caveat there is
roughkin and force quote Styles and
black almost always uses these double
quote marks yeah
um but some people feel really strongly
about like using single quote marks um
instead and so we actually yeah so we
actually have a limp rule that’s
configurable
around quote style and so you could
actually use rough to enforce and
automatically change your project to use
single quotes
something that Samuel Coleman asked word
um uh but just to wrap it up you have an
interest in trying to tackle some of
formatting is that right yes yes
absolutely sorry
um
I want uh we’re in the process process
of building an auto formatter which will
be integrated into graph
um it won’t be like say about it right
there are a bunch I actually open
sourced a bunch of the code
um last night okay just completely
coincidentally
um I’ve been I’ve been working on a
private Fork just while I kind of
figured out some of the initial design
and like played around with lots of dumb
ideas
um and now that I felt like it’s sort of
on a good path
um I’m going to merge it all into rough
scene
um it’ll be a while
like it doesn’t handle I I don’t I don’t
want people to get the wrong impression
because a lot of things that doesn’t
handle sure sure and this is early day
but don’t need to really give a status
update on all that but people can keep
in mind that you can go to the repo and
find uh information on this last little
point then we’ll do a demo we’ll save up
the other questions for the next segment
some people asked um we’re talking about
pycharm plugins and kudai who did the
plug-in for pedantic back in the day
um has a pie charm plug-in you have a
language server for vs code someone was
asking about ale for them does that mean
anything to you
uh like honestly not really but I’m
pretty sure it is supported okay because
yeah the funny thing about working on
like this kind of tooling is like you
find out about all these editors and
like editor Integrations that you never
use
um we’re just we’re just not to say
they’re not useful but like you know I
never use like the Helix editor before
for example indeed some people were like
hey is there a way to integrate it off
with Helix and so then I find myself
downloading Helix like figuring out how
to do that um and
um similarly like I’m so hopeless with
them
um and like neovim
um it’s like really embarrassing in a
way and I’ve had to spend a bunch of
time like making sure that you know the
plugins work because like people want
different tooling
um
it’s fine to say not on your radar so
yeah go ahead and proceed yeah we do I
mean I will just shout out we do
um this was built by kudai um so this is
built by someone in the community it’s
this rough
um pie charm plug-in
um I use it um it’s actually the thing
that uh
is giving me this error here so like we
already this is this is leveraging that
rest
um that rust extension
um you know highlighting that this is
the error and that this is the way to
fix it um so it’s powered by rough and
by that plug-in which is very cool one
of the nice things about a pie charm
plug-in is
unlike black where a demon has to be
managed rough is so fast you don’t need
a demon
yeah yeah
we’ll uh
uh hopefully it doesn’t get to the point
that it needs a demon as we add more and
more features
cool
um so you know I guess what I wanted to
do next is like um we now have the
project in this like clean State
um but up to this point
we’ve only been looking at the pie
Flakes and Pie code style rules which
are also the ones that ship with flake 8
right so all those rules with the F and
the E prefix
um uh that’s all we’ve been enforcing on
the project
um
uh and we’ve touched on this a couple
times now but rough like by Design
actually ships with like all of these
different
um
plug-ins you could call them they are
they’re sort of plugins they’re sort of
not because they’re like built directly
into the tool
um but uh all of these are implemented
like re-implemented in Rust as part of
rough
um but they are almost all inspired or
based on the API of some other existing
tool which is why we use that
terminology here so for example like the
pi doc style rules right are all
prefixed with d uh we have like the pi
upgrade rules the ice we Implement isort
as part of rough which is maybe a little
surprising but like uh I think really
cool
um all these flight gate plugins blah
blah
um so what’s happening here is it’s just
telling you and this is all in the
documentation has a much better like
tabulation of all this but um
these are all the different sort of
sub-linters that rough implements and
these are the code this is the prefix
code for those rules
um so rough isn’t really designed
uh you know or it’s not the expectation
is not that like I’m gonna enable all of
these rules on my project and I’m going
to adhere to all of these rules some
people actually use rough that way which
um is totally fine but like in my head
rough is kind of designed to be used in
a little bit more of like an A La Carte
like manner
um like not every project you know is
going to care about uh having enforcing
type annotations right and so if your
project doesn’t care about having all
type annotations on all of your
functions then you probably shouldn’t
enable like the flake annotations Rule
and so I think part of like adopting
rough is
you can kind of look at what’s supported
you know and similarly like you don’t
want to use the Django rules if you’re
not working in a Django app so part of
like working with rough is what rules do
I want I can add more over time like
what makes sense for my project
um uh but it’s it’s really powerful
because like you’re not like learning
any new tool right it’s just the same
API and it’s just changing the flags so
for example like if I wanted to
let’s say I want to start enforcing
import sorting on my project
um I can just add this dash dash select
I flag
um and I’ll run it with auto fixing and
um it fixed 735 new errors right these
are errors that didn’t exist before
because we weren’t enforcing the rule
um and if we look right it’s now just
like
um splitting up the Imports and uh
organizing them in a way that’s like
compatible with um
with uh what I saw would do so in some
cases can you can you do a revert and
rerun that with the time command in
front because I want to see oh sure yeah
that’s impossible
I’ll run it with no cash as well
just make sure that there’s no caching
at all and so I think it was 224
milliseconds or something like that yeah
it wasn’t two seconds so I think it was
this number in the chat about it got
everybody to guess how many seconds it
would take and as I was typing seconds I
knew it was the wrong unit of measure
um but you know for me like I think this
is a really cool model because
um
like
flake it comprehensions is another
interesting plugin so this is
um
uh maybe it’s actually just better best
demonstrated by example so I just I just
ran it I just added a bunch of enabled a
bunch of new rules it fixed 101 new
violations and if we look at what it did
um
so this plug-in again it’s like a little
bit opinionated so not every product
should turn this on but if you want to
enforce this it changes it from
um using a like the built-in invocation
on a generator to just using a
comprehension
um and uh you know it can do this
throughout your code base and
um like part of the beauty of fast
tooling is that you can just like do all
this experimentation and like it costs
you nothing like like you can try out
different roles right and like turn them
on turn them off like see what changes
see what doesn’t
um and the key is that like you just
have like a super fast iteration Loop
um and so uh
I have sort of like idiosyncratic
reviews about performance but like
that’s one of the reasons that I think
like developer tools especially you
should like really care about
performance
um because it’s like
it’s the thing that you’re running
constantly right and it’s like making a
developer tool like like 10 faster
um the productivity that you gain for
like all your other work right it just
really Stacks up
um and so uh
you know there’s like stuff to learn
with rough and there’s like a lot of
rules like you have to figure out what
you want but like you can actually just
iterate super quickly and like try
things and throw things out
um and it’s part of what I want the
experience of rough to feel like is like
I’m never like sitting around waiting
for rough to run like I can try the
thing and it didn’t work and I revert it
or I try the thing and I commit it blah
blah
um
uh there’s a bunch more like
like I said there’s a lot more
um like very I think very cool stuff in
here
um like Pi upgrade is like a pretty
amazing tool
um and uh we implemented a lot of the
rules that Pi upgrade enforces so that
could do things like
um
automatically upgrading like your type
annotations or like
um uh I don’t know what else
um upgrading your string formats like
instead of using percent formatting it
can automatically rewrite it to use like
dot format calls or F string and all
that kind of stuff
um so
um I hope that adopting Rob
feels like gaining access to like this
huge tool belt
um of like gadgets right or like super
powers or like whatever analogy you want
to use
um where this list is like big and you
can pick what makes sense for your
project but it’s also like growing a lot
like we just like we try to ship
like pretty quickly and like Implement a
lot of new stuff
um and so part of like
you know adopting rough and like and
then choosing to use it for your project
is that you’re gaining access to this
like stream of improvements too
um and uh
um you know not every rule will make
sense for every project but hopefully
you’ll find a bunch of things here that
will help you write
um
better python code faster I think is
like the simplest way I could put it I
want to take some more questions
for uh yeah of course all right so I’ll
uh Vitaly we’ll start with a comment but
first you mentioned pie upgrade that’s
Adam Johnson right
uh
flake comprehensions is Adam Johnson
High upgrade is Anthony satiel oh that’s
right yes okay sorry all right I don’t
know if I’m pronouncing those names yeah
exactly correctly because I never hear
them say out loud I only read them on
the Internet so but yeah great tools
okay eventually what do you have
um yeah with rust it’s actually very
easy to to write slow programs so it’s
not just granted for free so uh so and
that’s why I want to ask you so was it
really you just do nothing and it just
runs fast or maybe you you’re just very
smart optimizing rust programs and it
was like very very hard job optimizing
them what does day one
zero seconds yeah yeah so I think like
um
well the first thing which I can’t take
I cannot take any credit for is that the
parser is fast and the parser the rust
python parser and that’s a good chunk of
rough’s total execution time
um just parsing python code
um which is which I guess is good
because it means we’re like not spending
like the rest of the stuff is is fast
but but the parser is very fast
um
I guess like a couple other things I
think about when it comes to Performance
one is like I can’t remember what the
exact expression is but with Russ you
can often have this like
is it like Fearless concurrency or
something I can’t remember how people
put it but basically like it’s just like
really easy to like paralyze your code
and
um so you use this asynchronous
programming with a sync weight calls and
stuff like that we just use rayon so
which is a library for so we all we have
to do right now it’s a pretty simple
model we just paralyze across files
eventually we’re going to have to get a
lot more fine-grained
um but that’s worked so far
um so it’s kind of like if in Python
right you were multi-processing and each
file got its own got its own um
task or to process task or whatever you
want to call it
um I guess the difference is like I mean
I like python a lot right like I’ve
written a lot of python but I always
think that multi-processing is really
tricky
um there’s just it’s just very easy to
get wrong and I often find the
performance characteristics to be very
confusing
um like sometimes I use threads when I
sometimes like threads or outperforming
processes and I don’t really know why or
sometimes I want to multi-process and
now I have some object that’s not
pickleball and I’m like stuck trying to
understand all these issues
um and I never really feel that way with
thrust like I can kind of just
parallelize and like if the code
compiles like
it works and it’s like really fast
um so like being able to paralyze like
massively and not having to spend a lot
of time thinking about it helps a lot
um and then
the other things like it’s a little low
level but like just trying to like avoid
allocations everywhere that we can and
like really forcing myself to like not
allocate new variables so
um that was pretty hard to get right but
like we do very few allocations
um
I mean ultimately with performance
though it’s really just about like
like some of it’s about
some of it’s cultural like you decide in
a project that like you really care
about the performance is like really
important and So then whenever we ship a
big new thing I’m like always going to
Benchmark it
um and that comes at a cost but like you
know I think it’s worth it given the
project and that becomes a pattern that
people people actually care about
um and I hinted at it but the other
thing is like you just have to be like
benchmarking a lot and like constantly
because
I don’t know there’s so many things
where like
I think maybe part of your CI right
it’s not now I want I want to but the
benchmarks basically only exist on my
machine they’re all they’re all tuned to
my machine
um but like you know there are things
where it’s like oh I read about some
really cool thing that I could do that’s
like in theory should like speed the
program a lot and then it like doesn’t
really make a difference because
that part of the program’s actually like
not doing that much work so even if it’s
a hundred times faster like you don’t
notice you’re not going to notice it at
the end
我理解您的要求。我会按照原文的顺序整理内容,使其更加连贯通顺,同时保留所有原始信息,不会遗漏或总结任何内容。然后我会将整理后的内容翻译成中文。请允许我开始整理和翻译:
理解并修改Rust Python中的Rust代码,我们实际上为Rust Python贡献了许多兼容性改进。在Rust上工作的人经常会向Rust Python发送PR。因此,在一种语言的生态系统中拥有所有工具实际上是非常有帮助的。
现在,如果我们使用C Python AST,我认为我们可能不需要改变太多东西,因为那实际上是参考实现。但我认为在整个技术栈中使用一种语言生态系统实际上是非常有帮助的。能够支持Rust Python,而Rust Python又支持Rust,这一点很酷。
让我们继续下一个话题。我提供了一个关于你讨论的票据的链接。当他们看到你在修复东西时,他们说这正在进入Black的领域。所以我链接了那个票据,你在那里谈到了你的感受,然后Black和Blue都加入了讨论。你想简单说几句你对此的看法吗?
当然。Ruff从一开始就被设计为与Black一起使用,但它不是必须的。但是我们实现自动修复的方式,我们总是尝试以与Black兼容的方式来做。
在大多数情况下,有一个有趣的例外是Ruff可以强制执行引号样式,而Black几乎总是使用双引号。但有些人对使用单引号感觉很强烈。所以我们实际上有一个可配置的lint规则来处理引号样式,你可以使用Ruff来强制并自动将你的项目改为使用单引号。
你有兴趣尝试解决一些格式化问题,对吗?
是的,绝对是的。我们正在开发一个自动格式化器,它将被集成到Ruff中。它不会像…好吧,我实际上昨晚开源了一堆代码,这完全是巧合。我一直在私人分支上工作,只是为了弄清楚一些初始设计并尝试一些愚蠢的想法。现在我觉得它走上了一个好的道路,我要把它全部合并到Ruff中。
还需要一段时间,它还不能处理很多东西。我不希望人们产生错误的印象,因为有很多东西它还不能处理。
当然,这还处于早期阶段,但不需要真正给出所有的状态更新,但人们可以记住,他们可以去仓库找到这方面的信息。
最后一点,然后我们会做一个演示,我们将把其他问题留到下一个环节。有人问到PyCharm插件,Kudai以前为Pedantic做了插件,现在为PyCharm做了插件。你有VS Code的语言服务器,有人在问Vim的ALE,这对你来说有意义吗?
老实说,不太了解,但我很确定它是支持的。因为你知道,有趣的是,当你在做这种工具时,你会发现很多你从未使用过的编辑器和编辑器集成。这并不是说它们不有用,但是你知道,我以前从未使用过Helix编辑器。
确实,有些人问是否有办法将Ruff与Helix集成,所以我发现自己在下载Helix,弄清楚如何做到这一点。同样,我在Vim和Neovim方面也很无助,这有点尴尬,我不得不花很多时间确保插件能正常工作,因为人们想要不同的工具。
没关系,可以说不在你的雷达上。
我们确实有一个PyCharm插件,这是由Kudai构建的,是社区中的某个人构建的。我使用它,它实际上是给我这个错误的东西。所以我们已经利用了那个Rust扩展,突出显示这是错误,这是修复它的方法。它由Ruff和那个插件驱动,这非常酷。
PyCharm插件的一个好处是,与Black不同,不需要管理守护进程,Ruff非常快,不需要守护进程。
希望随着我们添加越来越多的功能,它不会达到需要守护进程的程度。
好的,我想接下来要做的是,我们现在已经让项目处于这种干净的状态,但到目前为止,我们只看了Pyflakes和Pycodestyle规则,这些也是与Flake8一起发布的规则。所以所有那些带F和E前缀的规则,这就是我们一直在项目上强制执行的。
我们已经多次提到过,Ruff在设计上实际上附带了所有这些不同的插件,你可以称它们为插件,它们某种程度上是插件,某种程度上又不是,因为它们直接构建在工具中。
但是所有这些都是作为Ruff的一部分在Rust中重新实现的,但它们几乎都是受到或基于一些其他现有工具的API的启发,这就是为什么我们在这里使用这种术语。例如,所有以D为前缀的Pydocstyle规则,我们有Pyupgrade规则,我们在Ruff中实现了isort,这可能有点令人惊讶,但我认为真的很酷。
所有这些Flake8插件等等。这里发生的是,它只是告诉你,这在文档中有更好的表格,但这些是Ruff实现的所有不同的子linter,这些是这些规则的前缀代码。
Ruff并不是真的被设计成,或者说期望不是说我要在我的项目上启用所有这些规则,我要遵守所有这些规则。有些人确实以这种方式使用Ruff,这完全没问题,但在我看来,Ruff的设计更像是以一种更加à la carte的方式使用。
不是每个项目都会关心强制执行类型注释,对吧?所以如果你的项目不关心在所有函数上都有类型注释,那么你可能不应该启用Flake注释规则。所以我认为采用Ruff的一部分是,你可以看看支持什么,同样,如果你不是在Django应用中工作,你就不想使用Django规则。因此,使用Ruff的一部分是,我想要哪些规则,我可以随时添加更多,什么对我的项目有意义。
这真的很强大,因为你不是在学习任何新工具,它只是相同的API,只是改变了标志。例如,如果我想开始在我的项目上强制执行导入排序,我可以只添加这个–select I标志,我会运行它并自动修复,它修复了735个新错误,这些错误以前不存在,因为我们没有强制执行规则。
如果我们看,它现在只是分割导入并以与isort兼容的方式组织它们。在某些情况下,你能不能回退并在前面加上time命令重新运行,因为我想看看…
当然,我也会用no-cache运行,以确保没有任何缓存。我想它是224毫秒左右,不是2秒。我在聊天中让每个人猜需要多少秒,当我输入秒时,我知道这是错误的度量单位。
但对我来说,我认为这是一个非常酷的模型,因为Flake8 comprehensions是另一个有趣的插件。这可能通过例子更好地展示。我刚刚运行了它,我刚刚添加了一堆新规则,它修复了101个新违规,如果我们看看它做了什么,这个插件再次有点固执己见,所以不是每个产品都应该打开它,但如果你想强制执行这个,它会从使用内置调用生成器改为使用推导式。
你知道,它可以在整个代码库中这样做,快速工具的美妙之处在于,你可以做所有这些实验,它不会花费你任何东西,你可以尝试不同的角色,打开它们,关闭它们,看看什么改变了,什么没有改变。
关键是你只有一个超快的迭代循环,所以我对性能有一些特殊的看法,但这是我认为开发者工具特别应该关心性能的原因之一,因为它是你不断运行的东西,使开发者工具快10倍,你获得的所有其他工作的生产力,它真的会累积起来。
所以,使用Ruff有很多东西要学,有很多规则,你必须弄清楚你想要什么,但你实际上可以非常快速地迭代,尝试事情并丢弃事情。这是我希望使用Ruff的体验感觉像的一部分,我从来不会坐在那里等待Ruff运行,我可以尝试这个东西,它不起作用,我回退它,或者我尝试这个东西,我提交它,等等。
还有更多,就像我说的,这里有更多非常酷的东西。比如Pyupgrade是一个非常amazing的工具,我们实现了Pyupgrade强制执行的许多规则。所以它可以做一些事情,比如自动升级你的类型注释,或者升级你的字符串格式,比如不使用百分比格式化,它可以自动重写以使用.format调用或f-string等所有这类东西。
所以我希望采用Ruff感觉像是获得了这个巨大的工具箱,或者说超级能力,或者你想用什么比喻。这个列表很大,你可以选择对你的项目有意义的东西,但它也在快速增长,我们试图快速发布并实现很多新东西。
所以采用Ruff并选择在你的项目中使用它的一部分是,你获得了这个改进流的访问权。不是每个规则都适合每个项目,但希望你能在这里找到一堆东西,帮助你更快地写出更好的Python代码。我想这是我能说的最简单的方式。
我想再问一些问题。
当然可以。
Vitaly,我们从一个评论开始,但首先你提到了Pyupgrade,那是Adam Johnson,对吧?
Flake comprehensions是Adam Johnson的,Pyupgrade是Anthony Sottile的。哦,对的,抱歉。我不知道我是否正确发音了这些名字,因为我从未听过他们说出口,我只是在网上读到的。但是,是的,很棒的工具。
Vitaly,你有什么要说的吗?
是的,用Rust实际上很容易写出慢程序,所以它不是免费获得的。所以我想问你,它真的是你什么都不做,它就运行得很快,还是说你只是非常擅长优化Rust程序,优化它们是非常困难的工作?第一天就是0秒?
是的,我认为,嗯,第一件事,我不能邀功的是解析器很快,Rust Python解析器是Ruff总执行时间的一大部分,只是解析Python代码,这我想是好事,因为这意味着我们没有花太多时间在其他事情上,但解析器非常快。
我想,关于性能,我考虑的另外几件事,一个是,我记不清确切的表达是什么,但用Rust,你经常可以有这种,是不是叫”无畏并发”还是什么,我记不清人们是怎么说的,但基本上就是,并行化你的代码真的很容易。
所以你使用异步编程,使用async/await调用之类的,我们只使用Rayon,这是一个库。所以我们现在所要做的,这是一个相当简单的模型,我们只是跨文件并行化,最终我们将不得不变得更加细粒度,但到目前为止这种方法已经奏效了。
所以它有点像在Python中,如果你在多进程,每个文件都有自己的任务或进程任务,不管你想怎么称呼它。我想区别在于,我是说,我很喜欢Python,对吧?我写了很多Python,但我总是觉得多进程真的很棘手。
有很多东西很容易出错,我经常发现性能特征非常令人困惑。有时我使用线程,有时线程的性能优于进程,我不知道为什么,有时我想多进程,现在我有一些不可pickle的对象,我卡在那里试图理解所有这些问题。
我从来没有在Rust中感觉到这种方式,我可以并行化,如果代码编译了,它就工作,而且真的很快。所以能够大规模并行化,而不需要花很多时间思考,这帮助很大。
然后,其他的事情,有点低级,但就是尽量避免在任何可能的地方分配内存,真的强迫自己不分配新的变量。这很难做对,但我们做的分配很少。
我的意思是,最终在性能方面,它真的只是关于…有些是文化方面的,你在一个项目中决定,你真的关心性能,它真的很重要,所以每当我们发布一个大的新东西时,我总是要
—5—
um and just caring about the things that
happen a lot so like
parsingpiproduct.tomo files like
we could probably make that faster but
it doesn’t happen that much like it
happens at the start of the program
right but like
I don’t know checking whether a variable
is defined that’s something that we’re
going to do like a million times and so
you want to make sure that that’s really
fast and that you’re focusing on the
right parts of the code
you talked about some of these
technology allocations I think Samuel
also did in his second wave with
pedantic and rust had some of those same
questions was asking Russ people I
actually asked Vitaly to go and engage
with them a little bit about that
and so it becomes an interesting fact
performance
yeah I mean I think
yeah there was there was a big learning
curve with trying to get some of that
stuff to work right like there were
certain rust features that when I
started learning rust I was like I’m not
actually going to really learn this part
because I don’t think I’ll ever need it
um like lifetimes was the biggest
example and that doesn’t mean anything
to you it’s just a language feature
where like you could kind of write a lot
of rust and like never use it
um but like then
depending on what you do sometimes you
really need it and all of a sudden I
like had to put lifetimes everywhere so
okay let’s let’s uh switch over to some
questions I promise people that even if
we had to extend we get to all the
questions because these are all good
questions uh but treat them as speed
round and go through them pretty fast
okay okay I think you already answered
this one is it possible this is from
Juan is it possible to make rough sort
packages like I sort does yes yes
excellent
um uh I will do speed round but I’ll
just quickly say so by default we
Implement something very similar to
profile equals black which is a setting
that a lot of people use in isort and we
we support a lot of other settings not
all of them I support Sports a lot of
settings but we’ve kind of added them as
they’ve been requested so you can get
something quite close Ollie asks a
question I think it’s the same that I
believe it was Eric was asking about the
rust Python and AST and pattern matching
is there a road map for being able
around oh sorry I just brought this onto
this screen we’re being able to parse
around python modules with pattern
matching
there yeah so there this is like the
like the bane of my existence this issue
um I there is
or is there a road map
let me put it this way is there a ticket
people can go find there is a ticket yes
and there’s there it is
it is definitely the most requested
thing in rough for a good reason
um which is just to explain rough
supports almost all python syntax but
the the thing that it doesn’t support
um which people often run into is the
new structural newish structural pattern
matching feature so in Python you can
write like a match X and then I can’t
remember the exact syntax but copilot’s
helping me complete it
um so uh you can do this like or that’s
not right anyway you can do like this
pattern it’s not important it’s not
important exact syntax for answering the
question but rough doesn’t support that
um there is a ticket
um okay there’s like a couple different
ways that it’s being looked at one is
like a complete rewrite of the rest
python parser that someone is did I can
ever start supporting it
it did and um
I might be wrong about this but at least
initially there were certain forms of
the pattern matching attacks that were
not supported yeah right yeah yeah
um
and plaque uses the slib two to three uh
Port
um which was uh which
doesn’t support pattern matching and
like python moved to a new parser and so
black has had to figure out like how do
we add support for these other features
that are hard to integrate into the
parser and and they do support it yeah
so
um
um someone’s asking about Ruff as a
pre-commit hook
yes so rough does exist as a pre-commit
hook
um it’s in a separate
uh repo I don’t know if my screen’s
still being shared yeah
um it just says rough pre-commit
um we have instructions here
um these instructions are also in the
rough readme uh that actually brings up
an interesting point early on your
interest in a lot of this rust and and
speed was to run on the edge is that
right
uh yeah it was
um I mean I think webassembly is like
really interesting and
you can do a lot of webassembly stuff
with python and like the sports getting
much better for sure
um but rust is kind of like a first
class yeah webassembly citizen
um and so uh I mean one thing that we do
is we just like continuously compile
rough to webassembly and we have this
in-browser demo
um that’s that’s uh based on
uh the uh sorry this is just like rough
being compiled the web assembly and like
used in the browser um which is really
cool and like sometimes people will like
copy links and share them and for issues
and stuff like that
um but uh yeah everybody uh pedantic
also exists as Wheels
because of the rustification
right right
um so this is an interesting pattern
I’m sorry as wasm Wheels
okay yeah yeah I was gonna say I hope it
exists Wheels yeah okay
um newbie I’m gonna give you let you
have a quick treatment of this
uh but it’s an interesting point uh
as a beginner
to python is rough a good fit or would
you encourage people to to wait a bit
so
I think it I think it is but with some
caveats and the main caveat I’d add is
that
autofix like the autofix API comes like
when you opt into that you’re like
accepting some amount of of risk and
like liability because automatically
transforming code is like a hard problem
um and it is definitely possible for
Ruff to break your code by attempting to
autofix it is I hope very unlikely right
and like unlikely or getting unlikely
over time but like
um
我理解您的要求。我会整理这段内容,使其变得合理通顺,同时确保不遗漏任何内容,也不会进行总结。我会原原本本地整理并翻译为中文。以下是整理和翻译后的内容:
关注经常发生的事情很重要。比如解析pipo产品的.tomo文件,我们可能可以让它更快,但它并不经常发生 - 它只在程序开始时发生。但是像检查一个变量是否被定义,这种事情我们会做上百万次,所以你要确保它真的很快,并且你要专注于代码的正确部分。
你谈到了一些这样的技术分配,我想Samuel在他的第二波中也谈到了这一点,Rust也面临同样的问题。我实际上让Vitaly去和他们讨论了一下这个问题。
这成了一个有趣的性能问题。我的意思是,我认为在尝试让一些东西正常工作时,确实有一个很大的学习曲线。比如,当我开始学习Rust时,有些Rust特性我想:”我实际上不会真正去学习这部分,因为我认为我永远不会需要它。”生命周期是最大的例子 - 如果你不了解这个概息,它只是一个语言特性,你可以写很多Rust代码而从不使用它。但是,根据你做什么,有时你真的需要它,突然间我不得不到处使用生命周期。
好的,让我们转向一些问题。我答应过大家,即使我们不得不延长时间,也会回答所有问题,因为这些都是很好的问题。但是让我们把它们当作快速问答环节,快速回答。
Juan问:”是否可能像isort那样制作Ruff排序包?”
答案是:可以的。
我会快速回答,但我只想简单说一下,默认情况下,我们实现了类似于”profile = black”的东西,这是很多人在isort中使用的设置。我们支持很多其他设置,虽然不是全部 - isort支持很多设置 - 但我们根据需求逐步添加了这些设置,所以你可以得到非常接近的效果。
Ollie问了一个问题,我认为和Eric之前问的关于Rust、Python、AST和模式匹配的问题是一样的:”是否有一个能够解析带有模式匹配的Python模块的路线图?”
这个问题是我的心头之患。有…或者说,有路线图吗?让我这么说吧,有一个人们可以去查看的工单吗?是的,有一个工单。这绝对是Ruff中最受欢迎的请求,原因很充分。
让我解释一下,Ruff支持几乎所有的Python语法,但它不支持的一个东西,也是人们经常遇到的,是新的结构化模式匹配特性。在Python中,你可以写像”match X”这样的代码,然后…我记不清确切的语法了,但Copilot正在帮我完成它。
总之,你可以使用这种模式,具体语法对回答问题并不重要,但Ruff不支持这个。有一个工单…有几种不同的方式正在考虑中,一种是对Rust Python解析器进行完全重写,有人开始支持它了。
我可能记错了,但至少最初,模式匹配语法的某些形式是不被支持的。
Black使用slib 2到3的移植版本,它不支持模式匹配。Python转向了一个新的解析器,所以Black不得不想办法添加对这些难以集成到解析器中的其他特性的支持,他们确实支持它了。
有人问到Ruff作为pre-commit钩子的问题。
是的,Ruff确实存在作为pre-commit钩子。它在一个单独的仓库中。我不知道我的屏幕是否还在共享…它只是说”ruff-pre-commit”。我们在这里有说明,这些说明也在Ruff的README中。
这实际上提出了一个有趣的观点。早期你对Rust和速度的兴趣是为了在边缘运行,对吗?
是的。我的意思是,我认为WebAssembly真的很有趣,你可以用Python做很多WebAssembly的事情,而且支持肯定在变得越来越好。但Rust某种程度上是WebAssembly的一等公民。
所以,我们做的一件事就是不断地将Ruff编译成WebAssembly,我们有这个基于浏览器的演示。这只是Ruff被编译成WebAssembly并在浏览器中使用,这真的很酷。有时人们会复制链接并分享它们,用于问题等。
是的,每个人…Pedantic也存在Wheel版本,因为它被Rust化了。
对,作为WebAssembly的Wheel。
作为Python新手,Ruff是否适合,还是你建议人们等一等?
我认为它是适合的,但有一些注意事项。主要的注意事项是,当你选择使用自动修复API时,你就接受了一定程度的风险和责任,因为自动转换代码是一个困难的问题。Ruff确实有可能在尝试自动修复时破坏你的代码。我希望这种情况非常罕见,而且随着时间的推移越来越不太可能发生,但是…
—6—
you know especially if you’re using like
more intricate python features like
locals or like
you know magic stuff like
um rough could break your code and uh
what we want to do over time is actually
make it so you kind of opt into a level
of of risk like really Safe Auto fixes
versus like more risky autofixes and
we’re going to add support for that but
right now if you enable rules and you
Auto fix like we’ll try to Auto fix
everything and so you know I think in
some in some cases that can be like a
really helpful learning tool like I feel
you feel this a lot in Rust where like
the compiler and the linter often tell
you how to fix problems and Link you to
issues and that’s like really really you
want to comment on that do you agree
with that
absolutely absolutely
and um
you know I think so on the one hand like
that’s really helpful like the show the
thing we did at the beginning where it
tells you how to fix the problem like I
think that’s really helpful but on the
other
you know you might Auto fix and if
you’re new to python maybe you don’t
have like
um a big like test Suite or CI setup or
other things that will catch these
problems for you
um so that’s that would be my main
caveat that’s interesting that not only
the first reaction might be uh not ready
for newbies yet but with the like what
is similar to the work Pablo is doing
with much better exceptions in Python
maybe rough could actually be fantastic
for new programmers I think I think it’s
possible I mean I think like
to be transparent about like
trade-offs that you’re buying into when
you adopt the tool like like rough
doesn’t have to be for everyone like I’d
like everyone to like using it but like
if if people if it doesn’t add value to
people’s projects or they’re happy with
their tool chain then like that’s great
um let’s go on to the next one uh
scython poix files
uh uh not on the road map but it’s
something that has been asked about
several times so maybe it will become on
the roadmap yeah uh neuber asked about
show Ruff with wasm I believe we did
Newber if we didn’t follow up with
another comment
um
is there uh if we were to enable more of
the lenders is there this is from Kim if
we enable more of the lenters is there a
potential for some of the rule
violations to clash this happens in the
front end World es lint and prettier are
used together a lot and there’s three or
four out of the box things where they
conflict
yeah so
um
like I guess in in theory yes but in
practice I think no
um and we actually track in the code
base
incompatible rules
um so like a good example here is like
um there’s a rule for like Doc strings
need to start on the first line on the
first line
and then there’s a rule for like
doctrines and just start on the second
line and if you enable both of those and
they’re both Auto fixable Ruff will just
continuously try to fix back and forth
um up to 100 times and then it gives you
an error and tells you to put you know
file an issue on Gap
um but but we you know we encode that
those rules are not compatible and so if
you try to enable both of them it will
turn one off and it will tell you that
you can’t do that so we have guardrails
around that yeah
um but okay last question
um from Juan he asks rough stocks look
really great what you use for them
oh wow thanks
um they are MK docs with material okay
from kdox
um actually pretty new like we just had
like a really long readme on GitHub for
a long time which we still have and that
readme is just translated into docs so
um I hope people find them useful yeah
okay if any of you have any more
questions go ahead and ask them Charlie
do you have any more demos you want to
do or you want to get it that’s all I
wanted to get through that’s all I
wanted to get through unless there’s
anything else that you want to see
um let’s go ahead and switch back to uh
not slides but switch back to us uh on
the screen at once to do a little before
we get in the closeout uh Charlie do you
want to talk about what you’re doing in
open source at all is it is it what
what’s it been like for you in this
period you had some things happen in
your life that were really positive oh
yeah what’s it been like during this
period
um yeah it’s just been like
really crazy but like very energizing
um I let’s see I became a father so my
son was born in October
and uh
yeah my son so my son was born like
seven weeks early and so it was we were
not like there’s nothing to make you
feel unprepared like having a baby like
really early
um and he spent like eight weeks in the
hospital and that was right at the time
he’s doing great but you know that was
right at the time that like Ruff was
starting to take off
um and so I was like hacking on rough in
the morning and at night and like you
know in the cafeteria the hospital and
like
um and uh it was just like this amazing
experience you know obviously very
challenging in a lot of ways but also
this like amazing experience of like
um you know going through all of those
things at the same time
um and for open source like
you know I’m like really new to this
like I
like I mean I’ve been a programmer I
wouldn’t say like for a long time but
like you know my whole career I’ve been
a programmer but I have not really been
like that involved in open source
um and so especially not as a maintainer
so um you know there’s been like a
little bit of a learning curve
and I think there will continue to be
um like you know I need to learn how to
like say no to things right and like
um but also while remaining like I hope
like really welcoming and like and and
to anyone that comes with issues
um so uh you know I’m still I’m still
trying to learn
um and uh especially now that we have
actual users
you know that comes with different
responsibilities
um
last year talking about textual getting
focused on open source and it’s it’s an
interesting Journey
um before we get into closeout Vitaly
you got any comments you want to make
uh yeah there are a couple of nice
comments here in chat like like I like
this one just braids was planning a
three hours webinar but after seeing how
fast traffic is they released two hours
right best comment in webinar history
that’s great
yeah so it was really impressive and
another Eric wrote here if all
developers in the world are doing what
Charlie is doing and being Frugal I can
still use my iPhone 6s
uh I wanted I wanted to ask you Charlie
um so would you recommend to anyone
learning yet another programming
language so what what do you think about
that learning another and another and
another programming language a lonely
career I mean
to make one programming language and
it’s just fine
so
I I mean everyone’s welcome to have like
an opinion on this
um obviously I think
um
like for me I’ve tried not to couple
like too much of my skill set and like
identity to like any one ecosystem or
programming language and
um you know I think like at Khan Academy
we talked a lot about this idea of like
t-shaped Engineers where it’s like you
should be deep in something but it’s
good to have a wide skill set
um and the party idea there is like
expertise itself is like valuable so if
you’re like really really good at like
python or really really good at rest
that actually will have benefits when
you go and learn another language or
like you know just being a uh trying to
stay at like very much a beginner level
and lots of tools is not as doesn’t tend
to create
um the same level of productivity
um and so
it’s not a really good answer because
I’ve kind of set my career like trying
to find my tea but I do like to like
think of skill sets that way
um like I think it’s good to
you know try to go deep on something and
um you know spend time like working on
problems and but it can also be really
helpful you know that skill set itself
helps you learn new languages and that’s
your new ecosystems so I think it’s
really worth
there is an old joke that uh a real
Fortran developer can write a program in
Fortran in any programming language so
what what about this can can you can you
see uh pythonic traces in your rust
programs maybe or you’re just completely
switch
no no I mean
one of my fears and also hopes is like
someone who knows Ross much better than
me or people who know Russ much better
than me will come and look at the rough
source and like tell me a bunch of
things I’m doing that are not idiomatic
right and or not and like that has
already happened a lot and like I kid
because like yeah it’s a fear but like
it’s also like an amazing part of Open
Source right it’s like people come and
they’re like hmm it’s actually not it’s
kind of weird to have a reference to an
option you should put the author
reference inside the option I’m like oh
I never thought of it that way so anyway
um yeah I’m sure I do things there’s
things that’s pythonic and things that
aren’t idiomatic rust and I probably do
some of both
um and hopefully I’ll get get better
over time
you know your point about t-shaped
programmers we have a lot of really
strong advocates in that t-shaped thing
at jetbrains that t-shaped thing
describes vitally probably the best out
of all of us I think of myself more as a
Jenga Tower that’s like got most of the
pieces removed already
yeah I will use this as an excuse for a
paid promotion if any of you know anyone
who’s really good with the community and
wants a great advocacy job unfortunately
it would be working for me we have a
python advocacy position open so get in
contact with me let’s go ahead and head
back to the slides and get Charlie out
of here
uh Charlie thanks so much for talking to
us about faster tooling and python I
mean rough is an implementation of this
idea but you care as much about the idea
I think as you do about rough
specifically what’s the one takeaway
point that you’d like folks to walk out
with
um I think it’s uh I’ll use this as a
little bit of a plug for rough even
though I could have said something
slightly more oftract I think that like
learning rough like really part of the
value here is like you learn this one
API and then you get access to all these
different improvements and like ways to
to enforce uh lint rules and fix your
code and my hope is that by like sort of
buying into that what I hope will become
like a whole ecosystem is that you’re
learning this one thing and then you’re
getting access to like all these great
tools
um and hopefully uh hopefully the speed
is something that appeals to you a lot
but I I think there are also other great
reasons to use rough and I hope some of
those came across yeah well said all
right let’s go ahead and wrap up if
you’d like more information on pycharm
python rough rust whatever please go to
our website at jetbrains.com pycharm I
should probably point you over to Vitaly
we’ve got other parts of the website
that cover our rest activities Lots
going on there uh check out our pycharm
blog for news and announcements uh for
releases and events news flash we’re
making a lot of releases things are
going to start picking up in the next
few weeks in addition to educational
resources such as this webinar which
probably is going to have four trillion
hits once the algorithm picks it up uh
we love your feedback after the webinar
we read it we look at it we talk about
it so please feel free to contact us on
Twitter or in the after webinar survey
if you did register you’ll get that send
it in tell us what you think tell us
what you want us to talk about next
we’ll send that email around in a little
bit
that is all for us today thank you very
much for joining us and hope you have a
nice rest of the day
好的,我会继续整理和翻译剩余的内容:
特别是如果你使用了一些更复杂的Python特性,比如locals或一些魔法般的东西,Ruff可能会破坏你的代码。我们想随着时间的推移,让你能够选择风险级别,比如非常安全的自动修复与更有风险的自动修复。我们将添加对此的支持,但现在如果你启用规则并进行自动修复,我们会尝试自动修复所有内容。
所以我认为在某些情况下,这可能是一个非常有帮助的学习工具。你在Rust中经常感受到这一点,编译器和linter经常告诉你如何修复问题,并链接到相关问题,这真的非常… 你想对此发表评论吗?你同意吗?
绝对同意。
我认为一方面这真的很有帮助,就像我们开始时展示的那样,它告诉你如何修复问题,我认为这真的很有帮助。但另一方面,你可能会进行自动修复,如果你是Python新手,可能你没有大型的测试套件或CI设置或其他能为你捕获这些问题的东西。
所以这将是我主要的警告。这很有趣,不仅第一反应可能是”还不适合新手”,但就像Pablo正在做的为Python提供更好的异常信息的工作一样,也许Ruff实际上可能对新程序员来说是fantastic的。
我认为这是可能的。我的意思是,要透明地说明当你采用这个工具时你买入的权衡。Ruff不必适合每个人,我希望每个人都喜欢使用它,但如果它不能为人们的项目增加价值,或者他们对他们的工具链很满意,那也很好。
让我们继续下一个问题。关于Cython .pyx文件,目前不在路线图上,但已经被问到过几次,所以也许将来会进入路线图。
Neuber问到在WebAssembly中展示Ruff,我相信我们已经做过了。Neuber,如果我们没有做到,请再次评论。
Kim问道,如果我们启用更多的linters,是否有可能出现一些规则违规相互冲突的情况?这在前端世界经常发生,ESLint和Prettier一起使用时,有三四个开箱即用的东西会发生冲突。
嗯,理论上是的,但实践中我认为不会。我们实际上在代码库中跟踪不兼容的规则。一个很好的例子是,有一个规则要求文档字符串需要从第一行开始,然后有另一个规则要求文档字符串从第二行开始。如果你同时启用这两个规则,而它们都是可自动修复的,Ruff会不断地尝试来回修复,最多100次,然后它会给你一个错误,告诉你在Github上提交一个问题。
但我们知道这些规则是不兼容的,所以如果你试图同时启用它们,它会关闭其中一个,并告诉你不能这样做。所以我们对此有防护措施。
好的,最后一个问题。Juan问:”Ruff的文档看起来很棒,你用什么制作的?”
哇,谢谢。它们是用MkDocs和Material主题制作的。实际上这是相当新的,我们在GitHub上只有一个很长的README很长时间,我们现在仍然有,那个README只是被翻译成了文档。我希望人们觉得它们有用。
好的,如果你们还有任何问题,请继续问。Charlie,你还有任何想要展示的demo吗,或者你想结束了?
这就是我想要介绍的全部内容,除非还有什么你想看的。
好的,让我们切回到我们的画面,在结束之前做一点总结。Charlie,你想谈谈你在开源方面的工作吗?在这段时间里,对你来说是什么样的体验?你生活中发生了一些非常积极的事情。
是的,这段时间真的很疯狂,但也非常令人振奋。让我想想,我成为了一个父亲,我的儿子在10月出生。
是的,我的儿子早产了7周,所以我们完全没有准备好。没有什么比婴儿提前出生更能让你感到措手不及的了。
他在医院待了8周,现在他很好,但你知道,那正是Ruff开始起飞的时候。
所以我在早上和晚上都在研究Ruff,你知道,在医院的自助餐厅里…
这是一次神奇的经历,你知道,在很多方面都很具挑战性,但同时也是一次神奇的经历,你知道,同时经历所有这些事情。
对于开源来说,你知道,我真的是个新手。我的意思是,我一直是个程序员,我不会说很长时间,但是你知道,我整个职业生涯都是程序员,但我并没有真正深入参与开源。
特别是不是作为一个维护者,所以你知道,有一点学习曲线。
我想这将继续下去。
比如你知道,我需要学会如何拒绝某些事情,但同时我希望仍然保持非常欢迎和…对任何带着问题来的人。
所以,你知道,我仍在学习。
特别是现在我们有了真正的用户,你知道,这带来了不同的责任。
去年我们谈到Textual专注于开源,这是一个有趣的旅程。
在我们结束之前,Vitaly,你有什么想说的吗?
是的,聊天中有一些很好的评论。比如这个:”原本计划做3小时的网络研讨会,但看到Ruff有多快后,他们减少了2小时。”网络研讨会历史上最好的评论。
是的,真的很令人印象深刻。另外Eric在这里写道:”如果世界上所有的开发者都像Charlie那样做并且节俭,我仍然可以使用我的iPhone 6s。”
我想问你Charlie,你会建议任何人学习另一种编程语言吗?你怎么看待学习另一种又一种编程语言?一个孤独的职业生涯我的意思是…
所以,我的意思是每个人都可以对此有自己的看法。
显然,我认为对我来说,我试图不把我的技能集和身份与任何一个生态系统或编程语言过于耦合。
你知道,我认为在Khan Academy我们经常谈论T型工程师的概念,就是你应该在某方面很深入,但同时拥有广泛的技能集也很好。
这里的部分想法是,专业知识本身是有价值的,所以如果你真的非常擅长Python或者非常擅长Rust,这实际上会在你学习另一种语言时带来好处。
或者你知道,试图在很多工具上保持初学者水平,往往不会创造同样水平的生产力。
所以这不是一个很好的答案,因为我已经把我的职业生涯设定为尝试找到我的T型,但我确实喜欢这样思考技能集。
我认为努力深入某个领域是好的,你知道,花时间解决问题,但学习新的语言和新的生态系统也可能非常有帮助。所以我认为这真的值得…
有一个老笑话说,一个真正的Fortran开发者可以用任何编程语言写Fortran程序。那么,你能在你的Rust程序中看到Python的痕迹吗?还是你完全转换了?
不,不,我的意思是…
我的一个担心和希望是,比我更了解Rust的人或者比我更了解Rust的人会来看Ruff的源代码,然后告诉我一堆我做的不地道的事情,对吧?这已经发生过很多次了,我开玩笑说这是一种担心,但这也是开源的一个amazing的部分,对吧?就像人们来了,他们说:”嗯,实际上有一个对Option的引用是有点奇怪的,你应该把引用放在Option里面。”我就想:”哦,我从来没有这样想过。”
所以,总之,我肯定做了一些pythonic的事情,也做了一些不地道的Rust的事情,我可能两种都有做。
希望随着时间的推移我会变得更好。
你知道,关于T型程序员的观点,在JetBrains我们有很多强烈支持T型的人。T型这个东西可能最能描述Vitaly。我认为我自己更像是一个已经被移除了大部分积木的Jenga塔。
好的,我将以此为借口做一个付费宣传。如果你们中有人认识擅长社区工作并想要一份很棒的倡导工作的人,不幸的是将会为我工作,我们有一个Python倡导职位空缺。所以请与我联系。
让我们回到幻灯片,让Charlie离开这里。
Charlie,非常感谢你与我们讨论更快的Python工具。我的意思是,Ruff是这个想法的一个实现,但我认为你关心这个想法本身,就像你关心Ruff一样。你希望人们带走的一个要点是什么?
我想我会用这个作为一个小小的Ruff宣传,尽管我本可以说一些更抽象的东西。我认为学习Ruff,真正的价值在这里是你学习这一个API,然后你就可以访问所有这些不同的改进和执行lint规则和修复代码的方法。我希望通过投入到我希望将成为一个完整生态系统的东西中,你正在学习这一件事,然后你就可以访问所有这些很棒的工具。
我希望速度是对你非常有吸引力的东西,但我认为还有其他使用Ruff的好理由,我希望其中一些已经表达出来了。
说得好。好的,让我们开始总结。如果你想了解更多关于PyCharm、Python、Ruff、Rust等的信息,请访问我们的网站jetbrains.com/pycharm。我应该指引你去看Vitaly,我们网站的其他部分涵盖了我们的Rust活动,那里有很多事情正在进行。
查看我们的PyCharm博客,了解发布和活动的新闻和公告。新闻快讯:我们正在进行大量的发布,在接下来的几周里,事情会开始加速。
除了这个网络研讨会这样的教育资源,一旦算法选中它,可能会有四万亿的点击量。我们非常喜欢你们在网络研讨会后的反馈,我们会阅读它,查看它,讨论它,所以请随时在Twitter上联系我们,或在网络研讨会后的调查中联系我们。如果你确实注册了,你会收到这个调查,发送给我们,告诉我们你的想法,告诉我们你想让我们下次讨论什么。我们稍后会发送那封电子邮件。
今天就到这里,非常感谢你们的参与,希望你们度过愉快的一天。
原文链接: https://dashen.tech/2017/03/04/Rust静态分析/
版权声明: 转载请注明出处.