diff options
author | Davanum Srinivas <davanum@gmail.com> | 2016-04-18 15:08:49 -0400 |
---|---|---|
committer | Davanum Srinivas <davanum@gmail.com> | 2016-04-19 13:34:47 -0400 |
commit | df05ebf3e88858ae7ac74071bd20c86782e1415d (patch) | |
tree | b9f3e1af1bea5f952f05d5dc152c279c8ec15889 | |
parent | fc6aec49d66daaf28d0c1a5ddb31766a056599f1 (diff) | |
download | external_python_setuptools-df05ebf3e88858ae7ac74071bd20c86782e1415d.tar.gz external_python_setuptools-df05ebf3e88858ae7ac74071bd20c86782e1415d.tar.bz2 external_python_setuptools-df05ebf3e88858ae7ac74071bd20c86782e1415d.zip |
Preserve order of egg_info section in setup.cfg
egg_info is the dictionary with information that is injected
into setup.cfg. edit_config uses RawConfigParser which uses
collections.OrderedDict for all the data. When we use a
simple dict(), when we loop through items in edit_config, we
see random behavior as a result the fields
tag_svn_revision/tag_date/tag_build are added to the setup.cfg
randomly. So if we sort the items by key when we traverse items
we will get deterministic output as RawConfigParser uses
OrderedDict internally by default.
-rwxr-xr-x | setuptools/command/setopt.py | 7 | ||||
-rw-r--r-- | setuptools/tests/test_egg_info.py | 62 |
2 files changed, 67 insertions, 2 deletions
diff --git a/setuptools/command/setopt.py b/setuptools/command/setopt.py index 7f332be5..912da782 100755 --- a/setuptools/command/setopt.py +++ b/setuptools/command/setopt.py @@ -2,6 +2,7 @@ from distutils.util import convert_path from distutils import log from distutils.errors import DistutilsOptionError import distutils +import operator import os from setuptools.extern.six.moves import configparser @@ -42,7 +43,8 @@ def edit_config(filename, settings, dry_run=False): log.debug("Reading configuration from %s", filename) opts = configparser.RawConfigParser() opts.read([filename]) - for section, options in settings.items(): + for section, options in sorted(settings.items(), + key=operator.itemgetter(0)): if options is None: log.info("Deleting section [%s] from %s", section, filename) opts.remove_section(section) @@ -50,7 +52,8 @@ def edit_config(filename, settings, dry_run=False): if not opts.has_section(section): log.debug("Adding new section [%s] to %s", section, filename) opts.add_section(section) - for option, value in options.items(): + for option, value in sorted(options.items(), + key=operator.itemgetter(0)): if value is None: log.debug( "Deleting %s.%s from %s", diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index fd5f26fc..d37b127e 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -1,7 +1,16 @@ import os import glob +import re import stat +import sys +try: + from unittest import mock +except ImportError: + import mock + +from setuptools.command.egg_info import egg_info +from setuptools.dist import Distribution from setuptools.extern.six.moves import map import pytest @@ -59,6 +68,59 @@ class TestEggInfo(object): }) yield env + def test_egg_info_save_version_info_setup_empty(self, tmpdir_cwd, env): + setup_cfg = os.path.join(env.paths['home'], 'setup.cfg') + build_files({ + setup_cfg: DALS(""" + [egg_info] + """), + }) + dist = Distribution() + ei = egg_info(dist) + ei.initialize_options() + ei.save_version_info(setup_cfg) + + with open(setup_cfg, 'r') as f: + content = f.read() + + assert '[egg_info]' in content + assert 'tag_build =' in content + assert 'tag_date = 0' in content + assert 'tag_svn_revision = 0' in content + + if sys.version_info[0:2] >= (2, 7): + assert re.search('tag_build.*tag_date.*tag_svn_revision', + content, + re.MULTILINE | re.DOTALL) is not None + + def test_egg_info_save_version_info_setup_defaults(self, tmpdir_cwd, env): + setup_cfg = os.path.join(env.paths['home'], 'setup.cfg') + build_files({ + setup_cfg: DALS(""" + [egg_info] + tag_build = + tag_date = 0 + tag_svn_revision = 0 + """), + }) + dist = Distribution() + ei = egg_info(dist) + ei.initialize_options() + ei.save_version_info(setup_cfg) + + with open(setup_cfg, 'r') as f: + content = f.read() + + assert '[egg_info]' in content + assert 'tag_build =' in content + assert 'tag_date = 0' in content + assert 'tag_svn_revision = 0' in content + + if sys.version_info[0:2] >= (2, 7): + assert re.search('tag_build.*tag_date.*tag_svn_revision', + content, + re.MULTILINE | re.DOTALL) is not None + def test_egg_base_installed_egg_info(self, tmpdir_cwd, env): self._create_project() |