Repository: asottile/setup-cfg-fmt

Issue:
fix: add option for defining long_description
Hello!
Thanks for this awesome project and you determination to open source.

I use Asciidoctor for documentation.

Because PyPI does not support rendering this format, I made a CI workflow to convert my README.adoc to a README.md before building the python wheels and uploading to PyPI etc (unrelevant to this ticket, just a info).

The current alphabetical-sort determination made by this hook ranks `.adoc` (with content_type of `text/plain`) as first, 
which results in PyPI showing `The author of this package has not provided a project description` as it does not support Asciidoctor.

I tried to do a workaround by renaming the markdown file to `README-.md` for it to rank first but then python/pypi does not like it:

```
...(README-.md file is not being copied)...

/tmp/build-env-cbglbinp/lib/python3.8/site-packages/setuptools/config/expand.py:142: UserWarning: File '/tmp/build-via-sdist-wi26p40b/test_application-0.3.6/README-.md' cannot be found
  warnings.warn(f"File {path!r} cannot be found")

warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md
```
I then tried to do a workaround by renaming the markdown file to `README`, but then this hook determines it as `text/plain`.
I reverted to commenting this pre-commit hook out for now.


I'd like to add an option for defining the filename for `long_description` like this:

```yaml
  - repo: https://github.com/asottile/setup-cfg-fmt
    rev: v1.20.2
    hooks:
      - id: setup-cfg-fmt
        long_description: README.md
```

I'd love to make my first PR for this!

Comments:

Patch:
diff --git a/README.md b/README.md
index f6c2f8c..cd5ecc3 100644
--- a/README.md
+++ b/README.md
@@ -95,7 +95,7 @@ setuptools allows dashed names but does not document them.
 +long_description = file: README.md
 ```
 
-### adds `long_description` if `README.md` is present
+### adds `long_description` if `README` is present
 
 This will show up on the pypi project page
 
diff --git a/setup_cfg_fmt.py b/setup_cfg_fmt.py
index afd3a45..299d670 100644
--- a/setup_cfg_fmt.py
+++ b/setup_cfg_fmt.py
@@ -103,7 +103,13 @@ def _case_insensitive_glob(s: str) -> str:
 def _first_file(setup_cfg: str, prefix: str) -> str | None:
     prefix = _case_insensitive_glob(prefix)
     path = _adjacent_filename(setup_cfg, prefix)
-    for filename in sorted(glob.iglob(f'{path}*')):
+
+    # prefer non-asciidoc because pypi does not render it
+    # https://github.com/asottile/setup-cfg-fmt/issues/149
+    def sort_key(filename: str) -> tuple[bool, str]:
+        return (filename.endswith(('.adoc', '.asciidoc')), filename)
+
+    for filename in sorted(glob.iglob(f'{path}*'), key=sort_key):
         if os.path.isfile(filename):
             return filename
     else:
@@ -369,7 +375,7 @@ def format_file(
     # normalize names to underscores so sdist / wheel have the same prefix
     cfg['metadata']['name'] = cfg['metadata']['name'].replace('-', '_')
 
-    # if README.md exists, set `long_description` + content type
+    # if README exists, set `long_description` + content type
     readme = _first_file(filename, 'readme')
     if readme is not None:
         long_description = f'file: {os.path.basename(readme)}'


Test patch:
diff --git a/tests/setup_cfg_fmt_test.py b/tests/setup_cfg_fmt_test.py
index b3372a7..4527f1b 100644
--- a/tests/setup_cfg_fmt_test.py
+++ b/tests/setup_cfg_fmt_test.py
@@ -296,6 +296,68 @@ def test_adds_long_description_with_readme(filename, content_type, tmpdir):
     )
 
 
+@pytest.mark.parametrize(
+    ('filename', 'content_type'),
+    (
+        ('README.rst', 'text/x-rst'),
+        ('README.markdown', 'text/markdown'),
+        ('README.md', 'text/markdown'),
+        ('README', 'text/plain'),
+        ('README.txt', 'text/plain'),
+        ('readme.txt', 'text/plain'),
+    ),
+)
+def test_readme_discover_does_not_prefer_adoc(filename, content_type, tmpdir):
+    tmpdir.join(filename).write('my project!')
+    tmpdir.join('README.adoc').write('my project!')
+    tmpdir.join('README.asciidoc').write('my project!')
+
+    setup_cfg = tmpdir.join('setup.cfg')
+    setup_cfg.write(
+        '[metadata]\n'
+        'name = pkg\n'
+        'version = 1.0\n',
+    )
+
+    assert main((str(setup_cfg),))
+
+    assert setup_cfg.read() == (
+        f'[metadata]\n'
+        f'name = pkg\n'
+        f'version = 1.0\n'
+        f'long_description = file: {filename}\n'
+        f'long_description_content_type = {content_type}\n'
+    )
+
+
+@pytest.mark.parametrize(
+    'filename',
+    (
+        'README.adoc',
+        'README.asciidoc',
+    ),
+)
+def test_readme_discover_uses_asciidoc_if_none_other_found(filename, tmpdir):
+    tmpdir.join(filename).write('my project!')
+
+    setup_cfg = tmpdir.join('setup.cfg')
+    setup_cfg.write(
+        '[metadata]\n'
+        'name = pkg\n'
+        'version = 1.0\n',
+    )
+
+    assert main((str(setup_cfg),))
+
+    assert setup_cfg.read() == (
+        f'[metadata]\n'
+        f'name = pkg\n'
+        f'version = 1.0\n'
+        f'long_description = file: {filename}\n'
+        f'long_description_content_type = text/plain\n'
+    )
+
+
 def test_readme_discover_prefers_file_over_directory(tmpdir):
     tmpdir.join('README').mkdir()
     tmpdir.join('README.md').write('my project!')