We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Revert "Redact auth from URL in UpdatingDefaultsHelpFormatter"
Reverts pypa/pip#9163

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pip/_internal/cli/parser.py`
Content:
```
1 """Base option parser setup"""
2 
3 # The following comment should be removed at some point in the future.
4 # mypy: disallow-untyped-defs=False
5 
6 from __future__ import absolute_import
7 
8 import logging
9 import optparse
10 import sys
11 import textwrap
12 from distutils.util import strtobool
13 
14 from pip._vendor.contextlib2 import suppress
15 from pip._vendor.six import string_types
16 
17 from pip._internal.cli.status_codes import UNKNOWN_ERROR
18 from pip._internal.configuration import Configuration, ConfigurationError
19 from pip._internal.utils.compat import get_terminal_size
20 from pip._internal.utils.misc import redact_auth_from_url
21 
22 logger = logging.getLogger(__name__)
23 
24 
25 class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
26     """A prettier/less verbose help formatter for optparse."""
27 
28     def __init__(self, *args, **kwargs):
29         # help position must be aligned with __init__.parseopts.description
30         kwargs['max_help_position'] = 30
31         kwargs['indent_increment'] = 1
32         kwargs['width'] = get_terminal_size()[0] - 2
33         optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)
34 
35     def format_option_strings(self, option):
36         return self._format_option_strings(option)
37 
38     def _format_option_strings(self, option, mvarfmt=' <{}>', optsep=', '):
39         """
40         Return a comma-separated list of option strings and metavars.
41 
42         :param option:  tuple of (short opt, long opt), e.g: ('-f', '--format')
43         :param mvarfmt: metavar format string
44         :param optsep:  separator
45         """
46         opts = []
47 
48         if option._short_opts:
49             opts.append(option._short_opts[0])
50         if option._long_opts:
51             opts.append(option._long_opts[0])
52         if len(opts) > 1:
53             opts.insert(1, optsep)
54 
55         if option.takes_value():
56             metavar = option.metavar or option.dest.lower()
57             opts.append(mvarfmt.format(metavar.lower()))
58 
59         return ''.join(opts)
60 
61     def format_heading(self, heading):
62         if heading == 'Options':
63             return ''
64         return heading + ':\n'
65 
66     def format_usage(self, usage):
67         """
68         Ensure there is only one newline between usage and the first heading
69         if there is no description.
70         """
71         msg = '\nUsage: {}\n'.format(
72             self.indent_lines(textwrap.dedent(usage), "  "))
73         return msg
74 
75     def format_description(self, description):
76         # leave full control over description to us
77         if description:
78             if hasattr(self.parser, 'main'):
79                 label = 'Commands'
80             else:
81                 label = 'Description'
82             # some doc strings have initial newlines, some don't
83             description = description.lstrip('\n')
84             # some doc strings have final newlines and spaces, some don't
85             description = description.rstrip()
86             # dedent, then reindent
87             description = self.indent_lines(textwrap.dedent(description), "  ")
88             description = '{}:\n{}\n'.format(label, description)
89             return description
90         else:
91             return ''
92 
93     def format_epilog(self, epilog):
94         # leave full control over epilog to us
95         if epilog:
96             return epilog
97         else:
98             return ''
99 
100     def indent_lines(self, text, indent):
101         new_lines = [indent + line for line in text.split('\n')]
102         return "\n".join(new_lines)
103 
104 
105 class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
106     """Custom help formatter for use in ConfigOptionParser.
107 
108     This is updates the defaults before expanding them, allowing
109     them to show up correctly in the help listing.
110 
111     Also redact auth from url type options
112     """
113 
114     def expand_default(self, option):
115         default_value = None
116         if self.parser is not None:
117             self.parser._update_defaults(self.parser.defaults)
118             default_value = self.parser.defaults.get(option.dest)
119         help_text = optparse.IndentedHelpFormatter.expand_default(self, option)
120 
121         if default_value and option.metavar == 'URL':
122             help_text = help_text.replace(
123                 default_value, redact_auth_from_url(default_value))
124 
125         return help_text
126 
127 
128 class CustomOptionParser(optparse.OptionParser):
129 
130     def insert_option_group(self, idx, *args, **kwargs):
131         """Insert an OptionGroup at a given position."""
132         group = self.add_option_group(*args, **kwargs)
133 
134         self.option_groups.pop()
135         self.option_groups.insert(idx, group)
136 
137         return group
138 
139     @property
140     def option_list_all(self):
141         """Get a list of all options, including those in option groups."""
142         res = self.option_list[:]
143         for i in self.option_groups:
144             res.extend(i.option_list)
145 
146         return res
147 
148 
149 class ConfigOptionParser(CustomOptionParser):
150     """Custom option parser which updates its defaults by checking the
151     configuration files and environmental variables"""
152 
153     def __init__(self, *args, **kwargs):
154         self.name = kwargs.pop('name')
155 
156         isolated = kwargs.pop("isolated", False)
157         self.config = Configuration(isolated)
158 
159         assert self.name
160         optparse.OptionParser.__init__(self, *args, **kwargs)
161 
162     def check_default(self, option, key, val):
163         try:
164             return option.check_value(key, val)
165         except optparse.OptionValueError as exc:
166             print("An error occurred during configuration: {}".format(exc))
167             sys.exit(3)
168 
169     def _get_ordered_configuration_items(self):
170         # Configuration gives keys in an unordered manner. Order them.
171         override_order = ["global", self.name, ":env:"]
172 
173         # Pool the options into different groups
174         section_items = {name: [] for name in override_order}
175         for section_key, val in self.config.items():
176             # ignore empty values
177             if not val:
178                 logger.debug(
179                     "Ignoring configuration key '%s' as it's value is empty.",
180                     section_key
181                 )
182                 continue
183 
184             section, key = section_key.split(".", 1)
185             if section in override_order:
186                 section_items[section].append((key, val))
187 
188         # Yield each group in their override order
189         for section in override_order:
190             for key, val in section_items[section]:
191                 yield key, val
192 
193     def _update_defaults(self, defaults):
194         """Updates the given defaults with values from the config files and
195         the environ. Does a little special handling for certain types of
196         options (lists)."""
197 
198         # Accumulate complex default state.
199         self.values = optparse.Values(self.defaults)
200         late_eval = set()
201         # Then set the options with those values
202         for key, val in self._get_ordered_configuration_items():
203             # '--' because configuration supports only long names
204             option = self.get_option('--' + key)
205 
206             # Ignore options not present in this parser. E.g. non-globals put
207             # in [global] by users that want them to apply to all applicable
208             # commands.
209             if option is None:
210                 continue
211 
212             if option.action in ('store_true', 'store_false'):
213                 try:
214                     val = strtobool(val)
215                 except ValueError:
216                     self.error(
217                         '{} is not a valid value for {} option, '  # noqa
218                         'please specify a boolean value like yes/no, '
219                         'true/false or 1/0 instead.'.format(val, key)
220                     )
221             elif option.action == 'count':
222                 with suppress(ValueError):
223                     val = strtobool(val)
224                 with suppress(ValueError):
225                     val = int(val)
226                 if not isinstance(val, int) or val < 0:
227                     self.error(
228                         '{} is not a valid value for {} option, '  # noqa
229                         'please instead specify either a non-negative integer '
230                         'or a boolean value like yes/no or false/true '
231                         'which is equivalent to 1/0.'.format(val, key)
232                     )
233             elif option.action == 'append':
234                 val = val.split()
235                 val = [self.check_default(option, key, v) for v in val]
236             elif option.action == 'callback':
237                 late_eval.add(option.dest)
238                 opt_str = option.get_opt_string()
239                 val = option.convert_value(opt_str, val)
240                 # From take_action
241                 args = option.callback_args or ()
242                 kwargs = option.callback_kwargs or {}
243                 option.callback(option, opt_str, val, self, *args, **kwargs)
244             else:
245                 val = self.check_default(option, key, val)
246 
247             defaults[option.dest] = val
248 
249         for key in late_eval:
250             defaults[key] = getattr(self.values, key)
251         self.values = None
252         return defaults
253 
254     def get_default_values(self):
255         """Overriding to make updating the defaults after instantiation of
256         the option parser possible, _update_defaults() does the dirty work."""
257         if not self.process_default_values:
258             # Old, pre-Optik 1.5 behaviour.
259             return optparse.Values(self.defaults)
260 
261         # Load the configuration, or error out in case of an error
262         try:
263             self.config.load()
264         except ConfigurationError as err:
265             self.exit(UNKNOWN_ERROR, str(err))
266 
267         defaults = self._update_defaults(self.defaults.copy())  # ours
268         for option in self._get_all_options():
269             default = defaults.get(option.dest)
270             if isinstance(default, string_types):
271                 opt_str = option.get_opt_string()
272                 defaults[option.dest] = option.check_value(opt_str, default)
273         return optparse.Values(defaults)
274 
275     def error(self, msg):
276         self.print_usage(sys.stderr)
277         self.exit(UNKNOWN_ERROR, "{}\n".format(msg))
278
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pip/_internal/cli/parser.py b/src/pip/_internal/cli/parser.py
--- a/src/pip/_internal/cli/parser.py
+++ b/src/pip/_internal/cli/parser.py
@@ -112,15 +112,23 @@
     """
 
     def expand_default(self, option):
-        default_value = None
+        default_values = None
         if self.parser is not None:
             self.parser._update_defaults(self.parser.defaults)
-            default_value = self.parser.defaults.get(option.dest)
+            default_values = self.parser.defaults.get(option.dest)
         help_text = optparse.IndentedHelpFormatter.expand_default(self, option)
 
-        if default_value and option.metavar == 'URL':
-            help_text = help_text.replace(
-                default_value, redact_auth_from_url(default_value))
+        if default_values and option.metavar == 'URL':
+            if isinstance(default_values, string_types):
+                default_values = [default_values]
+
+            # If its not a list, we should abort and just return the help text
+            if not isinstance(default_values, list):
+                default_values = []
+
+            for val in default_values:
+                help_text = help_text.replace(
+                    val, redact_auth_from_url(val))
 
         return help_text

{"golden_diff": "diff --git a/src/pip/_internal/cli/parser.py b/src/pip/_internal/cli/parser.py\n--- a/src/pip/_internal/cli/parser.py\n+++ b/src/pip/_internal/cli/parser.py\n@@ -112,15 +112,23 @@\n     \"\"\"\n \n     def expand_default(self, option):\n-        default_value = None\n+        default_values = None\n         if self.parser is not None:\n             self.parser._update_defaults(self.parser.defaults)\n-            default_value = self.parser.defaults.get(option.dest)\n+            default_values = self.parser.defaults.get(option.dest)\n         help_text = optparse.IndentedHelpFormatter.expand_default(self, option)\n \n-        if default_value and option.metavar == 'URL':\n-            help_text = help_text.replace(\n-                default_value, redact_auth_from_url(default_value))\n+        if default_values and option.metavar == 'URL':\n+            if isinstance(default_values, string_types):\n+                default_values = [default_values]\n+\n+            # If its not a list, we should abort and just return the help text\n+            if not isinstance(default_values, list):\n+                default_values = []\n+\n+            for val in default_values:\n+                help_text = help_text.replace(\n+                    val, redact_auth_from_url(val))\n \n         return help_text\n", "issue": "Revert \"Redact auth from URL in UpdatingDefaultsHelpFormatter\"\nReverts pypa/pip#9163\n", "before_files": [{"content": "\"\"\"Base option parser setup\"\"\"\n\n# The following comment should be removed at some point in the future.\n# mypy: disallow-untyped-defs=False\n\nfrom __future__ import absolute_import\n\nimport logging\nimport optparse\nimport sys\nimport textwrap\nfrom distutils.util import strtobool\n\nfrom pip._vendor.contextlib2 import suppress\nfrom pip._vendor.six import string_types\n\nfrom pip._internal.cli.status_codes import UNKNOWN_ERROR\nfrom pip._internal.configuration import Configuration, ConfigurationError\nfrom pip._internal.utils.compat import get_terminal_size\nfrom pip._internal.utils.misc import redact_auth_from_url\n\nlogger = logging.getLogger(__name__)\n\n\nclass PrettyHelpFormatter(optparse.IndentedHelpFormatter):\n    \"\"\"A prettier/less verbose help formatter for optparse.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # help position must be aligned with __init__.parseopts.description\n        kwargs['max_help_position'] = 30\n        kwargs['indent_increment'] = 1\n        kwargs['width'] = get_terminal_size()[0] - 2\n        optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)\n\n    def format_option_strings(self, option):\n        return self._format_option_strings(option)\n\n    def _format_option_strings(self, option, mvarfmt=' <{}>', optsep=', '):\n        \"\"\"\n        Return a comma-separated list of option strings and metavars.\n\n        :param option:  tuple of (short opt, long opt), e.g: ('-f', '--format')\n        :param mvarfmt: metavar format string\n        :param optsep:  separator\n        \"\"\"\n        opts = []\n\n        if option._short_opts:\n            opts.append(option._short_opts[0])\n        if option._long_opts:\n            opts.append(option._long_opts[0])\n        if len(opts) > 1:\n            opts.insert(1, optsep)\n\n        if option.takes_value():\n            metavar = option.metavar or option.dest.lower()\n            opts.append(mvarfmt.format(metavar.lower()))\n\n        return ''.join(opts)\n\n    def format_heading(self, heading):\n        if heading == 'Options':\n            return ''\n        return heading + ':\\n'\n\n    def format_usage(self, usage):\n        \"\"\"\n        Ensure there is only one newline between usage and the first heading\n        if there is no description.\n        \"\"\"\n        msg = '\\nUsage: {}\\n'.format(\n            self.indent_lines(textwrap.dedent(usage), \"  \"))\n        return msg\n\n    def format_description(self, description):\n        # leave full control over description to us\n        if description:\n            if hasattr(self.parser, 'main'):\n                label = 'Commands'\n            else:\n                label = 'Description'\n            # some doc strings have initial newlines, some don't\n            description = description.lstrip('\\n')\n            # some doc strings have final newlines and spaces, some don't\n            description = description.rstrip()\n            # dedent, then reindent\n            description = self.indent_lines(textwrap.dedent(description), \"  \")\n            description = '{}:\\n{}\\n'.format(label, description)\n            return description\n        else:\n            return ''\n\n    def format_epilog(self, epilog):\n        # leave full control over epilog to us\n        if epilog:\n            return epilog\n        else:\n            return ''\n\n    def indent_lines(self, text, indent):\n        new_lines = [indent + line for line in text.split('\\n')]\n        return \"\\n\".join(new_lines)\n\n\nclass UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):\n    \"\"\"Custom help formatter for use in ConfigOptionParser.\n\n    This is updates the defaults before expanding them, allowing\n    them to show up correctly in the help listing.\n\n    Also redact auth from url type options\n    \"\"\"\n\n    def expand_default(self, option):\n        default_value = None\n        if self.parser is not None:\n            self.parser._update_defaults(self.parser.defaults)\n            default_value = self.parser.defaults.get(option.dest)\n        help_text = optparse.IndentedHelpFormatter.expand_default(self, option)\n\n        if default_value and option.metavar == 'URL':\n            help_text = help_text.replace(\n                default_value, redact_auth_from_url(default_value))\n\n        return help_text\n\n\nclass CustomOptionParser(optparse.OptionParser):\n\n    def insert_option_group(self, idx, *args, **kwargs):\n        \"\"\"Insert an OptionGroup at a given position.\"\"\"\n        group = self.add_option_group(*args, **kwargs)\n\n        self.option_groups.pop()\n        self.option_groups.insert(idx, group)\n\n        return group\n\n    @property\n    def option_list_all(self):\n        \"\"\"Get a list of all options, including those in option groups.\"\"\"\n        res = self.option_list[:]\n        for i in self.option_groups:\n            res.extend(i.option_list)\n\n        return res\n\n\nclass ConfigOptionParser(CustomOptionParser):\n    \"\"\"Custom option parser which updates its defaults by checking the\n    configuration files and environmental variables\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.name = kwargs.pop('name')\n\n        isolated = kwargs.pop(\"isolated\", False)\n        self.config = Configuration(isolated)\n\n        assert self.name\n        optparse.OptionParser.__init__(self, *args, **kwargs)\n\n    def check_default(self, option, key, val):\n        try:\n            return option.check_value(key, val)\n        except optparse.OptionValueError as exc:\n            print(\"An error occurred during configuration: {}\".format(exc))\n            sys.exit(3)\n\n    def _get_ordered_configuration_items(self):\n        # Configuration gives keys in an unordered manner. Order them.\n        override_order = [\"global\", self.name, \":env:\"]\n\n        # Pool the options into different groups\n        section_items = {name: [] for name in override_order}\n        for section_key, val in self.config.items():\n            # ignore empty values\n            if not val:\n                logger.debug(\n                    \"Ignoring configuration key '%s' as it's value is empty.\",\n                    section_key\n                )\n                continue\n\n            section, key = section_key.split(\".\", 1)\n            if section in override_order:\n                section_items[section].append((key, val))\n\n        # Yield each group in their override order\n        for section in override_order:\n            for key, val in section_items[section]:\n                yield key, val\n\n    def _update_defaults(self, defaults):\n        \"\"\"Updates the given defaults with values from the config files and\n        the environ. Does a little special handling for certain types of\n        options (lists).\"\"\"\n\n        # Accumulate complex default state.\n        self.values = optparse.Values(self.defaults)\n        late_eval = set()\n        # Then set the options with those values\n        for key, val in self._get_ordered_configuration_items():\n            # '--' because configuration supports only long names\n            option = self.get_option('--' + key)\n\n            # Ignore options not present in this parser. E.g. non-globals put\n            # in [global] by users that want them to apply to all applicable\n            # commands.\n            if option is None:\n                continue\n\n            if option.action in ('store_true', 'store_false'):\n                try:\n                    val = strtobool(val)\n                except ValueError:\n                    self.error(\n                        '{} is not a valid value for {} option, '  # noqa\n                        'please specify a boolean value like yes/no, '\n                        'true/false or 1/0 instead.'.format(val, key)\n                    )\n            elif option.action == 'count':\n                with suppress(ValueError):\n                    val = strtobool(val)\n                with suppress(ValueError):\n                    val = int(val)\n                if not isinstance(val, int) or val < 0:\n                    self.error(\n                        '{} is not a valid value for {} option, '  # noqa\n                        'please instead specify either a non-negative integer '\n                        'or a boolean value like yes/no or false/true '\n                        'which is equivalent to 1/0.'.format(val, key)\n                    )\n            elif option.action == 'append':\n                val = val.split()\n                val = [self.check_default(option, key, v) for v in val]\n            elif option.action == 'callback':\n                late_eval.add(option.dest)\n                opt_str = option.get_opt_string()\n                val = option.convert_value(opt_str, val)\n                # From take_action\n                args = option.callback_args or ()\n                kwargs = option.callback_kwargs or {}\n                option.callback(option, opt_str, val, self, *args, **kwargs)\n            else:\n                val = self.check_default(option, key, val)\n\n            defaults[option.dest] = val\n\n        for key in late_eval:\n            defaults[key] = getattr(self.values, key)\n        self.values = None\n        return defaults\n\n    def get_default_values(self):\n        \"\"\"Overriding to make updating the defaults after instantiation of\n        the option parser possible, _update_defaults() does the dirty work.\"\"\"\n        if not self.process_default_values:\n            # Old, pre-Optik 1.5 behaviour.\n            return optparse.Values(self.defaults)\n\n        # Load the configuration, or error out in case of an error\n        try:\n            self.config.load()\n        except ConfigurationError as err:\n            self.exit(UNKNOWN_ERROR, str(err))\n\n        defaults = self._update_defaults(self.defaults.copy())  # ours\n        for option in self._get_all_options():\n            default = defaults.get(option.dest)\n            if isinstance(default, string_types):\n                opt_str = option.get_opt_string()\n                defaults[option.dest] = option.check_value(opt_str, default)\n        return optparse.Values(defaults)\n\n    def error(self, msg):\n        self.print_usage(sys.stderr)\n        self.exit(UNKNOWN_ERROR, \"{}\\n\".format(msg))\n", "path": "src/pip/_internal/cli/parser.py"}], "after_files": [{"content": "\"\"\"Base option parser setup\"\"\"\n\n# The following comment should be removed at some point in the future.\n# mypy: disallow-untyped-defs=False\n\nfrom __future__ import absolute_import\n\nimport logging\nimport optparse\nimport sys\nimport textwrap\nfrom distutils.util import strtobool\n\nfrom pip._vendor.contextlib2 import suppress\nfrom pip._vendor.six import string_types\n\nfrom pip._internal.cli.status_codes import UNKNOWN_ERROR\nfrom pip._internal.configuration import Configuration, ConfigurationError\nfrom pip._internal.utils.compat import get_terminal_size\nfrom pip._internal.utils.misc import redact_auth_from_url\n\nlogger = logging.getLogger(__name__)\n\n\nclass PrettyHelpFormatter(optparse.IndentedHelpFormatter):\n    \"\"\"A prettier/less verbose help formatter for optparse.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # help position must be aligned with __init__.parseopts.description\n        kwargs['max_help_position'] = 30\n        kwargs['indent_increment'] = 1\n        kwargs['width'] = get_terminal_size()[0] - 2\n        optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs)\n\n    def format_option_strings(self, option):\n        return self._format_option_strings(option)\n\n    def _format_option_strings(self, option, mvarfmt=' <{}>', optsep=', '):\n        \"\"\"\n        Return a comma-separated list of option strings and metavars.\n\n        :param option:  tuple of (short opt, long opt), e.g: ('-f', '--format')\n        :param mvarfmt: metavar format string\n        :param optsep:  separator\n        \"\"\"\n        opts = []\n\n        if option._short_opts:\n            opts.append(option._short_opts[0])\n        if option._long_opts:\n            opts.append(option._long_opts[0])\n        if len(opts) > 1:\n            opts.insert(1, optsep)\n\n        if option.takes_value():\n            metavar = option.metavar or option.dest.lower()\n            opts.append(mvarfmt.format(metavar.lower()))\n\n        return ''.join(opts)\n\n    def format_heading(self, heading):\n        if heading == 'Options':\n            return ''\n        return heading + ':\\n'\n\n    def format_usage(self, usage):\n        \"\"\"\n        Ensure there is only one newline between usage and the first heading\n        if there is no description.\n        \"\"\"\n        msg = '\\nUsage: {}\\n'.format(\n            self.indent_lines(textwrap.dedent(usage), \"  \"))\n        return msg\n\n    def format_description(self, description):\n        # leave full control over description to us\n        if description:\n            if hasattr(self.parser, 'main'):\n                label = 'Commands'\n            else:\n                label = 'Description'\n            # some doc strings have initial newlines, some don't\n            description = description.lstrip('\\n')\n            # some doc strings have final newlines and spaces, some don't\n            description = description.rstrip()\n            # dedent, then reindent\n            description = self.indent_lines(textwrap.dedent(description), \"  \")\n            description = '{}:\\n{}\\n'.format(label, description)\n            return description\n        else:\n            return ''\n\n    def format_epilog(self, epilog):\n        # leave full control over epilog to us\n        if epilog:\n            return epilog\n        else:\n            return ''\n\n    def indent_lines(self, text, indent):\n        new_lines = [indent + line for line in text.split('\\n')]\n        return \"\\n\".join(new_lines)\n\n\nclass UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):\n    \"\"\"Custom help formatter for use in ConfigOptionParser.\n\n    This is updates the defaults before expanding them, allowing\n    them to show up correctly in the help listing.\n\n    Also redact auth from url type options\n    \"\"\"\n\n    def expand_default(self, option):\n        default_values = None\n        if self.parser is not None:\n            self.parser._update_defaults(self.parser.defaults)\n            default_values = self.parser.defaults.get(option.dest)\n        help_text = optparse.IndentedHelpFormatter.expand_default(self, option)\n\n        if default_values and option.metavar == 'URL':\n            if isinstance(default_values, string_types):\n                default_values = [default_values]\n\n            # If its not a list, we should abort and just return the help text\n            if not isinstance(default_values, list):\n                default_values = []\n\n            for val in default_values:\n                help_text = help_text.replace(\n                    val, redact_auth_from_url(val))\n\n        return help_text\n\n\nclass CustomOptionParser(optparse.OptionParser):\n\n    def insert_option_group(self, idx, *args, **kwargs):\n        \"\"\"Insert an OptionGroup at a given position.\"\"\"\n        group = self.add_option_group(*args, **kwargs)\n\n        self.option_groups.pop()\n        self.option_groups.insert(idx, group)\n\n        return group\n\n    @property\n    def option_list_all(self):\n        \"\"\"Get a list of all options, including those in option groups.\"\"\"\n        res = self.option_list[:]\n        for i in self.option_groups:\n            res.extend(i.option_list)\n\n        return res\n\n\nclass ConfigOptionParser(CustomOptionParser):\n    \"\"\"Custom option parser which updates its defaults by checking the\n    configuration files and environmental variables\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.name = kwargs.pop('name')\n\n        isolated = kwargs.pop(\"isolated\", False)\n        self.config = Configuration(isolated)\n\n        assert self.name\n        optparse.OptionParser.__init__(self, *args, **kwargs)\n\n    def check_default(self, option, key, val):\n        try:\n            return option.check_value(key, val)\n        except optparse.OptionValueError as exc:\n            print(\"An error occurred during configuration: {}\".format(exc))\n            sys.exit(3)\n\n    def _get_ordered_configuration_items(self):\n        # Configuration gives keys in an unordered manner. Order them.\n        override_order = [\"global\", self.name, \":env:\"]\n\n        # Pool the options into different groups\n        section_items = {name: [] for name in override_order}\n        for section_key, val in self.config.items():\n            # ignore empty values\n            if not val:\n                logger.debug(\n                    \"Ignoring configuration key '%s' as it's value is empty.\",\n                    section_key\n                )\n                continue\n\n            section, key = section_key.split(\".\", 1)\n            if section in override_order:\n                section_items[section].append((key, val))\n\n        # Yield each group in their override order\n        for section in override_order:\n            for key, val in section_items[section]:\n                yield key, val\n\n    def _update_defaults(self, defaults):\n        \"\"\"Updates the given defaults with values from the config files and\n        the environ. Does a little special handling for certain types of\n        options (lists).\"\"\"\n\n        # Accumulate complex default state.\n        self.values = optparse.Values(self.defaults)\n        late_eval = set()\n        # Then set the options with those values\n        for key, val in self._get_ordered_configuration_items():\n            # '--' because configuration supports only long names\n            option = self.get_option('--' + key)\n\n            # Ignore options not present in this parser. E.g. non-globals put\n            # in [global] by users that want them to apply to all applicable\n            # commands.\n            if option is None:\n                continue\n\n            if option.action in ('store_true', 'store_false'):\n                try:\n                    val = strtobool(val)\n                except ValueError:\n                    self.error(\n                        '{} is not a valid value for {} option, '  # noqa\n                        'please specify a boolean value like yes/no, '\n                        'true/false or 1/0 instead.'.format(val, key)\n                    )\n            elif option.action == 'count':\n                with suppress(ValueError):\n                    val = strtobool(val)\n                with suppress(ValueError):\n                    val = int(val)\n                if not isinstance(val, int) or val < 0:\n                    self.error(\n                        '{} is not a valid value for {} option, '  # noqa\n                        'please instead specify either a non-negative integer '\n                        'or a boolean value like yes/no or false/true '\n                        'which is equivalent to 1/0.'.format(val, key)\n                    )\n            elif option.action == 'append':\n                val = val.split()\n                val = [self.check_default(option, key, v) for v in val]\n            elif option.action == 'callback':\n                late_eval.add(option.dest)\n                opt_str = option.get_opt_string()\n                val = option.convert_value(opt_str, val)\n                # From take_action\n                args = option.callback_args or ()\n                kwargs = option.callback_kwargs or {}\n                option.callback(option, opt_str, val, self, *args, **kwargs)\n            else:\n                val = self.check_default(option, key, val)\n\n            defaults[option.dest] = val\n\n        for key in late_eval:\n            defaults[key] = getattr(self.values, key)\n        self.values = None\n        return defaults\n\n    def get_default_values(self):\n        \"\"\"Overriding to make updating the defaults after instantiation of\n        the option parser possible, _update_defaults() does the dirty work.\"\"\"\n        if not self.process_default_values:\n            # Old, pre-Optik 1.5 behaviour.\n            return optparse.Values(self.defaults)\n\n        # Load the configuration, or error out in case of an error\n        try:\n            self.config.load()\n        except ConfigurationError as err:\n            self.exit(UNKNOWN_ERROR, str(err))\n\n        defaults = self._update_defaults(self.defaults.copy())  # ours\n        for option in self._get_all_options():\n            default = defaults.get(option.dest)\n            if isinstance(default, string_types):\n                opt_str = option.get_opt_string()\n                defaults[option.dest] = option.check_value(opt_str, default)\n        return optparse.Values(defaults)\n\n    def error(self, msg):\n        self.print_usage(sys.stderr)\n        self.exit(UNKNOWN_ERROR, \"{}\\n\".format(msg))\n", "path": "src/pip/_internal/cli/parser.py"}]}