@@ -2779,6 +2779,139 @@ def test_cli_compile_strip_extras(runner, make_package, make_sdist, tmpdir):
27792779 assert "[more]" not in out .stderr
27802780
27812781
2782+ @pytest .mark .parametrize (
2783+ ("package_specs" , "constraints" , "existing_reqs" , "expected_reqs" ),
2784+ (
2785+ (
2786+ [
2787+ {
2788+ "name" : "test_package_1" ,
2789+ "version" : "1.1" ,
2790+ "install_requires" : ["test_package_2 ~= 1.1" ],
2791+ },
2792+ {
2793+ "name" : "test_package_2" ,
2794+ "version" : "1.1" ,
2795+ "extras_require" : {"more" : "test_package_3" },
2796+ },
2797+ ],
2798+ """
2799+ test_package_1 == 1.1
2800+ """ ,
2801+ """
2802+ test_package_1 == 1.0
2803+ test_package_2 == 1.0
2804+ """ ,
2805+ """
2806+ test-package-1==1.1
2807+ test-package-2==1.1
2808+ """ ,
2809+ ),
2810+ (
2811+ [
2812+ {
2813+ "name" : "test_package_1" ,
2814+ "version" : "1.1" ,
2815+ "install_requires" : ["test_package_2[more] ~= 1.1" ],
2816+ },
2817+ {
2818+ "name" : "test_package_2" ,
2819+ "version" : "1.1" ,
2820+ "extras_require" : {"more" : "test_package_3" },
2821+ },
2822+ {
2823+ "name" : "test_package_3" ,
2824+ "version" : "0.1" ,
2825+ },
2826+ ],
2827+ """
2828+ test_package_1 == 1.1
2829+ """ ,
2830+ """
2831+ test_package_1 == 1.0
2832+ test_package_2 == 1.0
2833+ test_package_3 == 0.1
2834+ """ ,
2835+ """
2836+ test-package-1==1.1
2837+ test-package-2==1.1
2838+ test-package-3==0.1
2839+ """ ,
2840+ ),
2841+ (
2842+ [
2843+ {
2844+ "name" : "test_package_1" ,
2845+ "version" : "1.1" ,
2846+ "install_requires" : ["test_package_2[more] ~= 1.1" ],
2847+ },
2848+ {
2849+ "name" : "test_package_2" ,
2850+ "version" : "1.1" ,
2851+ "extras_require" : {"more" : "test_package_3" },
2852+ },
2853+ {
2854+ "name" : "test_package_3" ,
2855+ "version" : "0.1" ,
2856+ },
2857+ ],
2858+ """
2859+ test_package_1 == 1.1
2860+ """ ,
2861+ """
2862+ test_package_1 == 1.0
2863+ test_package_2[more] == 1.0
2864+ test_package_3 == 0.1
2865+ """ ,
2866+ """
2867+ test-package-1==1.1
2868+ test-package-2==1.1
2869+ test-package-3==0.1
2870+ """ ,
2871+ ),
2872+ ),
2873+ ids = ("no-extra" , "extra-stripped-from-existing" , "with-extra-in-existing" ),
2874+ )
2875+ def test_resolver_drops_existing_conflicting_constraint (
2876+ runner ,
2877+ make_package ,
2878+ make_sdist ,
2879+ tmpdir ,
2880+ package_specs ,
2881+ constraints ,
2882+ existing_reqs ,
2883+ expected_reqs ,
2884+ ) -> None :
2885+ """
2886+ Test that the resolver will find a solution even if some of the existing
2887+ (indirect) requirements are incompatible with the new constraints.
2888+
2889+ This must succeed even if the conflicting requirement includes some extra,
2890+ no matter whether the extra is mentioned in the existing requirements
2891+ or not (cf. `issue #1977 <https://github.com/jazzband/pip-tools/issues/1977>`_).
2892+ """
2893+ expected_requirements = {line .strip () for line in expected_reqs .splitlines ()}
2894+ dists_dir = tmpdir / "dists"
2895+
2896+ packages = [make_package (** spec ) for spec in package_specs ]
2897+ for pkg in packages :
2898+ make_sdist (pkg , dists_dir )
2899+
2900+ with open ("requirements.txt" , "w" ) as existing_reqs_out :
2901+ existing_reqs_out .write (dedent (existing_reqs ))
2902+
2903+ with open ("requirements.in" , "w" ) as constraints_out :
2904+ constraints_out .write (dedent (constraints ))
2905+
2906+ out = runner .invoke (cli , ["--strip-extras" , "--find-links" , str (dists_dir )])
2907+
2908+ assert out .exit_code == 0 , out
2909+
2910+ with open ("requirements.txt" ) as req_txt :
2911+ req_txt_content = req_txt .read ()
2912+ assert expected_requirements .issubset (req_txt_content .splitlines ())
2913+
2914+
27822915def test_resolution_failure (runner ):
27832916 """Test resolution impossible for unknown package."""
27842917 with open ("requirements.in" , "w" ) as reqs_out :
0 commit comments