@@ -1071,6 +1071,100 @@ version = "0.1.0"
10711071 ) ;
10721072}
10731073
1074+ /// Regression test for #6121: `core` declared editable both as a direct
1075+ /// pixi pypi-dependency and via the transitive `[tool.uv.sources]` of
1076+ /// `middle` must not produce a "conflicting URLs" error.
1077+ #[ tokio:: test]
1078+ async fn test_transitive_uv_sources_editable_consistency ( ) {
1079+ setup_tracing ( ) ;
1080+
1081+ // Create a fake channel with Python
1082+ let mut package_database = MockRepoData :: default ( ) ;
1083+ package_database. add_package ( Package :: build ( "python" , "3.10.0" ) . finish ( ) ) ;
1084+
1085+ let channel_dir = TempDir :: new ( ) . unwrap ( ) ;
1086+ package_database
1087+ . write_repodata ( channel_dir. path ( ) )
1088+ . await
1089+ . unwrap ( ) ;
1090+
1091+ let channel = Url :: from_file_path ( channel_dir. path ( ) ) . unwrap ( ) ;
1092+ let platform = Platform :: current ( ) ;
1093+
1094+ let pixi = PixiControl :: from_manifest ( & format ! (
1095+ r#"
1096+ [project]
1097+ name = "test-transitive-editable"
1098+ channels = ["{channel}"]
1099+ platforms = ["{platform}"]
1100+ conda-pypi-map = {{}} # disable mapping
1101+
1102+ [dependencies]
1103+ python = "*"
1104+
1105+ [pypi-dependencies]
1106+ core = {{ path = "./core", editable = true }}
1107+ middle = {{ path = "./middle", editable = true }}
1108+ "#
1109+ ) )
1110+ . unwrap ( ) ;
1111+
1112+ let project_path = pixi. workspace_path ( ) ;
1113+
1114+ let core_dir = project_path. join ( "core" ) ;
1115+ fs_err:: create_dir_all ( & core_dir) . unwrap ( ) ;
1116+ fs_err:: write (
1117+ core_dir. join ( "pyproject.toml" ) ,
1118+ r#"
1119+ [build-system]
1120+ requires = ["setuptools"]
1121+ build-backend = "setuptools.build_meta"
1122+
1123+ [project]
1124+ name = "core"
1125+ version = "0.1.0"
1126+ "# ,
1127+ )
1128+ . unwrap ( ) ;
1129+ let core_src = core_dir. join ( "core" ) ;
1130+ fs_err:: create_dir_all ( & core_src) . unwrap ( ) ;
1131+ fs_err:: write ( core_src. join ( "__init__.py" ) , "" ) . unwrap ( ) ;
1132+
1133+ let middle_dir = project_path. join ( "middle" ) ;
1134+ fs_err:: create_dir_all ( & middle_dir) . unwrap ( ) ;
1135+ fs_err:: write (
1136+ middle_dir. join ( "pyproject.toml" ) ,
1137+ r#"
1138+ [build-system]
1139+ requires = ["setuptools"]
1140+ build-backend = "setuptools.build_meta"
1141+
1142+ [project]
1143+ name = "middle"
1144+ version = "0.1.0"
1145+ dependencies = ["core"]
1146+
1147+ [tool.uv.sources]
1148+ core = { path = "../core", editable = true }
1149+ "# ,
1150+ )
1151+ . unwrap ( ) ;
1152+ let middle_src = middle_dir. join ( "middle" ) ;
1153+ fs_err:: create_dir_all ( & middle_src) . unwrap ( ) ;
1154+ fs_err:: write ( middle_src. join ( "__init__.py" ) , "" ) . unwrap ( ) ;
1155+
1156+ let lock_file = pixi. update_lock_file ( ) . await . unwrap ( ) ;
1157+
1158+ assert ! (
1159+ lock_file. contains_pypi_package( "default" , platform, "core" ) ,
1160+ "default environment should contain core"
1161+ ) ;
1162+ assert ! (
1163+ lock_file. contains_pypi_package( "default" , platform, "middle" ) ,
1164+ "default environment should contain middle"
1165+ ) ;
1166+ }
1167+
10741168#[ tokio:: test]
10751169async fn test_missing_mapping_file_error_includes_path ( ) {
10761170 setup_tracing ( ) ;
0 commit comments