mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-18 19:21:46 +00:00
Include newly-added optional dependencies in lockfile (#5686)
## Summary When we add a new optional group in `uv add`, we never to update the `pyproject.toml` before locking. Otherwise, we use the stale `pyproject.toml` and omit the optional group. Closes https://github.com/astral-sh/uv/issues/5687.
This commit is contained in:
parent
64c6caa57b
commit
b9b41d4a38
4 changed files with 117 additions and 6 deletions
|
|
@ -24,6 +24,8 @@ pub enum Error {
|
|||
Parse(#[from] Box<TomlError>),
|
||||
#[error("Failed to serialize `pyproject.toml`")]
|
||||
Serialize(#[from] Box<toml::ser::Error>),
|
||||
#[error("Failed to deserialize `pyproject.toml`")]
|
||||
Deserialize(#[from] Box<toml::de::Error>),
|
||||
#[error("Dependencies in `pyproject.toml` are malformed")]
|
||||
MalformedDependencies,
|
||||
#[error("Sources in `pyproject.toml` are malformed")]
|
||||
|
|
@ -35,13 +37,18 @@ pub enum Error {
|
|||
}
|
||||
|
||||
impl PyProjectTomlMut {
|
||||
/// Initialize a `PyProjectTomlMut` from a `PyProjectToml`.
|
||||
/// Initialize a [`PyProjectTomlMut`] from a [`PyProjectToml`].
|
||||
pub fn from_toml(pyproject: &PyProjectToml) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
doc: pyproject.raw.parse().map_err(Box::new)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Initialize a [`PyProjectToml`] from a [`PyProjectTomlMut`].
|
||||
pub fn to_toml(&self) -> Result<PyProjectToml, Error> {
|
||||
Ok(toml::from_str(&self.doc.to_string()).map_err(Box::new)?)
|
||||
}
|
||||
|
||||
/// Adds a project to the workspace.
|
||||
pub fn add_workspace(&mut self, path: impl AsRef<Path>) -> Result<(), Error> {
|
||||
// Get or create `tool.uv.workspace.members`.
|
||||
|
|
|
|||
|
|
@ -197,6 +197,48 @@ impl Workspace {
|
|||
})
|
||||
}
|
||||
|
||||
/// Set the [`ProjectWorkspace`] for a given workspace member.
|
||||
///
|
||||
/// Assumes that the project name is unchanged in the updated [`PyProjectToml`].
|
||||
#[must_use]
|
||||
pub fn with_pyproject_toml(
|
||||
self,
|
||||
package_name: &PackageName,
|
||||
pyproject_toml: PyProjectToml,
|
||||
) -> Option<Self> {
|
||||
let mut packages = self.packages;
|
||||
let member = packages.get_mut(package_name)?;
|
||||
|
||||
if member.root == self.install_path {
|
||||
// If the member is also the workspace root, update _both_ the member entry and the
|
||||
// root `pyproject.toml`.
|
||||
let workspace_pyproject_toml = pyproject_toml.clone();
|
||||
|
||||
// Refresh the workspace sources.
|
||||
let workspace_sources = workspace_pyproject_toml
|
||||
.tool
|
||||
.clone()
|
||||
.and_then(|tool| tool.uv)
|
||||
.and_then(|uv| uv.sources)
|
||||
.unwrap_or_default();
|
||||
|
||||
// Set the `pyproject.toml` for the member.
|
||||
member.pyproject_toml = pyproject_toml;
|
||||
|
||||
Some(Self {
|
||||
pyproject_toml: workspace_pyproject_toml,
|
||||
sources: workspace_sources,
|
||||
packages,
|
||||
..self
|
||||
})
|
||||
} else {
|
||||
// Set the `pyproject.toml` for the member.
|
||||
member.pyproject_toml = pyproject_toml;
|
||||
|
||||
Some(Self { packages, ..self })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the set of requirements that include all packages in the workspace.
|
||||
pub fn members_as_requirements(&self) -> Vec<Requirement> {
|
||||
self.packages
|
||||
|
|
@ -765,6 +807,19 @@ impl ProjectWorkspace {
|
|||
&self.workspace().packages[&self.project_name]
|
||||
}
|
||||
|
||||
/// Set the `pyproject.toml` for the current project.
|
||||
///
|
||||
/// Assumes that the project name is unchanged in the updated [`PyProjectToml`].
|
||||
#[must_use]
|
||||
pub fn with_pyproject_toml(self, pyproject_toml: PyProjectToml) -> Option<Self> {
|
||||
Some(Self {
|
||||
workspace: self
|
||||
.workspace
|
||||
.with_pyproject_toml(&self.project_name, pyproject_toml)?,
|
||||
..self
|
||||
})
|
||||
}
|
||||
|
||||
/// Find the workspace for a project.
|
||||
pub async fn from_project(
|
||||
install_path: &Path,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue