Skip to content

Commit 57a19f3

Browse files
committed
Fix the "safe_name" attribute of PackageFile for backwards compatibility
Commit 0bd26af introduced a regression that was causing some namespace packages with dots in them fail to upload to PyPI. The reason is because `packaging.utils.canonicalize_name()` is not equivalent to `pkg_resources.safe_name()` as the former transforms the "." into "-", while the later only does it for non-alphanumeric/. characters. Closes: #743
1 parent 2dab479 commit 57a19f3

3 files changed

Lines changed: 23 additions & 2 deletions

File tree

changelog/745.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a regression that was causing some namespace packages with dots in them fail to upload to PyPI.

tests/test_package.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ def test_package_signed_name_is_correct():
110110
assert package.signed_filename == (filename + ".asc")
111111

112112

113+
def test_package_safe_name_is_correct():
114+
package = package_file.PackageFile(
115+
filename="tests/fixtures/deprecated-pypirc",
116+
comment=None,
117+
metadata=pretend.stub(name="mosaik.SimConfig"),
118+
python_version=None,
119+
filetype=None,
120+
)
121+
122+
assert package.safe_name == "mosaik.SimConfig"
123+
124+
113125
@pytest.mark.parametrize("gpg_signature", [(None), (pretend.stub())])
114126
def test_metadata_dictionary(gpg_signature):
115127
meta = pretend.stub(

twine/package.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
import hashlib
1515
import io
1616
import os
17+
import re
1718
import subprocess
1819
from typing import Dict, NamedTuple, Optional, Sequence, Tuple, Union
1920

2021
import importlib_metadata
21-
import packaging.utils
2222
import pkginfo
2323

2424
from twine import exceptions
@@ -44,6 +44,14 @@
4444
MetadataValue = Union[str, Sequence[str]]
4545

4646

47+
def safe_name(name: str) -> str:
48+
"""Convert an arbitrary string to a standard distribution name.
49+
50+
Any runs of non-alphanumeric/. characters are replaced with a single '-'.
51+
"""
52+
return re.sub("[^A-Za-z0-9.]+", "-", name)
53+
54+
4755
class PackageFile:
4856
def __init__(
4957
self,
@@ -59,7 +67,7 @@ def __init__(
5967
self.metadata = metadata
6068
self.python_version = python_version
6169
self.filetype = filetype
62-
self.safe_name = packaging.utils.canonicalize_name(metadata.name)
70+
self.safe_name = safe_name(metadata.name)
6371
self.signed_filename = self.filename + ".asc"
6472
self.signed_basefilename = self.basefilename + ".asc"
6573
self.gpg_signature: Optional[Tuple[str, bytes]] = None

0 commit comments

Comments
 (0)