|
8 | 8 | from hashlib import sha256
|
9 | 9 | from pathlib import Path
|
10 | 10 | from textwrap import dedent
|
11 |
| -from typing import Callable, Dict, List, Tuple |
| 11 | +from typing import Callable, Dict, List, Optional, Tuple |
12 | 12 |
|
13 | 13 | import pytest
|
14 | 14 |
|
@@ -1266,6 +1266,8 @@ class Package:
|
1266 | 1266 | metadata: MetadataKind
|
1267 | 1267 | # This will override any dependencies specified in the actual dist's METADATA.
|
1268 | 1268 | requires_dist: Tuple[str, ...] = ()
|
| 1269 | + # This will override the Name specified in the actual dist's METADATA. |
| 1270 | + metadata_name: Optional[str] = None |
1269 | 1271 |
|
1270 | 1272 | def metadata_filename(self) -> str:
|
1271 | 1273 | """This is specified by PEP 658."""
|
@@ -1296,7 +1298,7 @@ def generate_metadata(self) -> bytes:
|
1296 | 1298 | return dedent(
|
1297 | 1299 | f"""\
|
1298 | 1300 | Metadata-Version: 2.1
|
1299 |
| - Name: {self.name} |
| 1301 | + Name: {self.metadata_name or self.name} |
1300 | 1302 | Version: {self.version}
|
1301 | 1303 | {self.requires_str()}
|
1302 | 1304 | """
|
@@ -1452,6 +1454,14 @@ def run_for_generated_index(
|
1452 | 1454 | ),
|
1453 | 1455 | # This will raise an error when pip attempts to fetch the metadata file.
|
1454 | 1456 | Package("simple2", "2.0", "simple2-2.0.tar.gz", MetadataKind.NoFile),
|
| 1457 | + # This has a METADATA file with a mismatched name. |
| 1458 | + Package( |
| 1459 | + "simple2", |
| 1460 | + "3.0", |
| 1461 | + "simple2-3.0.tar.gz", |
| 1462 | + MetadataKind.Sha256, |
| 1463 | + metadata_name="not-simple2", |
| 1464 | + ), |
1455 | 1465 | ],
|
1456 | 1466 | "colander": [
|
1457 | 1467 | # Ensure we can read the dependencies from a metadata file within a wheel
|
@@ -1491,6 +1501,16 @@ def run_for_generated_index(
|
1491 | 1501 | "priority", "1.0", "priority-1.0-py2.py3-none-any.whl", MetadataKind.NoFile
|
1492 | 1502 | ),
|
1493 | 1503 | ],
|
| 1504 | + "requires-simple-extra": [ |
| 1505 | + # Metadata name is not canonicalized. |
| 1506 | + Package( |
| 1507 | + "requires-simple-extra", |
| 1508 | + "0.1", |
| 1509 | + "requires_simple_extra-0.1-py2.py3-none-any.whl", |
| 1510 | + MetadataKind.Sha256, |
| 1511 | + metadata_name="Requires_Simple.Extra", |
| 1512 | + ), |
| 1513 | + ], |
1494 | 1514 | }
|
1495 | 1515 |
|
1496 | 1516 |
|
@@ -1581,3 +1601,47 @@ def test_metadata_not_found(
|
1581 | 1601 | f"ERROR: 404 Client Error: FileNotFoundError for url:.*{expected_re}"
|
1582 | 1602 | )
|
1583 | 1603 | assert pattern.search(result.stderr), (pattern, result.stderr)
|
| 1604 | + |
| 1605 | + |
| 1606 | +def test_produces_error_for_mismatched_package_name_in_metadata( |
| 1607 | + download_generated_html_index: Callable[..., Tuple[TestPipResult, Path]], |
| 1608 | +) -> None: |
| 1609 | + """Verify that the package name from the metadata matches the requested package.""" |
| 1610 | + result, _ = download_generated_html_index( |
| 1611 | + _simple_packages, |
| 1612 | + ["simple2==3.0"], |
| 1613 | + allow_error=True, |
| 1614 | + ) |
| 1615 | + assert result.returncode != 0 |
| 1616 | + assert ( |
| 1617 | + "simple2-3.0.tar.gz has inconsistent Name: expected 'simple2', but metadata " |
| 1618 | + "has 'not-simple2'" |
| 1619 | + ) in result.stdout |
| 1620 | + |
| 1621 | + |
| 1622 | +@pytest.mark.parametrize( |
| 1623 | + "requirement", |
| 1624 | + ( |
| 1625 | + "requires-simple-extra==0.1", |
| 1626 | + "REQUIRES_SIMPLE-EXTRA==0.1", |
| 1627 | + "REQUIRES....simple-_-EXTRA==0.1", |
| 1628 | + ), |
| 1629 | +) |
| 1630 | +def test_canonicalizes_package_name_before_verifying_metadata( |
| 1631 | + download_generated_html_index: Callable[..., Tuple[TestPipResult, Path]], |
| 1632 | + requirement: str, |
| 1633 | +) -> None: |
| 1634 | + """Verify that the package name from the command line and the package's |
| 1635 | + METADATA are both canonicalized before comparison. |
| 1636 | +
|
| 1637 | + Regression test for https://github.com/pypa/pip/issues/12038 |
| 1638 | + """ |
| 1639 | + result, download_dir = download_generated_html_index( |
| 1640 | + _simple_packages, |
| 1641 | + [requirement], |
| 1642 | + allow_error=True, |
| 1643 | + ) |
| 1644 | + assert result.returncode == 0 |
| 1645 | + assert os.listdir(download_dir) == [ |
| 1646 | + "requires_simple_extra-0.1-py2.py3-none-any.whl", |
| 1647 | + ] |
0 commit comments