diff --git a/tests/test_check.py b/tests/test_check.py index 58bfbdfb..deda3409 100644 --- a/tests/test_check.py +++ b/tests/test_check.py @@ -58,11 +58,13 @@ def test_check_passing_distribution(monkeypatch): renderer = pretend.stub( render=pretend.call_recorder(lambda *a, **kw: "valid") ) - package = pretend.stub(metadata_dictionary=lambda: {"description": "blah"}) + package = pretend.stub(metadata_dictionary=lambda: { + "description": "blah", 'description_content_type': 'text/markdown', + }) output_stream = check.StringIO() warning_stream = "" - monkeypatch.setattr(check, "_RENDERERS", {"": renderer}) + monkeypatch.setattr(check, "_RENDERERS", {None: renderer}) monkeypatch.setattr(check, "_find_dists", lambda a: ["dist/dist.tar.gz"]) monkeypatch.setattr( check, @@ -81,15 +83,41 @@ def test_check_passing_distribution(monkeypatch): ] +def test_check_no_description(monkeypatch, capsys): + package = pretend.stub(metadata_dictionary=lambda: { + 'description': None, 'description_content_type': None, + }) + + monkeypatch.setattr(check, "_find_dists", lambda a: ["dist/dist.tar.gz"]) + monkeypatch.setattr( + check, + "PackageFile", + pretend.stub(from_filename=lambda *a, **kw: package), + ) + + # used to crash with `AttributeError` + output_stream = check.StringIO() + check.check("dist/*", output_stream=output_stream) + assert output_stream.getvalue() == ( + 'Checking distribution dist/dist.tar.gz: ' + 'warning: `long_description_content_type` missing. ' + 'defaulting to `text/x-rst`.\n' + 'warning: `long_description` missing.\n' + 'Passed\n' + ) + + def test_check_failing_distribution(monkeypatch): renderer = pretend.stub( render=pretend.call_recorder(lambda *a, **kw: None) ) - package = pretend.stub(metadata_dictionary=lambda: {"description": "blah"}) + package = pretend.stub(metadata_dictionary=lambda: { + "description": "blah", "description_content_type": 'text/markdown', + }) output_stream = check.StringIO() warning_stream = "WARNING" - monkeypatch.setattr(check, "_RENDERERS", {"": renderer}) + monkeypatch.setattr(check, "_RENDERERS", {None: renderer}) monkeypatch.setattr(check, "_find_dists", lambda a: ["dist/dist.tar.gz"]) monkeypatch.setattr( check, diff --git a/twine/commands/check.py b/twine/commands/check.py index 20377613..f71b2c90 100644 --- a/twine/commands/check.py +++ b/twine/commands/check.py @@ -33,7 +33,6 @@ _RENDERERS = { None: readme_renderer.rst, # Default if description_content_type is None - "": readme_renderer.rst, # Default if description_content_type is None "text/plain": readme_renderer.txt, "text/x-rst": readme_renderer.rst, "text/markdown": readme_renderer.markdown, @@ -85,28 +84,33 @@ def check(dists, output_stream=sys.stdout): package = PackageFile.from_filename(filename, comment=None) metadata = package.metadata_dictionary() - content_type, parameters = cgi.parse_header( - metadata.get("description_content_type") or "" - ) - - # Get the appropriate renderer - renderer = _RENDERERS.get(content_type, readme_renderer.txt) - - # Actually render the given value - rendered = renderer.render( - metadata.get("description"), stream=stream, **parameters - ) + description = metadata["description"] + description_content_type = metadata["description_content_type"] - if rendered is None: - failure = True - output_stream.write("Failed\n") + if description_content_type is None: output_stream.write( - "The project's long_description has invalid markup which will " - "not be rendered on PyPI. The following syntax errors were " - "detected:\n%s" % stream + 'warning: `long_description_content_type` missing. ' + 'defaulting to `text/x-rst`.\n' ) - else: + description_content_type = 'text/x-rst' + + content_type, params = cgi.parse_header(description_content_type) + renderer = _RENDERERS.get(content_type, _RENDERERS[None]) + + if description in {None, 'UNKNOWN\n\n\n'}: + output_stream.write('warning: `long_description` missing.\n') output_stream.write("Passed\n") + else: + if renderer.render(description, stream=stream, **params) is None: + failure = True + output_stream.write("Failed\n") + output_stream.write( + "The project's long_description has invalid markup which " + "will not be rendered on PyPI. The following syntax " + "errors were detected:\n%s" % stream + ) + else: + output_stream.write("Passed\n") return failure