Repository: pypa/setuptools
Pull request #1075 (2017-07-03 15:43:14)

Add new long_description_content_type kwarg
This is a re-opening of #708 which was closed.

Since then, https://github.com/pypa/python-packaging-user-guide/pull/258 has been merged and is now documented here: https://packaging.python.org/specifications/#description-content-type

I've rebased it and amended the commit messages to reflect that https://github.com/pypa/python-packaging-user-guide/pull/258 was accepted.

lynncyrin: ping! markdown readme's would be great to have
jaraco: Looks good. Can you just add a CHANGES.txt entry notifying users of what's changed and how they can use it? Also, are there relevant docs changes that need to address this functionality?

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 51aee7c1f..24a3e4d0a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,10 @@
 v36.4.0
 -------
 
+* #1075: Add new ``Description-Content-Type`` metadata field. `See here for
+  documentation on how to use this field.
+  <https://packaging.python.org/specifications/#description-content-type>`_
+
 * #1068: Sort files and directories when building eggs for
   deterministic order.
 
diff --git a/docs/setuptools.txt b/docs/setuptools.txt
index 45d746d26..531d727c1 100644
--- a/docs/setuptools.txt
+++ b/docs/setuptools.txt
@@ -2394,27 +2394,28 @@ Metadata
     Aliases given below are supported for compatibility reasons,
     but not advised.
 
-=================  =================  =====
-Key                Aliases            Accepted value type
-=================  =================  =====
-name                                  str
-version                               attr:, str
-url                home-page          str
-download_url       download-url       str
-author                                str
-author_email       author-email       str
-maintainer                            str
-maintainer_email   maintainer-email   str
-classifiers        classifier         file:, list-comma
-license                               file:, str
-description        summary            file:, str
-long_description   long-description   file:, str
-keywords                              list-comma
-platforms          platform           list-comma
-provides                              list-comma
-requires                              list-comma
-obsoletes                             list-comma
-=================  =================  =====
+==============================  =================  =====
+Key                             Aliases            Accepted value type
+==============================  =================  =====
+name                                               str
+version                                            attr:, str
+url                             home-page          str
+download_url                    download-url       str
+author                                             str
+author_email                    author-email       str
+maintainer                                         str
+maintainer_email                maintainer-email   str
+classifiers                     classifier         file:, list-comma
+license                                            file:, str
+description                     summary            file:, str
+long_description                long-description   file:, str
+long_description_content_type                      str
+keywords                                           list-comma
+platforms                       platform           list-comma
+provides                                           list-comma
+requires                                           list-comma
+obsoletes                                          list-comma
+==============================  =================  =====
 
 .. note::
 
diff --git a/setup.py b/setup.py
index d7a13445b..a02e41aa2 100755
--- a/setup.py
+++ b/setup.py
@@ -95,6 +95,7 @@ setup_params = dict(
     author="Python Packaging Authority",
     author_email="distutils-sig@python.org",
     long_description=long_description,
+    long_description_content_type='text/x-rst; charset=UTF-8',
     keywords="CPAN PyPI distutils eggs package management",
     url="https://github.com/pypa/setuptools",
     src_root=None,
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 6c00b0b7c..a183d15db 100755
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -599,6 +599,10 @@ def write_pkg_info(cmd, basename, filename):
         metadata = cmd.distribution.metadata
         metadata.version, oldver = cmd.egg_version, metadata.version
         metadata.name, oldname = cmd.egg_name, metadata.name
+        metadata.long_description_content_type = getattr(
+            cmd.distribution,
+            'long_description_content_type'
+        )
         try:
             # write unescaped data to PKG-INFO, so older pkg_resources
             # can still parse it
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 21730f22b..084641a8b 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -58,6 +58,13 @@ def write_pkg_file(self, file):
     if self.download_url:
         file.write('Download-URL: %s\n' % self.download_url)
 
+    long_desc_content_type = getattr(
+        self,
+        'long_description_content_type',
+        None
+    ) or 'UNKNOWN'
+    file.write('Description-Content-Type: %s\n' % long_desc_content_type)
+
     long_desc = rfc822_escape(self.get_long_description())
     file.write('Description: %s\n' % long_desc)
 
@@ -317,6 +324,9 @@ class Distribution(Distribution_parse_config_files, _Distribution):
         self.dist_files = []
         self.src_root = attrs and attrs.pop("src_root", None)
         self.patch_missing_pkg_info(attrs)
+        self.long_description_content_type = _attrs_dict.get(
+            'long_description_content_type'
+        )
         # Make sure we have any eggs needed to interpret 'attrs'
         if attrs is not None:
             self.dependency_links = attrs.pop('dependency_links', [])


Test patch:
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 33d6cc526..e454694d1 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -398,6 +398,31 @@ class TestEggInfo(object):
             self._run_install_command(tmpdir_cwd, env)
         assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []
 
+    def test_long_description_content_type(self, tmpdir_cwd, env):
+        # Test that specifying a `long_description_content_type` keyword arg to
+        # the `setup` function results in writing a `Description-Content-Type`
+        # line to the `PKG-INFO` file in the `<distribution>.egg-info`
+        # directory.
+        # `Description-Content-Type` is described at
+        # https://github.com/pypa/python-packaging-user-guide/pull/258
+
+        self._setup_script_with_requires(
+            """long_description_content_type='text/markdown',""")
+        environ = os.environ.copy().update(
+            HOME=env.paths['home'],
+        )
+        code, data = environment.run_setup_py(
+            cmd=['egg_info'],
+            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),
+            data_stream=1,
+            env=environ,
+        )
+        egg_info_dir = os.path.join('.', 'foo.egg-info')
+        with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file:
+            pkg_info_lines = pkginfo_file.read().split('\n')
+        expected_line = 'Description-Content-Type: text/markdown'
+        assert expected_line in pkg_info_lines
+
     def test_python_requires_egg_info(self, tmpdir_cwd, env):
         self._setup_script_with_requires(
             """python_requires='>=2.7.12',""")