@@ -17750,3 +17750,125 @@ fn lock_transitive_git() -> Result<()> {
1775017750
1775117751 Ok(())
1775217752}
17753+
17754+ /// Lock a package that's excluded from the parent workspace, but depends on that parent.
17755+ #[test]
17756+ fn lock_dynamic_version() -> Result<()> {
17757+ let context = TestContext::new("3.12");
17758+
17759+ let pyproject_toml = context.temp_dir.child("pyproject.toml");
17760+ pyproject_toml.write_str(
17761+ r#"
17762+ [project]
17763+ name = "project"
17764+ requires-python = ">=3.12"
17765+ dynamic = ["version"]
17766+
17767+ [build-system]
17768+ requires = ["setuptools"]
17769+ build-backend = "setuptools.build_meta"
17770+
17771+ [tool.uv]
17772+ cache-keys = [{ file = "pyproject.toml" }, { file = "src/project/__init__.py" }]
17773+
17774+ [tool.setuptools.dynamic]
17775+ version = { attr = "project.__version__" }
17776+
17777+ [tool.setuptools]
17778+ package-dir = { "" = "src" }
17779+
17780+ [tool.setuptools.packages.find]
17781+ where = ["src"]
17782+ "#,
17783+ )?;
17784+
17785+ context
17786+ .temp_dir
17787+ .child("src")
17788+ .child("project")
17789+ .child("__init__.py")
17790+ .write_str("__version__ = '0.1.0'")?;
17791+
17792+ uv_snapshot!(context.filters(), context.lock(), @r###"
17793+ success: true
17794+ exit_code: 0
17795+ ----- stdout -----
17796+
17797+ ----- stderr -----
17798+ Resolved 1 package in [TIME]
17799+ "###);
17800+
17801+ let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock")).unwrap();
17802+
17803+ insta::with_settings!({
17804+ filters => context.filters(),
17805+ }, {
17806+ assert_snapshot!(
17807+ lock, @r###"
17808+ version = 1
17809+ requires-python = ">=3.12"
17810+
17811+ [options]
17812+ exclude-newer = "2024-03-25T00:00:00Z"
17813+
17814+ [[package]]
17815+ name = "project"
17816+ version = "0.1.0"
17817+ source = { editable = "." }
17818+ "###
17819+ );
17820+ });
17821+
17822+ // Bump the version.
17823+ context
17824+ .temp_dir
17825+ .child("src")
17826+ .child("project")
17827+ .child("__init__.py")
17828+ .write_str("__version__ = '0.1.1'")?;
17829+
17830+ // Re-run with `--locked`.
17831+ uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###"
17832+ success: false
17833+ exit_code: 2
17834+ ----- stdout -----
17835+
17836+ ----- stderr -----
17837+ Resolved 1 package in [TIME]
17838+ error: The lockfile at `uv.lock` needs to be updated, but `--locked` was provided. To update the lockfile, run `uv lock`.
17839+ "###);
17840+
17841+ // Re-lock.
17842+ uv_snapshot!(context.filters(), context.lock(), @r###"
17843+ success: true
17844+ exit_code: 0
17845+ ----- stdout -----
17846+
17847+ ----- stderr -----
17848+ Resolved 1 package in [TIME]
17849+ Updated project v0.1.0 -> v0.1.1
17850+ "###);
17851+
17852+ let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock")).unwrap();
17853+
17854+ insta::with_settings!({
17855+ filters => context.filters(),
17856+ }, {
17857+ assert_snapshot!(
17858+ lock, @r###"
17859+ version = 1
17860+ requires-python = ">=3.12"
17861+
17862+ [options]
17863+ exclude-newer = "2024-03-25T00:00:00Z"
17864+
17865+ [[package]]
17866+ name = "project"
17867+ version = "0.1.1"
17868+ source = { editable = "." }
17869+ "###
17870+ );
17871+ });
17872+
17873+ Ok(())
17874+ }
0 commit comments