Repository: pypa/setuptools

Issue:
[FR] Implement PEP 625 - File Name of a Source Distribution
### What's the problem this feature will solve?

Conform to accepted standards, make it possible to reliably determine a project's (canonical form) name and version from the source distribution filename.

### Describe the solution you'd like

See https://peps.python.org/pep-0625/

When creating sdist files, normalise the project name and version parts according to the specification, documented [here](https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-file-name).

### Alternative Solutions

Continue as at present, which will leave sdist consumers with no reliable way of knowing the filename and version of a sdist short of either extracting the metadata from the sdist (if the sdist conforms to [PEP 643](https://www.python.org/dev/peps/pep-0643/)) or actually building the distribution.

### Additional context

Code that wants the project's formal name will still need to read the distribution metadata - that is understood and this specification doesn't affect that.

### Code of Conduct

- [X] I agree to follow the PSF Code of Conduct


Discussion:
From Gentoo's standpoint, this will also help us getting predictable sdist names, as right now some PEP517 backends produce normalized filenames and others do not.

Resolving patch:
diff --git a/setuptools/_core_metadata.py b/setuptools/_core_metadata.py
--- a/setuptools/_core_metadata.py
+++ b/setuptools/_core_metadata.py
@@ -17,6 +17,7 @@
 from . import _normalization, _reqs
 from .extern.packaging.markers import Marker
 from .extern.packaging.requirements import Requirement
+from .extern.packaging.utils import canonicalize_name, canonicalize_version
 from .extern.packaging.version import Version
 from .warnings import SetuptoolsDeprecationWarning
 
@@ -257,3 +258,11 @@ def _write_provides_extra(file, processed_extras, safe, unsafe):
     else:
         processed_extras[safe] = unsafe
         file.write(f"Provides-Extra: {safe}\n")
+
+
+# from pypa/distutils#244; needed only until that logic is always available
+def get_fullname(self):
+    return "{}-{}".format(
+        canonicalize_name(self.get_name()).replace('-', '_'),
+        canonicalize_version(self.get_version()),
+    )
diff --git a/setuptools/monkey.py b/setuptools/monkey.py
--- a/setuptools/monkey.py
+++ b/setuptools/monkey.py
@@ -95,6 +95,7 @@ def _patch_distribution_metadata():
         'write_pkg_file',
         'read_pkg_file',
         'get_metadata_version',
+        'get_fullname',
     ):
         new_val = getattr(_core_metadata, attr)
         setattr(distutils.dist.DistributionMetadata, attr, new_val)


Test patch:
diff --git a/setuptools/tests/test_config_discovery.py b/setuptools/tests/test_config_discovery.py
--- a/setuptools/tests/test_config_discovery.py
+++ b/setuptools/tests/test_config_discovery.py
@@ -255,7 +255,7 @@ def test_py_modules_when_wheel_dir_is_cwd(self, tmp_path):
 
 
 class TestNoConfig:
-    DEFAULT_VERSION = "0.0.0"  # Default version given by setuptools
+    CANONICAL_DEFAULT_VERSION = "0"  # Canonical default version given by setuptools
 
     EXAMPLES = {
         "pkg1": ["src/pkg1.py"],
@@ -277,7 +277,9 @@ def test_build_with_discovered_name(self, tmp_path):
         _populate_project_dir(tmp_path, files, {})
         _run_build(tmp_path, "--sdist")
         # Expected distribution file
-        dist_file = tmp_path / f"dist/ns.nested.pkg-{self.DEFAULT_VERSION}.tar.gz"
+        dist_file = (
+            tmp_path / f"dist/ns_nested_pkg-{self.CANONICAL_DEFAULT_VERSION}.tar.gz"
+        )
         assert dist_file.is_file()