@@ -6347,6 +6347,110 @@ fn lock_no_workspace_source() -> Result<()> {
6347
6347
Ok(())
6348
6348
}
6349
6349
6350
+ /// Lock a workspace with a member that's a peer to the root.
6351
+ #[test]
6352
+ fn lock_peer_member() -> Result<()> {
6353
+ let context = TestContext::new("3.12");
6354
+
6355
+ context
6356
+ .temp_dir
6357
+ .child("project")
6358
+ .child("pyproject.toml")
6359
+ .write_str(
6360
+ r#"
6361
+ [project]
6362
+ name = "project"
6363
+ version = "0.1.0"
6364
+ requires-python = ">=3.12"
6365
+ dependencies = ["child"]
6366
+
6367
+ [tool.uv.workspace]
6368
+ members = ["../child"]
6369
+
6370
+ [tool.uv.sources]
6371
+ child = { workspace = true }
6372
+ "#,
6373
+ )?;
6374
+
6375
+ context
6376
+ .temp_dir
6377
+ .child("child")
6378
+ .child("pyproject.toml")
6379
+ .write_str(
6380
+ r#"
6381
+ [project]
6382
+ name = "child"
6383
+ version = "0.1.0"
6384
+ requires-python = ">=3.12"
6385
+ dependencies = []
6386
+
6387
+ [build-system]
6388
+ requires = ["setuptools>=42"]
6389
+ build-backend = "setuptools.build_meta"
6390
+ "#,
6391
+ )?;
6392
+
6393
+ uv_snapshot!(context.filters(), context.lock().current_dir(context.temp_dir.child("project")), @r###"
6394
+ success: true
6395
+ exit_code: 0
6396
+ ----- stdout -----
6397
+
6398
+ ----- stderr -----
6399
+ Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
6400
+ Resolved 2 packages in [TIME]
6401
+ "###);
6402
+
6403
+ let lock = fs_err::read_to_string(context.temp_dir.child("project").child("uv.lock")).unwrap();
6404
+
6405
+ insta::with_settings!({
6406
+ filters => context.filters(),
6407
+ }, {
6408
+ assert_snapshot!(
6409
+ lock, @r###"
6410
+ version = 1
6411
+ requires-python = ">=3.12"
6412
+
6413
+ [options]
6414
+ exclude-newer = "2024-03-25T00:00:00Z"
6415
+
6416
+ [manifest]
6417
+ members = [
6418
+ "child",
6419
+ "project",
6420
+ ]
6421
+
6422
+ [[package]]
6423
+ name = "child"
6424
+ version = "0.1.0"
6425
+ source = { editable = "../child" }
6426
+
6427
+ [[package]]
6428
+ name = "project"
6429
+ version = "0.1.0"
6430
+ source = { virtual = "." }
6431
+ dependencies = [
6432
+ { name = "child" },
6433
+ ]
6434
+
6435
+ [package.metadata]
6436
+ requires-dist = [{ name = "child", editable = "../child" }]
6437
+ "###
6438
+ );
6439
+ });
6440
+
6441
+ // Re-run with `--locked`.
6442
+ uv_snapshot!(context.filters(), context.lock().arg("--locked"), @r###"
6443
+ success: false
6444
+ exit_code: 2
6445
+ ----- stdout -----
6446
+
6447
+ ----- stderr -----
6448
+ error: No `pyproject.toml` found in current directory or any parent directory
6449
+ "###);
6450
+
6451
+ Ok(())
6452
+ }
6453
+
6350
6454
/// Ensure that development dependencies are omitted for non-workspace members. Below, `bar` depends
6351
6455
/// on `foo`, but `bar/uv.lock` should omit `anyio`, but should include `typing-extensions`.
6352
6456
#[test]
@@ -18886,6 +18990,107 @@ fn mismatched_name_self_editable() -> Result<()> {
18886
18990
Ok(())
18887
18991
}
18888
18992
18993
+ #[test]
18994
+ fn lock_relative_project() -> Result<()> {
18995
+ let context = TestContext::new("3.12");
18996
+
18997
+ context
18998
+ .temp_dir
18999
+ .child("project")
19000
+ .child("pyproject.toml")
19001
+ .write_str(
19002
+ r#"
19003
+ [project]
19004
+ name = "project"
19005
+ version = "0.1.0"
19006
+ requires-python = ">=3.12"
19007
+ dependencies = ["typing-extensions"]
19008
+ "#,
19009
+ )?;
19010
+
19011
+ let peer = context.temp_dir.child("peer");
19012
+ fs_err::create_dir_all(&peer)?;
19013
+
19014
+ uv_snapshot!(context.filters(), context.lock().arg("--project").arg("../project").current_dir(&peer), @r###"
19015
+ success: true
19016
+ exit_code: 0
19017
+ ----- stdout -----
19018
+
19019
+ ----- stderr -----
19020
+ Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
19021
+ Resolved 2 packages in [TIME]
19022
+ "###);
19023
+
19024
+ let lock = context.read(context.temp_dir.child("project").child("uv.lock"));
19025
+
19026
+ insta::with_settings!({
19027
+ filters => context.filters(),
19028
+ }, {
19029
+ assert_snapshot!(
19030
+ lock, @r###"
19031
+ version = 1
19032
+ requires-python = ">=3.12"
19033
+
19034
+ [options]
19035
+ exclude-newer = "2024-03-25T00:00:00Z"
19036
+
19037
+ [[package]]
19038
+ name = "project"
19039
+ version = "0.1.0"
19040
+ source = { virtual = "." }
19041
+ dependencies = [
19042
+ { name = "typing-extensions" },
19043
+ ]
19044
+
19045
+ [package.metadata]
19046
+ requires-dist = [{ name = "typing-extensions" }]
19047
+
19048
+ [[package]]
19049
+ name = "typing-extensions"
19050
+ version = "4.10.0"
19051
+ source = { registry = "https://pypi.org/simple" }
19052
+ sdist = { url = "https://files.pythonhosted.org/packages/16/3a/0d26ce356c7465a19c9ea8814b960f8a36c3b0d07c323176620b7b483e44/typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb", size = 77558 }
19053
+ wheels = [
19054
+ { url = "https://files.pythonhosted.org/packages/f9/de/dc04a3ea60b22624b51c703a84bbe0184abcd1d0b9bc8074b5d6b7ab90bb/typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", size = 33926 },
19055
+ ]
19056
+ "###
19057
+ );
19058
+ });
19059
+
19060
+ // Re-run with `--locked`.
19061
+ uv_snapshot!(context.filters(), context.lock().arg("--locked").arg("--project").arg("../project").current_dir(&peer), @r###"
19062
+ success: true
19063
+ exit_code: 0
19064
+ ----- stdout -----
19065
+
19066
+ ----- stderr -----
19067
+ Using CPython 3.12.[X] interpreter at: [PYTHON-3.12]
19068
+ Resolved 2 packages in [TIME]
19069
+ "###);
19070
+
19071
+ // Create a virtual environment in the project directory.
19072
+ context
19073
+ .command()
19074
+ .arg("venv")
19075
+ .current_dir(context.temp_dir.child("project"))
19076
+ .assert()
19077
+ .success();
19078
+
19079
+ // Install from the lockfile.
19080
+ uv_snapshot!(context.filters(), context.sync().arg("--frozen").arg("--project").arg("../project").current_dir(&peer), @r###"
19081
+ success: true
19082
+ exit_code: 0
19083
+ ----- stdout -----
19084
+
19085
+ ----- stderr -----
19086
+ Prepared 1 package in [TIME]
19087
+ Installed 1 package in [TIME]
19088
+ + typing-extensions==4.10.0
19089
+ "###);
19090
+
19091
+ Ok(())
19092
+ }
19093
+
18889
19094
#[test]
18890
19095
fn lock_recursive_extra() -> Result<()> {
18891
19096
let context = TestContext::new("3.12");
0 commit comments