mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
feature: --types=prod,dev,extra,group
This commit is contained in:
parent
a654845891
commit
eb9ea71069
6 changed files with 216 additions and 47 deletions
|
@ -22,6 +22,7 @@ use uv_redacted::DisplaySafeUrl;
|
|||
use uv_resolver::{AnnotationStyle, ExcludeNewer, ForkStrategy, PrereleaseMode, ResolutionMode};
|
||||
use uv_static::EnvVars;
|
||||
use uv_torch::TorchMode;
|
||||
use uv_workspace::pyproject::DependencyType;
|
||||
use uv_workspace::pyproject_mut::AddBoundsKind;
|
||||
|
||||
pub mod comma;
|
||||
|
@ -618,6 +619,21 @@ pub struct UpgradeProjectArgs {
|
|||
#[arg(long, env = EnvVars::UV_UPGRADE_RECURSIVE)]
|
||||
pub recursive: bool,
|
||||
|
||||
/// Only search specific tables in pyproject.toml (case-insensitive).
|
||||
/// * `prod,dev,optional,groups` (default)
|
||||
/// * `prod,dev,opt,group` or `p,d,o,g` (abbreviated)
|
||||
/// * `prd,dev,extra,group` or `p,d,e,g` (optional / extra)
|
||||
#[arg(
|
||||
long,
|
||||
env = EnvVars::UV_UPGRADE_TYPES,
|
||||
value_delimiter = ',',
|
||||
value_parser = parse_dependency_type,
|
||||
)]
|
||||
pub types: Vec<Maybe<DependencyType>>,
|
||||
|
||||
#[arg(long, short, alias = "build-constraint", env = EnvVars::UV_BUILD_CONSTRAINT, value_delimiter = ' ', value_parser = parse_maybe_file_path)]
|
||||
pub build_constraints: Vec<Maybe<PathBuf>>,
|
||||
|
||||
/// The Python interpreter to use during resolution (overrides pyproject.toml).
|
||||
///
|
||||
/// A Python interpreter is required for building source distributions to determine package
|
||||
|
@ -1085,6 +1101,18 @@ fn parse_insecure_host(input: &str) -> Result<Maybe<TrustedHost>, String> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a string into an [`DependencyType`], mapping the empty string to `None`.
|
||||
fn parse_dependency_type(input: &str) -> Result<Maybe<DependencyType>, String> {
|
||||
if input.is_empty() {
|
||||
Ok(Maybe::None)
|
||||
} else {
|
||||
match DependencyType::from_str(input) {
|
||||
Ok(table) => Ok(Maybe::Some(table)),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a string into a [`PathBuf`]. The string can represent a file, either as a path or a
|
||||
/// `file://` URL.
|
||||
fn parse_file_path(input: &str) -> Result<PathBuf, String> {
|
||||
|
|
|
@ -717,6 +717,17 @@ impl EnvVars {
|
|||
#[attr_hidden]
|
||||
pub const UV_UPGRADE_RECURSIVE: &'static str = "UV_UPGRADE_RECURSIVE";
|
||||
|
||||
/// Which pyproject.toml tables should `uv upgrade` search?
|
||||
///
|
||||
/// Default `prod,dev,optional,groups`.
|
||||
///
|
||||
/// * prod: `project.dependencies`
|
||||
/// * dev: `tool.uv.dev-dependencies`
|
||||
/// * optional: `project.optional-dependencies`
|
||||
/// * groups: `dependency-groups`
|
||||
#[attr_hidden]
|
||||
pub const UV_UPGRADE_TYPES: &'static str = "UV_UPGRADE_TYPES";
|
||||
|
||||
/// Overrides terminal width used for wrapping. This variable is not read by uv directly.
|
||||
///
|
||||
/// This is a quasi-standard variable, described, e.g., in `ncurses(3x)`.
|
||||
|
|
|
@ -1686,6 +1686,40 @@ pub enum DependencyType {
|
|||
Group(GroupName),
|
||||
}
|
||||
|
||||
impl DependencyType {
|
||||
pub fn iter() -> [Self; 4] {
|
||||
[
|
||||
Self::Production,
|
||||
Self::Dev,
|
||||
Self::Optional(ExtraName::from_str("e").ok().unwrap()),
|
||||
Self::Group(GroupName::from_str("g").ok().unwrap()),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for DependencyType {
|
||||
type Err = DependencyTypeError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// case-insensitive, allow abbreviations
|
||||
match s.to_lowercase().as_str() {
|
||||
"prod" | "prd" | "p" => Ok(Self::Production),
|
||||
"dev" | "d" => Ok(Self::Dev),
|
||||
"optional" | "opt" | "o" | "extra" | "e" => {
|
||||
Ok(Self::Optional(ExtraName::from_str("e").ok().unwrap()))
|
||||
}
|
||||
"groups" | "group" | "g" => Ok(Self::Group(GroupName::from_str("g").ok().unwrap())),
|
||||
_ => Err(DependencyTypeError::Unknown(s.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DependencyTypeError {
|
||||
#[error("unknown value for: `{0}` (allowed: `prod,dev,optional,groups`)")]
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(test, derive(Serialize))]
|
||||
pub struct BuildBackendSettingsSchema;
|
||||
|
|
|
@ -8,7 +8,6 @@ use thiserror::Error;
|
|||
use toml_edit::{
|
||||
Array, ArrayOfTables, DocumentMut, Formatted, Item, RawString, Table, TomlError, Value,
|
||||
};
|
||||
|
||||
use uv_cache_key::CanonicalUrl;
|
||||
use uv_distribution_types::Index;
|
||||
use uv_fs::PortablePath;
|
||||
|
@ -1122,31 +1121,54 @@ impl PyProjectTomlMut {
|
|||
>(
|
||||
&mut self,
|
||||
find_latest: &F,
|
||||
tables: &[DependencyType],
|
||||
) -> (
|
||||
usize,
|
||||
Vec<(usize, String, Requirement, Requirement, Version, bool)>,
|
||||
Vec<(
|
||||
usize,
|
||||
String,
|
||||
Requirement,
|
||||
Requirement,
|
||||
Version,
|
||||
bool,
|
||||
DependencyType,
|
||||
)>,
|
||||
) {
|
||||
let mut all_upgrades = Vec::new();
|
||||
let mut found = 0;
|
||||
|
||||
// Check `project.dependencies`
|
||||
if let Some(item) = self
|
||||
.project_mut()
|
||||
.ok()
|
||||
if let Some(item) = tables
|
||||
.contains(&DependencyType::Production)
|
||||
.then(|| {
|
||||
self.project_mut()
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|p| p.get_mut("dependencies"))
|
||||
})
|
||||
.flatten()
|
||||
.and_then(|p| p.get_mut("dependencies"))
|
||||
{
|
||||
found += item.as_array().map_or(0, Array::len);
|
||||
Self::replace_dependencies(find_latest, &mut all_upgrades, item).await;
|
||||
Self::replace_dependencies(
|
||||
find_latest,
|
||||
&mut all_upgrades,
|
||||
item,
|
||||
&DependencyType::Production,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
// Check `project.optional-dependencies`
|
||||
if let Some(groups) = self
|
||||
.project_mut()
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|p| p.get_mut("optional-dependencies"))
|
||||
.and_then(Item::as_table_like_mut)
|
||||
if let Some(groups) = tables
|
||||
.iter()
|
||||
.find(|t| matches!(t, DependencyType::Optional(_)))
|
||||
.and_then(|_| {
|
||||
self.project_mut()
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|p| p.get_mut("optional-dependencies"))
|
||||
.and_then(Item::as_table_like_mut)
|
||||
})
|
||||
{
|
||||
for (extra, item) in groups
|
||||
.iter_mut()
|
||||
|
@ -1154,16 +1176,26 @@ impl PyProjectTomlMut {
|
|||
{
|
||||
if let Some(_extra) = extra {
|
||||
found += item.as_array().map_or(0, Array::len);
|
||||
Self::replace_dependencies(find_latest, &mut all_upgrades, item).await;
|
||||
Self::replace_dependencies(
|
||||
find_latest,
|
||||
&mut all_upgrades,
|
||||
item,
|
||||
&DependencyType::Optional(_extra),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check `dependency-groups`.
|
||||
if let Some(groups) = self
|
||||
.doc
|
||||
.get_mut("dependency-groups")
|
||||
.and_then(Item::as_table_like_mut)
|
||||
if let Some(groups) = tables
|
||||
.iter()
|
||||
.find(|t| matches!(t, DependencyType::Group(_)))
|
||||
.and_then(|_| {
|
||||
self.doc
|
||||
.get_mut("dependency-groups")
|
||||
.and_then(Item::as_table_like_mut)
|
||||
})
|
||||
{
|
||||
for (group, item) in groups
|
||||
.iter_mut()
|
||||
|
@ -1171,22 +1203,33 @@ impl PyProjectTomlMut {
|
|||
{
|
||||
if let Some(_group) = group {
|
||||
found += item.as_array().map_or(0, Array::len);
|
||||
Self::replace_dependencies(find_latest, &mut all_upgrades, item).await;
|
||||
Self::replace_dependencies(
|
||||
find_latest,
|
||||
&mut all_upgrades,
|
||||
item,
|
||||
&DependencyType::Group(_group),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check `tool.uv.dev-dependencies`
|
||||
if let Some(item) = self
|
||||
.doc
|
||||
.get_mut("tool")
|
||||
.and_then(Item::as_table_mut)
|
||||
.and_then(|tool| tool.get_mut("uv"))
|
||||
.and_then(Item::as_table_mut)
|
||||
.and_then(|uv| uv.get_mut("dev-dependencies"))
|
||||
if let Some(item) = tables
|
||||
.contains(&DependencyType::Dev)
|
||||
.then(|| {
|
||||
self.doc
|
||||
.get_mut("tool")
|
||||
.and_then(Item::as_table_mut)
|
||||
.and_then(|tool| tool.get_mut("uv"))
|
||||
.and_then(Item::as_table_mut)
|
||||
.and_then(|uv| uv.get_mut("dev-dependencies"))
|
||||
})
|
||||
.flatten()
|
||||
{
|
||||
found += item.as_array().map_or(0, Array::len);
|
||||
Self::replace_dependencies(find_latest, &mut all_upgrades, item).await;
|
||||
Self::replace_dependencies(find_latest, &mut all_upgrades, item, &DependencyType::Dev)
|
||||
.await;
|
||||
}
|
||||
|
||||
(found, all_upgrades)
|
||||
|
@ -1194,19 +1237,45 @@ impl PyProjectTomlMut {
|
|||
|
||||
async fn replace_dependencies<Fut: Future<Output = Option<Version>>, F: Fn(String) -> Fut>(
|
||||
find_latest: &F,
|
||||
all_upgrades: &mut Vec<(usize, String, Requirement, Requirement, Version, bool)>,
|
||||
all_upgrades: &mut Vec<(
|
||||
usize,
|
||||
String,
|
||||
Requirement,
|
||||
Requirement,
|
||||
Version,
|
||||
bool,
|
||||
DependencyType,
|
||||
)>,
|
||||
item: &mut Item,
|
||||
dependency_type: &DependencyType,
|
||||
) {
|
||||
if let Some(dependencies) = item.as_array_mut().filter(|d| !d.is_empty()) {
|
||||
Self::replace_upgrades(find_latest, all_upgrades, dependencies).await;
|
||||
Self::replace_upgrades(find_latest, all_upgrades, dependencies, dependency_type).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_upgrades<Fut: Future<Output = Option<Version>>, F: Fn(String) -> Fut>(
|
||||
find_latest: F,
|
||||
dependencies: &mut Array,
|
||||
all_upgrades: &[(usize, String, Requirement, Requirement, Version, bool)],
|
||||
) -> Vec<(usize, String, Requirement, Requirement, Version, bool)> {
|
||||
all_upgrades: &[(
|
||||
usize,
|
||||
String,
|
||||
Requirement,
|
||||
Requirement,
|
||||
Version,
|
||||
bool,
|
||||
DependencyType,
|
||||
)],
|
||||
dependency_type: &DependencyType,
|
||||
) -> Vec<(
|
||||
usize,
|
||||
String,
|
||||
Requirement,
|
||||
Requirement,
|
||||
Version,
|
||||
bool,
|
||||
DependencyType,
|
||||
)> {
|
||||
let mut upgrades = Vec::new();
|
||||
for (i, dep) in dependencies.iter().enumerate() {
|
||||
let Some(mut req) = dep.as_str().and_then(try_parse_requirement) else {
|
||||
|
@ -1220,9 +1289,9 @@ impl PyProjectTomlMut {
|
|||
};
|
||||
if let Some(upgrade) = match all_upgrades
|
||||
.iter()
|
||||
.find(|(_, _, _, r, _, _)| r.name == req.name)
|
||||
.find(|(_, _, _, r, _, _, _)| r.name == req.name)
|
||||
{
|
||||
Some((_, _, _, _, v, _)) => Some(v.clone()), // reuse cached upgrade
|
||||
Some((_, _, _, _, v, _, _)) => Some(v.clone()), // reuse cached upgrade
|
||||
_ => find_latest(req.name.to_string())
|
||||
.await
|
||||
.filter(|latest| !version_specifiers.contains(latest)),
|
||||
|
@ -1237,6 +1306,7 @@ impl PyProjectTomlMut {
|
|||
req,
|
||||
upgrade,
|
||||
upgraded,
|
||||
dependency_type.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1246,11 +1316,21 @@ impl PyProjectTomlMut {
|
|||
|
||||
async fn replace_upgrades<Fut: Future<Output = Option<Version>>, F: Fn(String) -> Fut>(
|
||||
find_latest: F,
|
||||
all_upgrades: &mut Vec<(usize, String, Requirement, Requirement, Version, bool)>,
|
||||
all_upgrades: &mut Vec<(
|
||||
usize,
|
||||
String,
|
||||
Requirement,
|
||||
Requirement,
|
||||
Version,
|
||||
bool,
|
||||
DependencyType,
|
||||
)>,
|
||||
dependencies: &mut Array,
|
||||
dependency_type: &DependencyType,
|
||||
) {
|
||||
let upgrades = Self::find_upgrades(find_latest, dependencies, all_upgrades).await;
|
||||
for (i, _dep, _old, new, _upgrade, _upgraded) in &upgrades {
|
||||
let upgrades =
|
||||
Self::find_upgrades(find_latest, dependencies, all_upgrades, dependency_type).await;
|
||||
for (i, _dep, _old, new, _upgrade, _upgraded, _) in &upgrades {
|
||||
let string = new.to_string();
|
||||
dependencies.replace(*i, toml_edit::Value::from(string));
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ use std::io::ErrorKind;
|
|||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::commands::ExitStatus;
|
||||
use crate::commands::pip::latest::LatestClient;
|
||||
use crate::printer::Printer;
|
||||
use anyhow::Result;
|
||||
use owo_colors::OwoColorize;
|
||||
use prettytable::format::FormatBuilder;
|
||||
|
@ -21,17 +24,23 @@ use uv_pep440::{Version, VersionSpecifiers};
|
|||
use uv_pep508::{PackageName, Requirement};
|
||||
use uv_resolver::{PrereleaseMode, RequiresPython};
|
||||
use uv_warnings::warn_user;
|
||||
use uv_workspace::pyproject::DependencyType;
|
||||
use uv_workspace::pyproject_mut::{DependencyTarget, PyProjectTomlMut};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::commands::ExitStatus;
|
||||
use crate::commands::pip::latest::LatestClient;
|
||||
use crate::printer::Printer;
|
||||
|
||||
/// Upgrade all dependencies in the project requirements (pyproject.toml).
|
||||
///
|
||||
/// This doesn't read or modify uv.lock, only constraints like `<1.0` are bumped.
|
||||
pub(crate) async fn upgrade_project_dependencies(args: UpgradeProjectArgs) -> Result<ExitStatus> {
|
||||
let tables: Vec<_> = match args
|
||||
.types
|
||||
.iter()
|
||||
.filter_map(|t| t.clone().into_option())
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
tables if !tables.is_empty() => tables,
|
||||
_ => DependencyType::iter().to_vec(),
|
||||
};
|
||||
let tomls = match args
|
||||
.recursive
|
||||
.then(|| search_pyproject_tomls(Path::new(".")))
|
||||
|
@ -131,7 +140,7 @@ pub(crate) async fn upgrade_project_dependencies(args: UpgradeProjectArgs) -> Re
|
|||
format!("{}/", &toml_dir[2..])
|
||||
};
|
||||
let subpath = format!("{relative}pyproject.toml");
|
||||
let (found, upgrades) = toml.upgrade_all_dependencies(&find_latest).await;
|
||||
let (found, upgrades) = toml.upgrade_all_dependencies(&find_latest, &tables).await;
|
||||
let bumped = upgrades.len();
|
||||
all_found += found;
|
||||
all_bumped += bumped;
|
||||
|
@ -158,7 +167,7 @@ pub(crate) async fn upgrade_project_dependencies(args: UpgradeProjectArgs) -> Re
|
|||
"upgraded {subpath}{}",
|
||||
if args.dry_run { " (dry run)" } else { "" }
|
||||
);
|
||||
table.add_row(row![r->"#", rb->"name", Fr->"-old", bFg->"+new", "latest", dry_run]); // diff-like
|
||||
table.add_row(row![r->"#", rb->"name", Fr->"-old", bFg->"+new", "latest", "type", dry_run]); // diff-like
|
||||
let remove_spaces = |v: &Requirement| {
|
||||
v.clone()
|
||||
.version_or_url
|
||||
|
@ -169,12 +178,18 @@ pub(crate) async fn upgrade_project_dependencies(args: UpgradeProjectArgs) -> Re
|
|||
upgrades
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(i, (_, _dep, old, new, version, upgraded))| {
|
||||
.for_each(|(i, (_, _dep, old, new, version, upgraded, dependency_type))| {
|
||||
let from = remove_spaces(old);
|
||||
let to = remove_spaces(new);
|
||||
let upordown = if *upgraded { "✅ up" } else { "❌ down" };
|
||||
let _type = match dependency_type {
|
||||
DependencyType::Production => "prod".into(),
|
||||
DependencyType::Dev => "dev".into(),
|
||||
DependencyType::Optional(extra) => format!("{extra} [extra]"),
|
||||
DependencyType::Group(group) => format!("{group} [group]"),
|
||||
};
|
||||
table.add_row(
|
||||
row![r->i + 1, rb->old.name, Fr->from, bFg->to, version.to_string(), upordown],
|
||||
row![r->i + 1, rb->old.name, Fr->from, bFg->to, version.to_string(), _type, upordown],
|
||||
);
|
||||
});
|
||||
table.printstd();
|
||||
|
@ -219,7 +234,7 @@ fn search_pyproject_tomls(root: &Path) -> Result<Vec<String>, anyhow::Error> {
|
|||
// Hint: Doesn't skip special folders like `build`, `dist` or `target`
|
||||
let is_hidden_or_not_pyproject = |path: &Path| {
|
||||
path.file_name().and_then(OsStr::to_str).is_some_and(|s| {
|
||||
s.starts_with('.') || s.starts_with('_') || path.is_file() && s != "pyproject.toml"
|
||||
s.starts_with('.') || s.starts_with('_') || s == "target" || path.is_file() && s != "pyproject.toml"
|
||||
})
|
||||
};
|
||||
|
||||
|
|
|
@ -951,7 +951,7 @@ uv upgrade [OPTIONS]
|
|||
<p>Can be provided multiple times.</p>
|
||||
<p>Expects to receive either a hostname (e.g., <code>localhost</code>), a host-port pair (e.g., <code>localhost:8080</code>), or a URL (e.g., <code>https://localhost</code>).</p>
|
||||
<p>WARNING: Hosts included in this list will not be verified against the system's certificate store. Only use <code>--allow-insecure-host</code> in a secure network with verified sources, as it bypasses SSL verification and could expose you to MITM attacks.</p>
|
||||
<p>May also be set with the <code>UV_INSECURE_HOST</code> environment variable.</p></dd><dt id="uv-upgrade--cache-dir"><a href="#uv-upgrade--cache-dir"><code>--cache-dir</code></a> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<p>May also be set with the <code>UV_INSECURE_HOST</code> environment variable.</p></dd><dt id="uv-upgrade--build-constraints"><a href="#uv-upgrade--build-constraints"><code>--build-constraints</code></a>, <code>--build-constraint</code>, <code>-b</code> <i>build-constraints</i></dt><dt id="uv-upgrade--cache-dir"><a href="#uv-upgrade--cache-dir"><code>--cache-dir</code></a> <i>cache-dir</i></dt><dd><p>Path to the cache directory.</p>
|
||||
<p>Defaults to <code>$XDG_CACHE_HOME/uv</code> or <code>$HOME/.cache/uv</code> on macOS and Linux, and <code>%LOCALAPPDATA%\uv\cache</code> on Windows.</p>
|
||||
<p>To view the location of the cache directory, run <code>uv cache dir</code>.</p>
|
||||
<p>May also be set with the <code>UV_CACHE_DIR</code> environment variable.</p></dd><dt id="uv-upgrade--color"><a href="#uv-upgrade--color"><code>--color</code></a> <i>color-choice</i></dt><dd><p>Control the use of color in output.</p>
|
||||
|
@ -997,7 +997,8 @@ metadata when there are not wheels.</p>
|
|||
<p>May also be set with the <code>UV_PYTHON</code> environment variable.</p></dd><dt id="uv-upgrade--quiet"><a href="#uv-upgrade--quiet"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output.</p>
|
||||
<p>Repeating this option, e.g., <code>-qq</code>, will enable a silent mode in which uv will write no output to stdout.</p>
|
||||
</dd><dt id="uv-upgrade--recursive"><a href="#uv-upgrade--recursive"><code>--recursive</code></a></dt><dd><p>Search recursively for pyproject.toml files</p>
|
||||
<p>May also be set with the <code>UV_UPGRADE_RECURSIVE</code> environment variable.</p></dd><dt id="uv-upgrade--verbose"><a href="#uv-upgrade--verbose"><code>--verbose</code></a>, <code>-v</code></dt><dd><p>Use verbose output.</p>
|
||||
<p>May also be set with the <code>UV_UPGRADE_RECURSIVE</code> environment variable.</p></dd><dt id="uv-upgrade--types"><a href="#uv-upgrade--types"><code>--types</code></a> <i>types</i></dt><dd><p>Only search specific tables in pyproject.toml (case-insensitive). * <code>prod,dev,optional,groups</code> (default) * <code>prod,dev,opt,group</code> or <code>p,d,o,g</code> (abbreviated) * <code>prd,dev,extra,group</code> or <code>p,d,e,g</code> (optional / extra)</p>
|
||||
<p>May also be set with the <code>UV_UPGRADE_TYPES</code> environment variable.</p></dd><dt id="uv-upgrade--verbose"><a href="#uv-upgrade--verbose"><code>--verbose</code></a>, <code>-v</code></dt><dd><p>Use verbose output.</p>
|
||||
<p>You can configure fine-grained logging using the <code>RUST_LOG</code> environment variable. (<a href="https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives">https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives</a>)</p>
|
||||
</dd></dl>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue