Repository: zestsoftware/zest.releaser (language: python)

Issue:
Support Markdown file validation under longtest
Hi,
I am always used to the tool `longtest` to validate files that are included in setup.py. I am wondering if it is possible to validate Markdown files in the same way.

Thanks
Support Markdown file validation under longtest
Hi,
I am always used to the tool `longtest` to validate files that are included in setup.py. I am wondering if it is possible to validate Markdown files in the same way.

Thanks


Discussion / hints:
I hardly ever use this command anymore. Instead I use `restview --long-description`, or `restview CHANGES.rst` if I expect problems in that file. See https://pypi.org/project/restview/

Other options:

- https://pypi.org/project/readme-renderer/
- With recent `twine` versions you can do `python setup.py bdist_wheel && twine check dist/*`, although this does not open a browser for a visual check.

I am not sure how well those handle MarkDown. I am still only using restructured text, though that may change.
I hardly ever use this command anymore. Instead I use `restview --long-description`, or `restview CHANGES.rst` if I expect problems in that file. See https://pypi.org/project/restview/

Other options:

- https://pypi.org/project/readme-renderer/
- With recent `twine` versions you can do `python setup.py bdist_wheel && twine check dist/*`, although this does not open a browser for a visual check.

I am not sure how well those handle MarkDown. I am still only using restructured text, though that may change.

Fix patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index e3d8d85b..7d610f23 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -6,7 +6,7 @@ Changelog for zest.releaser
 
 - Ignore error output when calling `build`.
   We only need to look at the exit code to see if it worked.
-  You can call zest.releaser with ``--verbose`` if you want 
+  You can call zest.releaser with ``--verbose`` if you want
   to see the possible warnings.
 
 - Removed ``encoding`` config option as nobody is using it anymore (using the
@@ -14,6 +14,13 @@ Changelog for zest.releaser
   we don't use python 2 anymore. Fixes `issue 391
   <https://github.com/zestsoftware/zest.releaser/issues/391>`_.
 
+- The ``longtest`` is now simpler. It runs readme_renderer and just displays
+  the result in the browser, without error handling. ``twine check`` should be
+  used if you want a real hard check (``longtest --headless`` is
+  deprecated). The advantage is that longtest now also renders markdown
+  correctly.  This adds `readme_renderer[md]` as dependency.
+  Fixes `issue 363 <https://github.com/zestsoftware/zest.releaser/issues/363>`_.
+
 
 9.0.0a1 (2023-07-13)
 --------------------
diff --git a/README.rst b/README.rst
index 317f6269..e511a01e 100644
--- a/README.rst
+++ b/README.rst
@@ -164,9 +164,9 @@ Note: markdown files should use the "underline" style of headings, not the
 
 There are some additional tools:
 
-- **longtest**: small tool that renders a setup.py's long description
-  and opens it in a web browser. This assumes an installed docutils
-  (as it needs ``rst2html.py``).
+- **longtest**: small tool that renders the long description and opens it in a
+  web browser. Handy for debugging formatting issues locally before uploading
+  it to pypi.
 
 - **lasttagdiff**: small tool that shows the *diff* of the current
   branch with the last released tag.  Handy for checking whether all
diff --git a/pyproject.toml b/pyproject.toml
index f4d18605..a7b6babf 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,13 +13,13 @@ authors = [
     {name = "Maurits van Rees", email = "maurits@vanrees.org"},
 ]
 dependencies = [
-    "setuptools",
+    "build >= 0.6.0.post1",  # 0.6.0 wasn't compatible with Python 3.7
     "colorama",
+    "readme_renderer[md] >= 40",
     "requests",
-    "twine >= 1.6.0",
-    "build >= 0.6.0.post1",  # 0.6.0 wasn't compatible with Python 3.7
-    "tomli; python_version<'3.11'",
     "setuptools >= 61.0.0",  # older versions can't read pyproject.toml configurations
+    "tomli; python_version<'3.11'",
+    "twine >= 1.6.0",
 ]
 requires-python = ">=3.8"
 classifiers = [
@@ -47,13 +47,12 @@ recommended = [
     "check-manifest",
     "pep440",
     "pyroma",
-    "readme_renderer",
     "wheel",
 ]
 test = [
+    "wheel",
     "zope.testing",
     "zope.testrunner",
-    "wheel",
 ]
 
 [project.urls]


Test patch:
diff --git a/zest/releaser/longtest.py b/zest/releaser/longtest.py
index f660006b..6facb374 100644
--- a/zest/releaser/longtest.py
+++ b/zest/releaser/longtest.py
@@ -1,24 +1,18 @@
 """Do the checks and tasks that have to happen before doing a release.
 """
 
-import io
+from zest.releaser import choose
+from zest.releaser import utils
+from zest.releaser.utils import _execute_command
+
 import logging
+import os
+import readme_renderer
 import sys
 import tempfile
 import webbrowser
 
 
-try:
-    from readme_renderer.rst import render
-
-    HAVE_README = True
-except ImportError:
-    HAVE_README = False
-
-from zest.releaser import utils
-from zest.releaser.utils import _execute_command
-
-
 HTML_PREFIX = """<html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@@ -29,36 +23,31 @@
 </html>"""
 
 
+readme_renderer  # noqa, indicating it as a dependency
 logger = logging.getLogger(__name__)
 
 
-def show_longdesc(headless):
-    if not HAVE_README:
-        logging.error(
-            "To check the long description, we need the 'readme_renderer' "
-            "package. "
-            "(It is included if you install `zest.releaser[recommended]`)"
-        )
-        return 1
+def show_longdesc():
+    vcs = choose.version_control()
+    name = vcs.name
 
-    filename = tempfile.mktemp(".html")
-    # Note: for the setup.py call we use _execute_command() from our
-    # utils module. This makes sure the python path is set up right.
-    longdesc = _execute_command(utils.setup_py("--long-description"))
-    warnings = io.StringIO()
-    html = render(longdesc, warnings)
-    if html is None:
-        logging.error("Error generating html. Invalid ReST.")
-        rst_filename = tempfile.mktemp(".rst")
-        with open(rst_filename, "wb") as rst_file:
-            rst_file.write(longdesc.encode("utf-8"))
-        warning_text = warnings.getvalue()
-        warning_text = warning_text.replace("<string>", rst_filename)
-        print(warning_text)
-        return 1
+    # Corner case. importlib.metadata wants to be next to the egg-info. Which
+    # doesn't play nice if the egg-info is in a src/ dir, which is a
+    # relatively common occurrence.
+    if os.path.exists(f"src/{name}.egg-info"):
+        logger.info("egg-info dir found in src/ dir, chdir'ing to src first")
+        os.chdir("src")
 
-    if headless:
-        return 0
+    filename = tempfile.mktemp(".html")
+    html = _execute_command(
+        [
+            sys.executable,
+            "-m",
+            "readme_renderer",
+            "--package",
+            name,
+        ]
+    )
 
     if "<html" not in html[:20]:
         # Add a html declaration including utf-8 indicator
@@ -70,7 +59,6 @@ def show_longdesc(headless):
     url = "file://" + filename
     logging.info("Opening %s in your webbrowser.", url)
     webbrowser.open(url)
-    return 0
 
 
 def main():
@@ -80,9 +68,11 @@ def main():
         action="store_true",
         dest="headless",
         default=False,
-        help="Do not open a browser window with the HTML result",
+        help="Deprecated",
     )
     options = utils.parse_options(parser)
     utils.configure_logging()
-    code = show_longdesc(headless=options.headless)
-    sys.exit(code)
+    if options.headless:
+        logger.error("--headless is deprecated, for real checks use 'twine check'.")
+        sys.exit(1)
+    show_longdesc()