prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  setuptools changes underscore to dash for package name
  After I pip install cx_oracle, I use python -m pip show cx_oracle command and it shows the package name is cx-Oracle
  After discussed with cx_Oracle's author, it shows setuptools changed the underscore to dash for the package name.  Is that an issue for setuptools or is there any way to stop this auto-conversion? Thanks.
  
  setup.cfg for cx_Oracle
  [metadata]
  name = cx_Oracle
  
  PKG-INFO for cx_Oracle
  Metadata-Version: 2.1
  Name: cx-Oracle
  
  setup.py used in cx_Oracel
  # setup the extension
  extension = setuptools.Extension(
          name = "cx_Oracle",
          include_dirs = includeDirs,
          extra_compile_args = extraCompileArgs,
          define_macros = [("CXO_BUILD_VERSION", BUILD_VERSION)],
          extra_link_args = extraLinkArgs,
          sources = sources + dpiSources,
          depends = depends,
          libraries = libraries,
          library_dirs = libraryDirs)
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `setuptools/_normalization.py`
  Content:
  ```
  1 """
  2 Helpers for normalization as expected in wheel/sdist/module file names
  3 and core metadata
  4 """
  5 import re
  6 from pathlib import Path
  7 from typing import Union
  8 
  9 from .extern import packaging
  10 
  11 _Path = Union[str, Path]
  12 
  13 # https://packaging.python.org/en/latest/specifications/core-metadata/#name
  14 _VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I)
  15 _UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9.]+", re.I)
  16 _NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.I)
  17 _PEP440_FALLBACK = re.compile(r"^v?(?P<safe>(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
  18 
  19 
  20 def safe_identifier(name: str) -> str:
  21     """Make a string safe to be used as Python identifier.
  22     >>> safe_identifier("12abc")
  23     '_12abc'
  24     >>> safe_identifier("__editable__.myns.pkg-78.9.3_local")
  25     '__editable___myns_pkg_78_9_3_local'
  26     """
  27     safe = re.sub(r'\W|^(?=\d)', '_', name)
  28     assert safe.isidentifier()
  29     return safe
  30 
  31 
  32 def safe_name(component: str) -> str:
  33     """Escape a component used as a project name according to Core Metadata.
  34     >>> safe_name("hello world")
  35     'hello-world'
  36     >>> safe_name("hello?world")
  37     'hello-world'
  38     """
  39     # See pkg_resources.safe_name
  40     return _UNSAFE_NAME_CHARS.sub("-", component)
  41 
  42 
  43 def safe_version(version: str) -> str:
  44     """Convert an arbitrary string into a valid version string.
  45     Can still raise an ``InvalidVersion`` exception.
  46     To avoid exceptions use ``best_effort_version``.
  47     >>> safe_version("1988 12 25")
  48     '1988.12.25'
  49     >>> safe_version("v0.2.1")
  50     '0.2.1'
  51     >>> safe_version("v0.2?beta")
  52     '0.2b0'
  53     >>> safe_version("v0.2 beta")
  54     '0.2b0'
  55     >>> safe_version("ubuntu lts")
  56     Traceback (most recent call last):
  57     ...
  58     setuptools.extern.packaging.version.InvalidVersion: Invalid version: 'ubuntu.lts'
  59     """
  60     v = version.replace(' ', '.')
  61     try:
  62         return str(packaging.version.Version(v))
  63     except packaging.version.InvalidVersion:
  64         attempt = _UNSAFE_NAME_CHARS.sub("-", v)
  65         return str(packaging.version.Version(attempt))
  66 
  67 
  68 def best_effort_version(version: str) -> str:
  69     """Convert an arbitrary string into a version-like string.
  70     Fallback when ``safe_version`` is not safe enough.
  71     >>> best_effort_version("v0.2 beta")
  72     '0.2b0'
  73     >>> best_effort_version("ubuntu lts")
  74     '0.dev0+sanitized.ubuntu.lts'
  75     >>> best_effort_version("0.23ubuntu1")
  76     '0.23.dev0+sanitized.ubuntu1'
  77     >>> best_effort_version("0.23-")
  78     '0.23.dev0+sanitized'
  79     >>> best_effort_version("0.-_")
  80     '0.dev0+sanitized'
  81     >>> best_effort_version("42.+?1")
  82     '42.dev0+sanitized.1'
  83     """
  84     # See pkg_resources._forgiving_version
  85     try:
  86         return safe_version(version)
  87     except packaging.version.InvalidVersion:
  88         v = version.replace(' ', '.')
  89         match = _PEP440_FALLBACK.search(v)
  90         if match:
  91             safe = match["safe"]
  92             rest = v[len(safe) :]
  93         else:
  94             safe = "0"
  95             rest = version
  96         safe_rest = _NON_ALPHANUMERIC.sub(".", rest).strip(".")
  97         local = f"sanitized.{safe_rest}".strip(".")
  98         return safe_version(f"{safe}.dev0+{local}")
  99 
  100 
  101 def safe_extra(extra: str) -> str:
  102     """Normalize extra name according to PEP 685
  103     >>> safe_extra("_FrIeNdLy-._.-bArD")
  104     'friendly-bard'
  105     >>> safe_extra("FrIeNdLy-._.-bArD__._-")
  106     'friendly-bard'
  107     """
  108     return _NON_ALPHANUMERIC.sub("-", extra).strip("-").lower()
  109 
  110 
  111 def filename_component(value: str) -> str:
  112     """Normalize each component of a filename (e.g. distribution/version part of wheel)
  113     Note: ``value`` needs to be already normalized.
  114     >>> filename_component("my-pkg")
  115     'my_pkg'
  116     """
  117     return value.replace("-", "_").strip("_")
  118 
  119 
  120 def safer_name(value: str) -> str:
  121     """Like ``safe_name`` but can be used as filename component for wheel"""
  122     # See bdist_wheel.safer_name
  123     return filename_component(safe_name(value))
  124 
  125 
  126 def safer_best_effort_version(value: str) -> str:
  127     """Like ``best_effort_version`` but can be used as filename component for wheel"""
  128     # See bdist_wheel.safer_verion
  129     # TODO: Replace with only safe_version in the future (no need for best effort)
  130     return filename_component(best_effort_version(value))
  131
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py
  --- a/setuptools/_normalization.py
  +++ b/setuptools/_normalization.py
  @@ -12,7 +12,7 @@
   
   # https://packaging.python.org/en/latest/specifications/core-metadata/#name
   _VALID_NAME = re.compile(r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.I)
  -_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9.]+", re.I)
  +_UNSAFE_NAME_CHARS = re.compile(r"[^A-Z0-9._-]+", re.I)
   _NON_ALPHANUMERIC = re.compile(r"[^A-Z0-9]+", re.I)
   _PEP440_FALLBACK = re.compile(r"^v?(?P<safe>(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
   
  @@ -35,6 +35,8 @@
       'hello-world'
       >>> safe_name("hello?world")
       'hello-world'
  +    >>> safe_name("hello_world")
  +    'hello_world'
       """
       # See pkg_resources.safe_name
       return _UNSAFE_NAME_CHARS.sub("-", component)
  
verification_info: {"golden_diff": "diff --git a/setuptools/_normalization.py b/setuptools/_normalization.py\n--- a/setuptools/_normalization.py\n+++ b/setuptools/_normalization.py\n@@ -12,7 +12,7 @@\n \n # https://packaging.python.org/en/latest/specifications/core-metadata/#name\n _VALID_NAME = re.compile(r\"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$\", re.I)\n-_UNSAFE_NAME_CHARS = re.compile(r\"[^A-Z0-9.]+\", re.I)\n+_UNSAFE_NAME_CHARS = re.compile(r\"[^A-Z0-9._-]+\", re.I)\n _NON_ALPHANUMERIC = re.compile(r\"[^A-Z0-9]+\", re.I)\n _PEP440_FALLBACK = re.compile(r\"^v?(?P<safe>(?:[0-9]+!)?[0-9]+(?:\\.[0-9]+)*)\", re.I)\n \n@@ -35,6 +35,8 @@\n     'hello-world'\n     >>> safe_name(\"hello?world\")\n     'hello-world'\n+    >>> safe_name(\"hello_world\")\n+    'hello_world'\n     \"\"\"\n     # See pkg_resources.safe_name\n     return _UNSAFE_NAME_CHARS.sub(\"-\", component)\n", "issue": "setuptools changes underscore to dash for package name\nAfter I pip install cx_oracle, I use python -m pip show cx_oracle command and it shows the package name is cx-Oracle\r\nAfter discussed with cx_Oracle's author, it shows setuptools changed the underscore to dash for the package name.  Is that an issue for setuptools or is there any way to stop this auto-conversion? Thanks.\r\n\r\nsetup.cfg for cx_Oracle\r\n[metadata]\r\nname = cx_Oracle\r\n\r\nPKG-INFO for cx_Oracle\r\nMetadata-Version: 2.1\r\nName: cx-Oracle\r\n\r\nsetup.py used in cx_Oracel\r\n# setup the extension\r\nextension = setuptools.Extension(\r\n        name = \"cx_Oracle\",\r\n        include_dirs = includeDirs,\r\n        extra_compile_args = extraCompileArgs,\r\n        define_macros = [(\"CXO_BUILD_VERSION\", BUILD_VERSION)],\r\n        extra_link_args = extraLinkArgs,\r\n        sources = sources + dpiSources,\r\n        depends = depends,\r\n        libraries = libraries,\r\n        library_dirs = libraryDirs)\n", "before_files": [{"content": "\"\"\"\nHelpers for normalization as expected in wheel/sdist/module file names\nand core metadata\n\"\"\"\nimport re\nfrom pathlib import Path\nfrom typing import Union\n\nfrom .extern import packaging\n\n_Path = Union[str, Path]\n\n# https://packaging.python.org/en/latest/specifications/core-metadata/#name\n_VALID_NAME = re.compile(r\"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$\", re.I)\n_UNSAFE_NAME_CHARS = re.compile(r\"[^A-Z0-9.]+\", re.I)\n_NON_ALPHANUMERIC = re.compile(r\"[^A-Z0-9]+\", re.I)\n_PEP440_FALLBACK = re.compile(r\"^v?(?P<safe>(?:[0-9]+!)?[0-9]+(?:\\.[0-9]+)*)\", re.I)\n\n\ndef safe_identifier(name: str) -> str:\n    \"\"\"Make a string safe to be used as Python identifier.\n    >>> safe_identifier(\"12abc\")\n    '_12abc'\n    >>> safe_identifier(\"__editable__.myns.pkg-78.9.3_local\")\n    '__editable___myns_pkg_78_9_3_local'\n    \"\"\"\n    safe = re.sub(r'\\W|^(?=\\d)', '_', name)\n    assert safe.isidentifier()\n    return safe\n\n\ndef safe_name(component: str) -> str:\n    \"\"\"Escape a component used as a project name according to Core Metadata.\n    >>> safe_name(\"hello world\")\n    'hello-world'\n    >>> safe_name(\"hello?world\")\n    'hello-world'\n    \"\"\"\n    # See pkg_resources.safe_name\n    return _UNSAFE_NAME_CHARS.sub(\"-\", component)\n\n\ndef safe_version(version: str) -> str:\n    \"\"\"Convert an arbitrary string into a valid version string.\n    Can still raise an ``InvalidVersion`` exception.\n    To avoid exceptions use ``best_effort_version``.\n    >>> safe_version(\"1988 12 25\")\n    '1988.12.25'\n    >>> safe_version(\"v0.2.1\")\n    '0.2.1'\n    >>> safe_version(\"v0.2?beta\")\n    '0.2b0'\n    >>> safe_version(\"v0.2 beta\")\n    '0.2b0'\n    >>> safe_version(\"ubuntu lts\")\n    Traceback (most recent call last):\n    ...\n    setuptools.extern.packaging.version.InvalidVersion: Invalid version: 'ubuntu.lts'\n    \"\"\"\n    v = version.replace(' ', '.')\n    try:\n        return str(packaging.version.Version(v))\n    except packaging.version.InvalidVersion:\n        attempt = _UNSAFE_NAME_CHARS.sub(\"-\", v)\n        return str(packaging.version.Version(attempt))\n\n\ndef best_effort_version(version: str) -> str:\n    \"\"\"Convert an arbitrary string into a version-like string.\n    Fallback when ``safe_version`` is not safe enough.\n    >>> best_effort_version(\"v0.2 beta\")\n    '0.2b0'\n    >>> best_effort_version(\"ubuntu lts\")\n    '0.dev0+sanitized.ubuntu.lts'\n    >>> best_effort_version(\"0.23ubuntu1\")\n    '0.23.dev0+sanitized.ubuntu1'\n    >>> best_effort_version(\"0.23-\")\n    '0.23.dev0+sanitized'\n    >>> best_effort_version(\"0.-_\")\n    '0.dev0+sanitized'\n    >>> best_effort_version(\"42.+?1\")\n    '42.dev0+sanitized.1'\n    \"\"\"\n    # See pkg_resources._forgiving_version\n    try:\n        return safe_version(version)\n    except packaging.version.InvalidVersion:\n        v = version.replace(' ', '.')\n        match = _PEP440_FALLBACK.search(v)\n        if match:\n            safe = match[\"safe\"]\n            rest = v[len(safe) :]\n        else:\n            safe = \"0\"\n            rest = version\n        safe_rest = _NON_ALPHANUMERIC.sub(\".\", rest).strip(\".\")\n        local = f\"sanitized.{safe_rest}\".strip(\".\")\n        return safe_version(f\"{safe}.dev0+{local}\")\n\n\ndef safe_extra(extra: str) -> str:\n    \"\"\"Normalize extra name according to PEP 685\n    >>> safe_extra(\"_FrIeNdLy-._.-bArD\")\n    'friendly-bard'\n    >>> safe_extra(\"FrIeNdLy-._.-bArD__._-\")\n    'friendly-bard'\n    \"\"\"\n    return _NON_ALPHANUMERIC.sub(\"-\", extra).strip(\"-\").lower()\n\n\ndef filename_component(value: str) -> str:\n    \"\"\"Normalize each component of a filename (e.g. distribution/version part of wheel)\n    Note: ``value`` needs to be already normalized.\n    >>> filename_component(\"my-pkg\")\n    'my_pkg'\n    \"\"\"\n    return value.replace(\"-\", \"_\").strip(\"_\")\n\n\ndef safer_name(value: str) -> str:\n    \"\"\"Like ``safe_name`` but can be used as filename component for wheel\"\"\"\n    # See bdist_wheel.safer_name\n    return filename_component(safe_name(value))\n\n\ndef safer_best_effort_version(value: str) -> str:\n    \"\"\"Like ``best_effort_version`` but can be used as filename component for wheel\"\"\"\n    # See bdist_wheel.safer_verion\n    # TODO: Replace with only safe_version in the future (no need for best effort)\n    return filename_component(best_effort_version(value))\n", "path": "setuptools/_normalization.py"}], "after_files": [{"content": "\"\"\"\nHelpers for normalization as expected in wheel/sdist/module file names\nand core metadata\n\"\"\"\nimport re\nfrom pathlib import Path\nfrom typing import Union\n\nfrom .extern import packaging\n\n_Path = Union[str, Path]\n\n# https://packaging.python.org/en/latest/specifications/core-metadata/#name\n_VALID_NAME = re.compile(r\"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$\", re.I)\n_UNSAFE_NAME_CHARS = re.compile(r\"[^A-Z0-9._-]+\", re.I)\n_NON_ALPHANUMERIC = re.compile(r\"[^A-Z0-9]+\", re.I)\n_PEP440_FALLBACK = re.compile(r\"^v?(?P<safe>(?:[0-9]+!)?[0-9]+(?:\\.[0-9]+)*)\", re.I)\n\n\ndef safe_identifier(name: str) -> str:\n    \"\"\"Make a string safe to be used as Python identifier.\n    >>> safe_identifier(\"12abc\")\n    '_12abc'\n    >>> safe_identifier(\"__editable__.myns.pkg-78.9.3_local\")\n    '__editable___myns_pkg_78_9_3_local'\n    \"\"\"\n    safe = re.sub(r'\\W|^(?=\\d)', '_', name)\n    assert safe.isidentifier()\n    return safe\n\n\ndef safe_name(component: str) -> str:\n    \"\"\"Escape a component used as a project name according to Core Metadata.\n    >>> safe_name(\"hello world\")\n    'hello-world'\n    >>> safe_name(\"hello?world\")\n    'hello-world'\n    >>> safe_name(\"hello_world\")\n    'hello_world'\n    \"\"\"\n    # See pkg_resources.safe_name\n    return _UNSAFE_NAME_CHARS.sub(\"-\", component)\n\n\ndef safe_version(version: str) -> str:\n    \"\"\"Convert an arbitrary string into a valid version string.\n    Can still raise an ``InvalidVersion`` exception.\n    To avoid exceptions use ``best_effort_version``.\n    >>> safe_version(\"1988 12 25\")\n    '1988.12.25'\n    >>> safe_version(\"v0.2.1\")\n    '0.2.1'\n    >>> safe_version(\"v0.2?beta\")\n    '0.2b0'\n    >>> safe_version(\"v0.2 beta\")\n    '0.2b0'\n    >>> safe_version(\"ubuntu lts\")\n    Traceback (most recent call last):\n    ...\n    setuptools.extern.packaging.version.InvalidVersion: Invalid version: 'ubuntu.lts'\n    \"\"\"\n    v = version.replace(' ', '.')\n    try:\n        return str(packaging.version.Version(v))\n    except packaging.version.InvalidVersion:\n        attempt = _UNSAFE_NAME_CHARS.sub(\"-\", v)\n        return str(packaging.version.Version(attempt))\n\n\ndef best_effort_version(version: str) -> str:\n    \"\"\"Convert an arbitrary string into a version-like string.\n    Fallback when ``safe_version`` is not safe enough.\n    >>> best_effort_version(\"v0.2 beta\")\n    '0.2b0'\n    >>> best_effort_version(\"ubuntu lts\")\n    '0.dev0+sanitized.ubuntu.lts'\n    >>> best_effort_version(\"0.23ubuntu1\")\n    '0.23.dev0+sanitized.ubuntu1'\n    >>> best_effort_version(\"0.23-\")\n    '0.23.dev0+sanitized'\n    >>> best_effort_version(\"0.-_\")\n    '0.dev0+sanitized'\n    >>> best_effort_version(\"42.+?1\")\n    '42.dev0+sanitized.1'\n    \"\"\"\n    # See pkg_resources._forgiving_version\n    try:\n        return safe_version(version)\n    except packaging.version.InvalidVersion:\n        v = version.replace(' ', '.')\n        match = _PEP440_FALLBACK.search(v)\n        if match:\n            safe = match[\"safe\"]\n            rest = v[len(safe) :]\n        else:\n            safe = \"0\"\n            rest = version\n        safe_rest = _NON_ALPHANUMERIC.sub(\".\", rest).strip(\".\")\n        local = f\"sanitized.{safe_rest}\".strip(\".\")\n        return safe_version(f\"{safe}.dev0+{local}\")\n\n\ndef safe_extra(extra: str) -> str:\n    \"\"\"Normalize extra name according to PEP 685\n    >>> safe_extra(\"_FrIeNdLy-._.-bArD\")\n    'friendly-bard'\n    >>> safe_extra(\"FrIeNdLy-._.-bArD__._-\")\n    'friendly-bard'\n    \"\"\"\n    return _NON_ALPHANUMERIC.sub(\"-\", extra).strip(\"-\").lower()\n\n\ndef filename_component(value: str) -> str:\n    \"\"\"Normalize each component of a filename (e.g. distribution/version part of wheel)\n    Note: ``value`` needs to be already normalized.\n    >>> filename_component(\"my-pkg\")\n    'my_pkg'\n    \"\"\"\n    return value.replace(\"-\", \"_\").strip(\"_\")\n\n\ndef safer_name(value: str) -> str:\n    \"\"\"Like ``safe_name`` but can be used as filename component for wheel\"\"\"\n    # See bdist_wheel.safer_name\n    return filename_component(safe_name(value))\n\n\ndef safer_best_effort_version(value: str) -> str:\n    \"\"\"Like ``best_effort_version`` but can be used as filename component for wheel\"\"\"\n    # See bdist_wheel.safer_verion\n    # TODO: Replace with only safe_version in the future (no need for best effort)\n    return filename_component(best_effort_version(value))\n", "path": "setuptools/_normalization.py"}]}