22
33import pytest
44
5+ from pip ._internal .exceptions import InvalidEggFragment , PipError
56from pip ._internal .models .link import Link , links_equivalent
67from pip ._internal .utils .hashes import Hashes
78
@@ -80,20 +81,6 @@ def test_fragments(self) -> None:
8081 assert "eggname" == Link (url ).egg_fragment
8182 assert "subdir" == Link (url ).subdirectory_fragment
8283
83- # Extras are supported and preserved in the egg fragment,
84- # even the empty extras specifier.
85- # This behavior is deprecated and will change in pip 25.
86- url = "git+https://example.com/package#egg=eggname[extra]"
87- assert "eggname[extra]" == Link (url ).egg_fragment
88- assert None is Link (url ).subdirectory_fragment
89- url = "git+https://example.com/package#egg=eggname[extra1,extra2]"
90- assert "eggname[extra1,extra2]" == Link (url ).egg_fragment
91- assert None is Link (url ).subdirectory_fragment
92- url = "git+https://example.com/package#egg=eggname[]"
93- assert "eggname[]" == Link (url ).egg_fragment
94- assert None is Link (url ).subdirectory_fragment
95-
96- @pytest .mark .xfail (reason = "Behavior change scheduled for 25.0" , strict = True )
9784 @pytest .mark .parametrize (
9885 "fragment" ,
9986 [
@@ -102,15 +89,32 @@ def test_fragments(self) -> None:
10289 # Version specifiers are not valid in egg fragments.
10390 "eggname==1.2.3" ,
10491 "eggname>=1.2.3" ,
105- # The extras specifier must be in PEP 508 form .
92+ # Extras are also prohibited .
10693 "eggname[!]" ,
94+ "eggname[extra]" ,
95+ "eggname[extra1,extra2]" ,
96+ "eggmame[]" ,
97+ "eggname[extra]==1000" ,
10798 ],
10899 )
109100 def test_invalid_egg_fragments (self , fragment : str ) -> None :
110101 url = f"git+https://example.com/package#egg={ fragment } "
111- with pytest .raises (ValueError ):
102+ with pytest .raises (PipError ):
112103 Link (url )
113104
105+ def test_invalid_egg_fragment_with_extras_and_version_hint (self ) -> None :
106+ """Test that fragments with extras and version specifiers get proper hint."""
107+
108+ url = "git+https://example.com/package#egg=eggname[extra]==1.0"
109+ with pytest .raises (InvalidEggFragment ) as exc_info :
110+ Link (url )
111+
112+ # The hint should suggest Direct URL syntax, not just "remove version
113+ # specifiers" because the extras require Direct URL syntax anyway.
114+ hint = str (exc_info .value .hint_stmt )
115+ assert r"name\[extra] @ URL" in hint
116+ assert "Version specifiers are silently ignored" in hint
117+
114118 @pytest .mark .parametrize (
115119 "yanked_reason, expected" ,
116120 [
0 commit comments