Repository: pypa/setuptools
Pull request #1552 (2018-10-28 16:21:42)

Add missing word to sentence in docs
"the Setuptools strongly recommends" -> "the Setuptools project strongly recommends"

- [x] News fragment added in changelog.d. See [documentation](http://setuptools.readthedocs.io/en/latest/developer-guide.html#making-a-pull-request) for details



Patch:
diff --git a/README.rst b/README.rst
index a9bed5211..0454f2edd 100644
--- a/README.rst
+++ b/README.rst
@@ -23,10 +23,6 @@ See the `Installation Instructions
 User's Guide for instructions on installing, upgrading, and uninstalling
 Setuptools.
 
-The project is `maintained at GitHub <https://github.com/pypa/setuptools>`_
-by the `Setuptools Developers
-<https://github.com/orgs/pypa/teams/setuptools-developers>`_.
-
 Questions and comments should be directed to the `distutils-sig
 mailing list <http://mail.python.org/pipermail/distutils-sig/>`_.
 Bug reports and especially tested patches may be
diff --git a/changelog.d/1456.doc.rst b/changelog.d/1456.doc.rst
new file mode 100644
index 000000000..b01d53380
--- /dev/null
+++ b/changelog.d/1456.doc.rst
@@ -0,0 +1,1 @@
+Documented that the ``rpmbuild`` packages is required for the ``bdist_rpm`` command.
diff --git a/changelog.d/1541.deprecation.rst b/changelog.d/1541.deprecation.rst
new file mode 100644
index 000000000..cc07aaa78
--- /dev/null
+++ b/changelog.d/1541.deprecation.rst
@@ -0,0 +1,1 @@
+Officially deprecated the ``requires`` parameter in ``setup()``.
diff --git a/changelog.d/1545.feature.rst b/changelog.d/1545.feature.rst
new file mode 100644
index 000000000..70591d56d
--- /dev/null
+++ b/changelog.d/1545.feature.rst
@@ -0,0 +1,1 @@
+Changed the warning class of all deprecation warnings; deprecation warning classes are no longer derived from ``DeprecationWarning`` and are thus visible by default.
diff --git a/changelog.d/1552.doc.rst b/changelog.d/1552.doc.rst
new file mode 100644
index 000000000..43e0e62d1
--- /dev/null
+++ b/changelog.d/1552.doc.rst
@@ -0,0 +1,1 @@
+Fixed a minor typo in the python 2/3 compatibility documentation.
diff --git a/changelog.d/1553.doc.rst b/changelog.d/1553.doc.rst
new file mode 100644
index 000000000..2f68b95e3
--- /dev/null
+++ b/changelog.d/1553.doc.rst
@@ -0,0 +1,1 @@
+Update installation instructions to point to ``pip install`` instead of ``ez_setup.py``.
\ No newline at end of file
diff --git a/docs/python3.txt b/docs/python3.txt
index c528fc3ce..6b55fe785 100644
--- a/docs/python3.txt
+++ b/docs/python3.txt
@@ -9,7 +9,7 @@ code.
 
 Setuptools provides a facility to invoke 2to3 on the code as a part of the
 build process, by setting the keyword parameter ``use_2to3`` to True, but
-the Setuptools strongly recommends instead developing a unified codebase
+the Setuptools project strongly recommends instead developing a unified codebase
 using `six <https://pypi.org/project/six/>`_,
 `future <https://pypi.org/project/future/>`_, or another compatibility
 library.
diff --git a/docs/setuptools.txt b/docs/setuptools.txt
index 9398f8e9b..2912a43ca 100644
--- a/docs/setuptools.txt
+++ b/docs/setuptools.txt
@@ -73,23 +73,17 @@ Developer's Guide
 Installing ``setuptools``
 =========================
 
-Please follow the `EasyInstall Installation Instructions`_ to install the
-current stable version of setuptools.  In particular, be sure to read the
-section on `Custom Installation Locations`_ if you are installing anywhere
-other than Python's ``site-packages`` directory.
+.. _EasyInstall Installation Instructions: easy_install.html
 
-.. _EasyInstall Installation Instructions: easy_install.html#installation-instructions
+.. _Custom Installation Locations: easy_install.html
 
-.. _Custom Installation Locations: easy_install.html#custom-installation-locations
+.. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/
 
-If you want the current in-development version of setuptools, you should first
-install a stable version, and then run::
+To install the latest version of setuptools, use::
 
-    ez_setup.py setuptools==dev
-
-This will download and install the latest development (i.e. unstable) version
-of setuptools from the Python Subversion sandbox.
+    pip install -U setuptools
 
+Refer to `Installing Packages`_ guide for more information.
 
 Basic Use
 =========
@@ -1339,6 +1333,10 @@ Creating System Packages
     ``bdist_deb`` command is an example of a command that currently requires
     this kind of patching to work with setuptools.
 
+    Please note that building system packages may require you to install
+    some system software, for example ``bdist_rpm`` requires the ``rpmbuild``
+    command installed.
+
     If you or your users have a problem building a usable system package for
     your project, please report the problem via the mailing list so that
     either the "bdist" tool in question or setuptools can be modified to
diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py
index 741347013..d8e4c26b4 100644
--- a/pkg_resources/__init__.py
+++ b/pkg_resources/__init__.py
@@ -238,6 +238,9 @@ __all__ = [
     'register_finder', 'register_namespace_handler', 'register_loader_type',
     'fixup_namespace_packages', 'get_importer',
 
+    # Warnings
+    'PkgResourcesDeprecationWarning',
+
     # Deprecated/backward compatibility only
     'run_main', 'AvailableDistributions',
 ]
@@ -2335,7 +2338,7 @@ class EntryPoint:
             warnings.warn(
                 "Parameters to load are deprecated.  Call .resolve and "
                 ".require separately.",
-                DeprecationWarning,
+                PkgResourcesDeprecationWarning,
                 stacklevel=2,
             )
         if require:
@@ -3158,3 +3161,11 @@ def _initialize_master_working_set():
     # match order
     list(map(working_set.add_entry, sys.path))
     globals().update(locals())
+
+class PkgResourcesDeprecationWarning(Warning):
+    """
+    Base class for warning about deprecations in ``pkg_resources``
+
+    This class is not derived from ``DeprecationWarning``, and as such is
+    visible by default.
+    """
diff --git a/setuptools/__init__.py b/setuptools/__init__.py
index 54309b57f..e438036a8 100644
--- a/setuptools/__init__.py
+++ b/setuptools/__init__.py
@@ -8,6 +8,8 @@ import distutils.filelist
 from distutils.util import convert_path
 from fnmatch import fnmatchcase
 
+from ._deprecation_warning import SetuptoolsDeprecationWarning
+
 from setuptools.extern.six import PY3
 from setuptools.extern.six.moves import filter, map
 
@@ -22,6 +24,7 @@ __metaclass__ = type
 
 __all__ = [
     'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require',
+    'SetuptoolsDeprecationWarning',
     'find_packages'
 ]
 
@@ -188,4 +191,5 @@ def findall(dir=os.curdir):
     return list(files)
 
 
+# Apply monkey patches
 monkey.patch_all()
diff --git a/setuptools/_deprecation_warning.py b/setuptools/_deprecation_warning.py
new file mode 100644
index 000000000..086b64dd3
--- /dev/null
+++ b/setuptools/_deprecation_warning.py
@@ -0,0 +1,7 @@
+class SetuptoolsDeprecationWarning(Warning):
+    """
+    Base class for warning deprecations in ``setuptools``
+
+    This class is not derived from ``DeprecationWarning``, and as such is
+    visible by default.
+    """
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index c670a16e6..06c98271b 100644
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -40,8 +40,11 @@ import subprocess
 import shlex
 import io
 
+
 from sysconfig import get_config_vars, get_path
 
+from setuptools import SetuptoolsDeprecationWarning
+
 from setuptools.extern import six
 from setuptools.extern.six.moves import configparser, map
 
@@ -2077,7 +2080,7 @@ class ScriptWriter:
     @classmethod
     def get_script_args(cls, dist, executable=None, wininst=False):
         # for backward compatibility
-        warnings.warn("Use get_args", DeprecationWarning)
+        warnings.warn("Use get_args", EasyInstallDeprecationWarning)
         writer = (WindowsScriptWriter if wininst else ScriptWriter).best()
         header = cls.get_script_header("", executable, wininst)
         return writer.get_args(dist, header)
@@ -2085,7 +2088,7 @@ class ScriptWriter:
     @classmethod
     def get_script_header(cls, script_text, executable=None, wininst=False):
         # for backward compatibility
-        warnings.warn("Use get_header", DeprecationWarning, stacklevel=2)
+        warnings.warn("Use get_header", EasyInstallDeprecationWarning, stacklevel=2)
         if wininst:
             executable = "python.exe"
         return cls.get_header(script_text, executable)
@@ -2120,7 +2123,7 @@ class ScriptWriter:
     @classmethod
     def get_writer(cls, force_windows):
         # for backward compatibility
-        warnings.warn("Use best", DeprecationWarning)
+        warnings.warn("Use best", EasyInstallDeprecationWarning)
         return WindowsScriptWriter.best() if force_windows else cls.best()
 
     @classmethod
@@ -2152,7 +2155,7 @@ class WindowsScriptWriter(ScriptWriter):
     @classmethod
     def get_writer(cls):
         # for backward compatibility
-        warnings.warn("Use best", DeprecationWarning)
+        warnings.warn("Use best", EasyInstallDeprecationWarning)
         return cls.best()
 
     @classmethod
@@ -2333,3 +2336,7 @@ def _patch_usage():
         yield
     finally:
         distutils.core.gen_usage = saved
+
+class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning):
+    """Class for warning about deprecations in EasyInstall in SetupTools. Not ignored by default, unlike DeprecationWarning."""
+    
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index bd116e1f6..e1022d31f 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -31,7 +31,7 @@ import setuptools.unicode_utils as unicode_utils
 from setuptools.glob import glob
 
 from setuptools.extern import packaging
-
+from setuptools import SetuptoolsDeprecationWarning
 
 def translate_pattern(glob):
     """
@@ -696,7 +696,7 @@ def get_pkg_info_revision():
     Get a -r### off of PKG-INFO Version in case this is an sdist of
     a subversion revision.
     """
-    warnings.warn("get_pkg_info_revision is deprecated.", DeprecationWarning)
+    warnings.warn("get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning)
     if os.path.exists('PKG-INFO'):
         with io.open('PKG-INFO') as f:
             for line in f:
@@ -704,3 +704,7 @@ def get_pkg_info_revision():
                 if match:
                     return int(match.group(1))
     return 0
+
+
+class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning):
+    """Class for warning about deprecations in eggInfo in setupTools. Not ignored by default, unlike DeprecationWarning."""
diff --git a/setuptools/config.py b/setuptools/config.py
index 73a3bf703..d1ac6734d 100644
--- a/setuptools/config.py
+++ b/setuptools/config.py
@@ -2,8 +2,12 @@ from __future__ import absolute_import, unicode_literals
 import io
 import os
 import sys
+
+import warnings
+import functools
 from collections import defaultdict
 from functools import partial
+from functools import wraps
 from importlib import import_module
 
 from distutils.errors import DistutilsOptionError, DistutilsFileError
@@ -61,6 +65,18 @@ def read_configuration(
     return configuration_to_dict(handlers)
 
 
+def _get_option(target_obj, key):
+    """
+    Given a target object and option key, get that option from
+    the target object, either through a get_{key} method or
+    from an attribute directly.
+    """
+    getter_name = 'get_{key}'.format(**locals())
+    by_attribute = functools.partial(getattr, target_obj, key)
+    getter = getattr(target_obj, getter_name, by_attribute)
+    return getter()
+
+
 def configuration_to_dict(handlers):
     """Returns configuration data gathered by given handlers as a dict.
 
@@ -72,20 +88,9 @@ def configuration_to_dict(handlers):
     config_dict = defaultdict(dict)
 
     for handler in handlers:
-
-        obj_alias = handler.section_prefix
-        target_obj = handler.target_obj
-
         for option in handler.set_options:
-            getter = getattr(target_obj, 'get_%s' % option, None)
-
-            if getter is None:
-                value = getattr(target_obj, option)
-
-            else:
-                value = getter()
-
-            config_dict[obj_alias][option] = value
+            value = _get_option(handler.target_obj, option)
+            config_dict[handler.section_prefix][option] = value
 
     return config_dict
 
@@ -110,7 +115,8 @@ def parse_configuration(
     options.parse()
 
     meta = ConfigMetadataHandler(
-        distribution.metadata, command_options, ignore_option_errors, distribution.package_dir)
+        distribution.metadata, command_options, ignore_option_errors,
+        distribution.package_dir)
     meta.parse()
 
     return meta, options
@@ -399,6 +405,20 @@ class ConfigHandler:
 
             section_parser_method(section_options)
 
+    def _deprecated_config_handler(self, func, msg, warning_class):
+        """ this function will wrap around parameters that are deprecated
+        
+        :param msg: deprecation message 
+        :param warning_class: class of warning exception to be raised
+        :param func: function to be wrapped around
+        """
+        @wraps(func)
+        def config_handler(*args, **kwargs):
+            warnings.warn(msg, warning_class)
+            return func(*args, **kwargs)
+        
+        return config_handler
+
 
 class ConfigMetadataHandler(ConfigHandler):
 
@@ -434,7 +454,10 @@ class ConfigMetadataHandler(ConfigHandler):
             'platforms': parse_list,
             'keywords': parse_list,
             'provides': parse_list,
-            'requires': parse_list,
+            'requires': self._deprecated_config_handler(parse_list,
+                "The requires parameter is deprecated, please use " +
+                "install_requires for runtime dependencies.",
+                DeprecationWarning),
             'obsoletes': parse_list,
             'classifiers': self._get_parser_compound(parse_file, parse_list),
             'license': parse_file,
@@ -458,9 +481,12 @@ class ConfigMetadataHandler(ConfigHandler):
             # Be strict about versions loaded from file because it's easy to
             # accidentally include newlines and other unintended content
             if isinstance(parse(version), LegacyVersion):
-                raise DistutilsOptionError('Version loaded from %s does not comply with PEP 440: %s' % (
-                    value, version
-                ))
+                tmpl = (
+                    'Version loaded from {value} does not '
+                    'comply with PEP 440: {version}'
+                )
+                raise DistutilsOptionError(tmpl.format(**locals()))
+
             return version
 
         version = self._parse_attr(value, self.package_dir)
@@ -518,12 +544,13 @@ class ConfigOptionsHandler(ConfigHandler):
         find_directives = ['find:', 'find_namespace:']
         trimmed_value = value.strip()
 
-        if not trimmed_value in find_directives:
+        if trimmed_value not in find_directives:
             return self._parse_list(value)
 
         findns = trimmed_value == find_directives[1]
         if findns and not PY3:
-            raise DistutilsOptionError('find_namespace: directive is unsupported on Python < 3.3')
+            raise DistutilsOptionError(
+                'find_namespace: directive is unsupported on Python < 3.3')
 
         # Read function arguments from a dedicated section.
         find_kwargs = self.parse_section_packages__find(
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 6ee4a97f3..f6078dbe0 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -21,6 +21,8 @@ from setuptools.extern import six
 from setuptools.extern import packaging
 from setuptools.extern.six.moves import map, filter, filterfalse
 
+from . import SetuptoolsDeprecationWarning
+
 from setuptools.depends import Require
 from setuptools import windows_support
 from setuptools.monkey import get_unpatched
@@ -33,7 +35,7 @@ __import__('setuptools.extern.packaging.version')
 
 
 def _get_unpatched(cls):
-    warnings.warn("Do not call this function", DeprecationWarning)
+    warnings.warn("Do not call this function", DistDeprecationWarning)
     return get_unpatched(cls)
 
 
@@ -980,7 +982,7 @@ class Feature:
             "Features are deprecated and will be removed in a future "
             "version. See https://github.com/pypa/setuptools/issues/65."
         )
-        warnings.warn(msg, DeprecationWarning, stacklevel=3)
+        warnings.warn(msg, DistDeprecationWarning, stacklevel=3)
 
     def __init__(
             self, description, standard=False, available=True,
@@ -1069,3 +1071,7 @@ class Feature:
                     " doesn't contain any packages or modules under %s"
                     % (self.description, item, item)
                 )
+
+
+class DistDeprecationWarning(SetuptoolsDeprecationWarning):
+    """Class for warning about deprecations in dist in setuptools. Not ignored by default, unlike DeprecationWarning."""


Test patch:
diff --git a/pkg_resources/tests/test_resources.py b/pkg_resources/tests/test_resources.py
index 171ba2f96..86afcf741 100644
--- a/pkg_resources/tests/test_resources.py
+++ b/pkg_resources/tests/test_resources.py
@@ -15,7 +15,7 @@ import pkg_resources
 from pkg_resources import (
     parse_requirements, VersionConflict, parse_version,
     Distribution, EntryPoint, Requirement, safe_version, safe_name,
-    WorkingSet)
+    WorkingSet, PkgResourcesDeprecationWarning)
 
 
 # from Python 3.6 docs.
@@ -492,6 +492,15 @@ class TestEntryPoints:
         with pytest.raises(ValueError):
             EntryPoint.parse_map(self.submap_str)
 
+    def testDeprecationWarnings(self):
+        ep = EntryPoint(
+            "foo", "pkg_resources.tests.test_resources", ["TestEntryPoints"],
+            ["x"]
+        )
+        with pytest.warns(pkg_resources.PkgResourcesDeprecationWarning):
+            ep.load(require=False)
+
+
 
 class TestRequirements:
     def testBasics(self):
diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py
index 76759ec57..736c184dc 100644
--- a/setuptools/tests/test_config.py
+++ b/setuptools/tests/test_config.py
@@ -391,6 +391,23 @@ class TestMetadata:
         with get_dist(tmpdir) as dist:
             assert set(dist.metadata.classifiers) == expected
 
+    def test_deprecated_config_handlers(self, tmpdir):
+        fake_env(
+            tmpdir,
+            '[metadata]\n'
+            'version = 10.1.1\n'
+            'description = Some description\n'
+            'requires = some, requirement\n'
+        )
+
+        with pytest.deprecated_call():
+            with get_dist(tmpdir) as dist:
+                metadata = dist.metadata
+
+                assert metadata.version == '10.1.1'
+                assert metadata.description == 'Some description'
+                assert metadata.requires == ['some', 'requirement']
+
 
 class TestOptions:
 
diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py
index 5162e1c98..223ad90c9 100644
--- a/setuptools/tests/test_dist.py
+++ b/setuptools/tests/test_dist.py
@@ -3,7 +3,7 @@
 from __future__ import unicode_literals
 
 import io
-
+from setuptools.dist import DistDeprecationWarning, _get_unpatched
 from setuptools import Distribution
 from setuptools.extern.six.moves.urllib.request import pathname2url
 from setuptools.extern.six.moves.urllib_parse import urljoin
@@ -56,6 +56,9 @@ def test_dist_fetch_build_egg(tmpdir):
     assert [dist.key for dist in resolved_dists if dist] == reqs
 
 
+def test_dist__get_unpatched_deprecated():
+    pytest.warns(DistDeprecationWarning, _get_unpatched, [""])
+
 def __maintainer_test_cases():
     attrs = {"name": "package",
              "version": "1.0",
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
index b0cc4c9fb..2cf65ae7e 100644
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -15,7 +15,7 @@ import distutils.errors
 import io
 import zipfile
 import mock
-
+from setuptools.command.easy_install import EasyInstallDeprecationWarning, ScriptWriter, WindowsScriptWriter
 import time
 from setuptools.extern import six
 from setuptools.extern.six.moves import urllib
@@ -288,6 +288,22 @@ class TestEasyInstallTest:
         assert (target / 'mypkg_script').exists()
 
 
+    def test_dist_get_script_args_deprecated(self):
+        with pytest.warns(EasyInstallDeprecationWarning):
+            ScriptWriter.get_script_args(None, None)
+
+    def test_dist_get_script_header_deprecated(self):
+        with pytest.warns(EasyInstallDeprecationWarning):
+            ScriptWriter.get_script_header("")
+
+    def test_dist_get_writer_deprecated(self):
+        with pytest.warns(EasyInstallDeprecationWarning):
+            ScriptWriter.get_writer(None)
+
+    def test_dist_WindowsScriptWriter_get_writer_deprecated(self):
+        with pytest.warns(EasyInstallDeprecationWarning):
+            WindowsScriptWriter.get_writer()
+
 @pytest.mark.filterwarnings('ignore:Unbuilt egg')
 class TestPTHFileWriter:
     def test_add_from_cwd_site_sets_dirty(self):
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py
index 59ffb16d1..46fb884f2 100644
--- a/setuptools/tests/test_egg_info.py
+++ b/setuptools/tests/test_egg_info.py
@@ -7,7 +7,7 @@ import re
 import stat
 import time
 
-from setuptools.command.egg_info import egg_info, manifest_maker
+from setuptools.command.egg_info import egg_info, manifest_maker, EggInfoDeprecationWarning, get_pkg_info_revision
 from setuptools.dist import Distribution
 from setuptools.extern.six.moves import map
 
@@ -603,3 +603,6 @@ class TestEggInfo:
         with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file:
             pkg_info_lines = pkginfo_file.read().split('\n')
         assert 'Version: 0.0.0.dev0' in pkg_info_lines
+
+    def test_get_pkg_info_revision_deprecated(self):
+        pytest.warns(EggInfoDeprecationWarning, get_pkg_info_revision)
\ No newline at end of file