Repository: pypa/wheel

Issue:
`wheel tags` command displays invalid filenames on stdout
To quote `python -m wheel tags --help`:

> The output filename(s) will be displayed on stdout for further processing.

This should make usage in shell scripts like `FIXED_WHEEL_PATH=$(python -m wheel tags ...)` (with single input file) possible.

However, instead, the stdout is spammed with "added: 'module/some/file.py'" lines, which are not valid filenames. Such logging should be sent to stderr instead.

<details>
<summary>Example output of `python -m wheel tags`</summary>

```terminal
$ python -m wheel tags --python-tag py3 --abi-tag none --platform-tag manylinux2014_x86_64.manylinux_2_17_x86_64 dist/impuls-0.6.0-cp312-cp312-linux_x86_64.whl 2>/dev/null
adding 'impuls-0.6.0.dist-info/METADATA'
adding 'impuls-0.6.0.dist-info/WHEEL'
adding 'impuls/extern/libextern.so'
adding 'impuls/extern/__init__.py'
adding 'impuls/model/meta/__init__.py'
adding 'impuls/model/meta/entity.py'
adding 'impuls/model/meta/sql_builder.py'
adding 'impuls/model/meta/utility_types.py'
adding 'impuls/model/__init__.py'
adding 'impuls/model/agency.py'
adding 'impuls/model/attribution.py'
adding 'impuls/model/calendar_exception.py'
adding 'impuls/model/calendar.py'
adding 'impuls/model/fare_attribute.py'
adding 'impuls/model/fare_rule.py'
adding 'impuls/model/feed_info.py'
adding 'impuls/model/frequency.py'
adding 'impuls/model/route.py'
adding 'impuls/model/shape_point.py'
adding 'impuls/model/stop.py'
adding 'impuls/model/stop_time.py'
adding 'impuls/model/transfer.py'
adding 'impuls/model/translation.py'
adding 'impuls/model/trip.py'
adding 'impuls/tasks/__init__.py'
adding 'impuls/tasks/add_entity.py'
adding 'impuls/tasks/exec_sql.py'
adding 'impuls/tasks/generate_trip_headsign.py'
adding 'impuls/tasks/load_busman.py'
adding 'impuls/tasks/load_gtfs.py'
adding 'impuls/tasks/merge.py'
adding 'impuls/tasks/modify_from_csv.py'
adding 'impuls/tasks/remove_unused_entities.py'
adding 'impuls/tasks/save_db.py'
adding 'impuls/tasks/save_gtfs.py'
adding 'impuls/tasks/truncate_calendars.py'
adding 'impuls/tools/__init__.py'
adding 'impuls/tools/color.py'
adding 'impuls/tools/geo.py'
adding 'impuls/tools/iteration.py'
adding 'impuls/tools/logs.py'
adding 'impuls/tools/machine_load.py'
adding 'impuls/tools/polish_calendar_exceptions.py'
adding 'impuls/tools/strings.py'
adding 'impuls/tools/temporal.py'
adding 'impuls/tools/testing_mocks.py'
adding 'impuls/tools/types.py'
adding 'impuls/__init__.py'
adding 'impuls/app.py'
adding 'impuls/db.py'
adding 'impuls/errors.py'
adding 'impuls/multi_file.py'
adding 'impuls/options.py'
adding 'impuls/pipeline.py'
adding 'impuls/py.typed'
adding 'impuls/resource.py'
adding 'impuls/task.py'
adding 'impuls-0.6.0.dist-info/RECORD'
impuls-0.6.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
```
</details>

Hints from issue comments:

Solution patch:
diff --git a/docs/news.rst b/docs/news.rst
index cd319be..9acf918 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -4,6 +4,7 @@ Release Notes
 **UNRELEASED**
 
 - Refactored the ``convert`` command to not need setuptools to be installed
+- Don't configure setuptools logging unless running ``bdist_wheel``
 - Added a redirection from ``wheel.bdist_wheel.bdist_wheel`` to
   ``setuptools.command.bdist_wheel.bdist_wheel`` to improve compatibility with
   ``setuptools``' latest fixes.
diff --git a/src/wheel/_bdist_wheel.py b/src/wheel/_bdist_wheel.py
index 3cc7165..88973eb 100644
--- a/src/wheel/_bdist_wheel.py
+++ b/src/wheel/_bdist_wheel.py
@@ -34,6 +34,15 @@ from .wheelfile import WheelFile
 if TYPE_CHECKING:
     import types
 
+# ensure Python logging is configured
+try:
+    __import__("setuptools.logging")
+except ImportError:
+    # setuptools < ??
+    from . import _setuptools_logging
+
+    _setuptools_logging.configure()
+
 
 def safe_name(name: str) -> str:
     """Convert an arbitrary string to a standard distribution name
diff --git a/src/wheel/cli/convert.py b/src/wheel/cli/convert.py
index 3361fd4..ec5ecf3 100644
--- a/src/wheel/cli/convert.py
+++ b/src/wheel/cli/convert.py
@@ -293,7 +293,7 @@ def convert(files: list[str], dest_dir: str, verbose: bool) -> None:
                 source = WininstFileSource(path)
 
             if verbose:
-                print(f"{archive}... ", flush=True)
+                print(f"{archive}...", flush=True, end="")
 
             dest_path = Path(dest_dir) / (
                 f"{source.name}-{source.version}-{source.pyver}-{source.abi}"
diff --git a/src/wheel/util.py b/src/wheel/util.py
index d98d98c..c928aa4 100644
--- a/src/wheel/util.py
+++ b/src/wheel/util.py
@@ -5,15 +5,6 @@ import logging
 
 log = logging.getLogger("wheel")
 
-# ensure Python logging is configured
-try:
-    __import__("setuptools.logging")
-except ImportError:
-    # setuptools < ??
-    from . import _setuptools_logging
-
-    _setuptools_logging.configure()
-
 
 def urlsafe_b64encode(data: bytes) -> bytes:
     """urlsafe_b64encode without padding"""


Test patch:
diff --git a/tests/cli/test_convert.py b/tests/cli/test_convert.py
index e8da2ad..a1bfd5d 100644
--- a/tests/cli/test_convert.py
+++ b/tests/cli/test_convert.py
@@ -7,11 +7,11 @@ from textwrap import dedent
 
 import pytest
 from _pytest.fixtures import SubRequest
-from pytest import TempPathFactory
+from pytest import CaptureFixture, TempPathFactory
 
 import wheel
 from wheel.cli.convert import convert, egg_filename_re
-from wheel.wheelfile import WHEEL_INFO_RE, WheelFile
+from wheel.wheelfile import WheelFile
 
 PKG_INFO = """\
 Metadata-Version: 2.1
@@ -187,16 +187,21 @@ def test_egg_re() -> None:
 
 
 def test_convert_egg_file(
-    egg_path: str, tmp_path: Path, arch: str, expected_wheelfile: bytes
+    egg_path: str,
+    tmp_path: Path,
+    arch: str,
+    expected_wheelfile: bytes,
+    capsys: CaptureFixture,
 ) -> None:
-    convert([egg_path], str(tmp_path), verbose=False)
+    convert([egg_path], str(tmp_path), verbose=True)
     wheel_path = next(path for path in tmp_path.iterdir() if path.suffix == ".whl")
-    assert WHEEL_INFO_RE.match(wheel_path.name)
     with WheelFile(wheel_path) as wf:
         assert wf.read("sampledist-1.0.0.dist-info/METADATA") == EXPECTED_METADATA
         assert wf.read("sampledist-1.0.0.dist-info/WHEEL") == expected_wheelfile
         assert wf.read("sampledist-1.0.0.dist-info/entry_points.txt") == b""
 
+    assert capsys.readouterr().out == f"{egg_path}...OK\n"
+
 
 def test_convert_egg_directory(
     egg_path: str,
@@ -204,30 +209,32 @@ def test_convert_egg_directory(
     tmp_path_factory: TempPathFactory,
     arch: str,
     expected_wheelfile: bytes,
+    capsys: CaptureFixture,
 ) -> None:
     with zipfile.ZipFile(egg_path) as egg_file:
         egg_dir_path = tmp_path_factory.mktemp("eggdir") / Path(egg_path).name
         egg_dir_path.mkdir()
         egg_file.extractall(egg_dir_path)
 
-    convert([str(egg_dir_path)], str(tmp_path), verbose=False)
+    convert([str(egg_dir_path)], str(tmp_path), verbose=True)
     wheel_path = next(path for path in tmp_path.iterdir() if path.suffix == ".whl")
-    assert WHEEL_INFO_RE.match(wheel_path.name)
     with WheelFile(wheel_path) as wf:
         assert wf.read("sampledist-1.0.0.dist-info/METADATA") == EXPECTED_METADATA
         assert wf.read("sampledist-1.0.0.dist-info/WHEEL") == expected_wheelfile
         assert wf.read("sampledist-1.0.0.dist-info/entry_points.txt") == b""
 
+    assert capsys.readouterr().out == f"{egg_dir_path}...OK\n"
+
 
 def test_convert_bdist_wininst(
     bdist_wininst_path: str,
     tmp_path: Path,
     arch: str,
     expected_wheelfile: bytes,
+    capsys: CaptureFixture,
 ) -> None:
-    convert([bdist_wininst_path], str(tmp_path), verbose=False)
+    convert([bdist_wininst_path], str(tmp_path), verbose=True)
     wheel_path = next(path for path in tmp_path.iterdir() if path.suffix == ".whl")
-    assert WHEEL_INFO_RE.match(wheel_path.name)
     with WheelFile(wheel_path) as wf:
         assert (
             wf.read("sampledist-1.0.0.data/scripts/somecommand")
@@ -236,3 +243,5 @@ def test_convert_bdist_wininst(
         assert wf.read("sampledist-1.0.0.dist-info/METADATA") == EXPECTED_METADATA
         assert wf.read("sampledist-1.0.0.dist-info/WHEEL") == expected_wheelfile
         assert wf.read("sampledist-1.0.0.dist-info/entry_points.txt") == b""
+
+    assert capsys.readouterr().out == f"{bdist_wininst_path}...OK\n"