We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pip 7.0.1: you should use "--trusted-host". Hey, no such option "--trusted-host"!
```
$ cat req.txt 
--extra-index-url http://pip.mycompany.com/simple 
mylib
myanotherlib

$ pip install -r req.txt
Collecting mylib (from -r req.txt (line 2))
.../urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
  The repository located at pip.mycompany.com is not a trusted or secure host and is being ignored. If this repository is available via HTTPS it is recommended to use HTTPS instead, otherwise you may silence this warning and allow it anyways with '--trusted-host pip.mycompany.com'.
  Could not find a version that satisfies the requirement mylib (from -r req.txt (line 2)) (from versions: )
No matching distribution found for mylib (from -r req.txt (line 2))

$ cat req1.txt 
--extra-index-url http://pip.mycompany.com/simple 
--trusted-host pip.mycompany.com
mylib
myanotherlib

$ pip install -r req1.txt 
Usage: pip [options]

pip: error: no such option: --trusted-host
$ 
```

I know that i can run `pip install -r file.txt --trusted-host=mycompany.com` but I configure my servers with Chef, not running pip directly.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pip/req/req_file.py`
Content:
```
1 """
2 Requirements file parsing
3 """
4 
5 from __future__ import absolute_import
6 
7 import os
8 import re
9 import shlex
10 import optparse
11 import warnings
12 
13 from pip._vendor.six.moves.urllib import parse as urllib_parse
14 from pip._vendor.six.moves import filterfalse
15 
16 import pip
17 from pip.download import get_file_content
18 from pip.req.req_install import InstallRequirement
19 from pip.exceptions import (RequirementsFileParseError)
20 from pip.utils.deprecation import RemovedInPip10Warning
21 from pip import cmdoptions
22 
23 __all__ = ['parse_requirements']
24 
25 SCHEME_RE = re.compile(r'^(http|https|file):', re.I)
26 COMMENT_RE = re.compile(r'(^|\s)+#.*$')
27 
28 SUPPORTED_OPTIONS = [
29     cmdoptions.constraints,
30     cmdoptions.editable,
31     cmdoptions.requirements,
32     cmdoptions.no_index,
33     cmdoptions.index_url,
34     cmdoptions.find_links,
35     cmdoptions.extra_index_url,
36     cmdoptions.allow_external,
37     cmdoptions.allow_all_external,
38     cmdoptions.no_allow_external,
39     cmdoptions.allow_unsafe,
40     cmdoptions.no_allow_unsafe,
41     cmdoptions.use_wheel,
42     cmdoptions.no_use_wheel,
43     cmdoptions.always_unzip,
44     cmdoptions.no_binary,
45     cmdoptions.only_binary,
46 ]
47 
48 # options to be passed to requirements
49 SUPPORTED_OPTIONS_REQ = [
50     cmdoptions.install_options,
51     cmdoptions.global_options
52 ]
53 
54 # the 'dest' string values
55 SUPPORTED_OPTIONS_REQ_DEST = [o().dest for o in SUPPORTED_OPTIONS_REQ]
56 
57 
58 def parse_requirements(filename, finder=None, comes_from=None, options=None,
59                        session=None, constraint=False, wheel_cache=None):
60     """Parse a requirements file and yield InstallRequirement instances.
61 
62     :param filename:    Path or url of requirements file.
63     :param finder:      Instance of pip.index.PackageFinder.
64     :param comes_from:  Origin description of requirements.
65     :param options:     Global options.
66     :param session:     Instance of pip.download.PipSession.
67     :param constraint:  If true, parsing a constraint file rather than
68         requirements file.
69     :param wheel_cache: Instance of pip.wheel.WheelCache
70     """
71     if session is None:
72         raise TypeError(
73             "parse_requirements() missing 1 required keyword argument: "
74             "'session'"
75         )
76 
77     _, content = get_file_content(
78         filename, comes_from=comes_from, session=session
79     )
80 
81     lines = content.splitlines()
82     lines = ignore_comments(lines)
83     lines = join_lines(lines)
84     lines = skip_regex(lines, options)
85 
86     for line_number, line in enumerate(lines, 1):
87         req_iter = process_line(line, filename, line_number, finder,
88                                 comes_from, options, session, wheel_cache,
89                                 constraint=constraint)
90         for req in req_iter:
91             yield req
92 
93 
94 def process_line(line, filename, line_number, finder=None, comes_from=None,
95                  options=None, session=None, wheel_cache=None,
96                  constraint=False):
97     """Process a single requirements line; This can result in creating/yielding
98     requirements, or updating the finder.
99 
100     For lines that contain requirements, the only options that have an effect
101     are from SUPPORTED_OPTIONS_REQ, and they are scoped to the
102     requirement. Other options from SUPPORTED_OPTIONS may be present, but are
103     ignored.
104 
105     For lines that do not contain requirements, the only options that have an
106     effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may
107     be present, but are ignored. These lines may contain multiple options
108     (although our docs imply only one is supported), and all our parsed and
109     affect the finder.
110 
111     :param constraint: If True, parsing a constraints file.
112     """
113     parser = build_parser()
114     defaults = parser.get_default_values()
115     defaults.index_url = None
116     if finder:
117         # `finder.format_control` will be updated during parsing
118         defaults.format_control = finder.format_control
119     args_str, options_str = break_args_options(line)
120     opts, _ = parser.parse_args(shlex.split(options_str), defaults)
121 
122     # preserve for the nested code path
123     line_comes_from = '%s %s (line %s)' % (
124         '-c' if constraint else '-r', filename, line_number)
125 
126     # yield a line requirement
127     if args_str:
128         isolated = options.isolated_mode if options else False
129         if options:
130             cmdoptions.check_install_build_global(options, opts)
131         # get the options that apply to requirements
132         req_options = {}
133         for dest in SUPPORTED_OPTIONS_REQ_DEST:
134             if dest in opts.__dict__ and opts.__dict__[dest]:
135                 req_options[dest] = opts.__dict__[dest]
136         yield InstallRequirement.from_line(
137             args_str, line_comes_from, constraint=constraint,
138             isolated=isolated, options=req_options, wheel_cache=wheel_cache
139         )
140 
141     # yield an editable requirement
142     elif opts.editables:
143         isolated = options.isolated_mode if options else False
144         default_vcs = options.default_vcs if options else None
145         yield InstallRequirement.from_editable(
146             opts.editables[0], comes_from=line_comes_from,
147             constraint=constraint, default_vcs=default_vcs, isolated=isolated,
148             wheel_cache=wheel_cache
149         )
150 
151     # parse a nested requirements file
152     elif opts.requirements or opts.constraints:
153         if opts.requirements:
154             req_path = opts.requirements[0]
155             nested_constraint = False
156         else:
157             req_path = opts.constraints[0]
158             nested_constraint = True
159         # original file is over http
160         if SCHEME_RE.search(filename):
161             # do a url join so relative paths work
162             req_path = urllib_parse.urljoin(filename, req_path)
163         # original file and nested file are paths
164         elif not SCHEME_RE.search(req_path):
165             # do a join so relative paths work
166             req_dir = os.path.dirname(filename)
167             req_path = os.path.join(os.path.dirname(filename), req_path)
168         # TODO: Why not use `comes_from='-r {} (line {})'` here as well?
169         parser = parse_requirements(
170             req_path, finder, comes_from, options, session,
171             constraint=nested_constraint, wheel_cache=wheel_cache
172         )
173         for req in parser:
174             yield req
175 
176     # set finder options
177     elif finder:
178         if opts.allow_external:
179             warnings.warn(
180                 "--allow-external has been deprecated and will be removed in "
181                 "the future. Due to changes in the repository protocol, it no "
182                 "longer has any effect.",
183                 RemovedInPip10Warning,
184             )
185 
186         if opts.allow_all_external:
187             warnings.warn(
188                 "--allow-all-external has been deprecated and will be removed "
189                 "in the future. Due to changes in the repository protocol, it "
190                 "no longer has any effect.",
191                 RemovedInPip10Warning,
192             )
193 
194         if opts.allow_unverified:
195             warnings.warn(
196                 "--allow-unverified has been deprecated and will be removed "
197                 "in the future. Due to changes in the repository protocol, it "
198                 "no longer has any effect.",
199                 RemovedInPip10Warning,
200             )
201 
202         if opts.index_url:
203             finder.index_urls = [opts.index_url]
204         if opts.use_wheel is False:
205             finder.use_wheel = False
206             pip.index.fmt_ctl_no_use_wheel(finder.format_control)
207         if opts.no_index is True:
208             finder.index_urls = []
209         if opts.extra_index_urls:
210             finder.index_urls.extend(opts.extra_index_urls)
211         if opts.find_links:
212             # FIXME: it would be nice to keep track of the source
213             # of the find_links: support a find-links local path
214             # relative to a requirements file.
215             value = opts.find_links[0]
216             req_dir = os.path.dirname(os.path.abspath(filename))
217             relative_to_reqs_file = os.path.join(req_dir, value)
218             if os.path.exists(relative_to_reqs_file):
219                 value = relative_to_reqs_file
220             finder.find_links.append(value)
221 
222 
223 def break_args_options(line):
224     """Break up the line into an args and options string.  We only want to shlex
225     (and then optparse) the options, not the args.  args can contain markers
226     which are corrupted by shlex.
227     """
228     tokens = line.split(' ')
229     args = []
230     options = tokens[:]
231     for token in tokens:
232         if token.startswith('-') or token.startswith('--'):
233             break
234         else:
235             args.append(token)
236             options.pop(0)
237     return ' '.join(args), ' '.join(options)
238 
239 
240 def build_parser():
241     """
242     Return a parser for parsing requirement lines
243     """
244     parser = optparse.OptionParser(add_help_option=False)
245 
246     option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ
247     for option_factory in option_factories:
248         option = option_factory()
249         parser.add_option(option)
250 
251     # By default optparse sys.exits on parsing errors. We want to wrap
252     # that in our own exception.
253     def parser_exit(self, msg):
254         raise RequirementsFileParseError(msg)
255     parser.exit = parser_exit
256 
257     return parser
258 
259 
260 def join_lines(iterator):
261     """
262     Joins a line ending in '\' with the previous line.
263     """
264     lines = []
265     for line in iterator:
266         if not line.endswith('\\'):
267             if lines:
268                 lines.append(line)
269                 yield ''.join(lines)
270                 lines = []
271             else:
272                 yield line
273         else:
274             lines.append(line.strip('\\'))
275 
276     # TODO: handle space after '\'.
277     # TODO: handle '\' on last line.
278 
279 
280 def ignore_comments(iterator):
281     """
282     Strips and filters empty or commented lines.
283     """
284     for line in iterator:
285         line = COMMENT_RE.sub('', line)
286         line = line.strip()
287         if line:
288             yield line
289 
290 
291 def skip_regex(lines, options):
292     """
293     Optionally exclude lines that match '--skip-requirements-regex'
294     """
295     skip_regex = options.skip_requirements_regex if options else None
296     if skip_regex:
297         lines = filterfalse(re.compile(skip_regex).search, lines)
298     return lines
299
```
--- 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/pip/req/req_file.py b/pip/req/req_file.py
--- a/pip/req/req_file.py
+++ b/pip/req/req_file.py
@@ -43,6 +43,7 @@
     cmdoptions.always_unzip,
     cmdoptions.no_binary,
     cmdoptions.only_binary,
+    cmdoptions.trusted_host,
 ]
 
 # options to be passed to requirements
@@ -218,6 +219,9 @@
             if os.path.exists(relative_to_reqs_file):
                 value = relative_to_reqs_file
             finder.find_links.append(value)
+        if opts.trusted_hosts:
+            finder.secure_origins.extend(
+                ("*", host, "*") for host in opts.trusted_hosts)
 
 
 def break_args_options(line):

{"golden_diff": "diff --git a/pip/req/req_file.py b/pip/req/req_file.py\n--- a/pip/req/req_file.py\n+++ b/pip/req/req_file.py\n@@ -43,6 +43,7 @@\n     cmdoptions.always_unzip,\n     cmdoptions.no_binary,\n     cmdoptions.only_binary,\n+    cmdoptions.trusted_host,\n ]\n \n # options to be passed to requirements\n@@ -218,6 +219,9 @@\n             if os.path.exists(relative_to_reqs_file):\n                 value = relative_to_reqs_file\n             finder.find_links.append(value)\n+        if opts.trusted_hosts:\n+            finder.secure_origins.extend(\n+                (\"*\", host, \"*\") for host in opts.trusted_hosts)\n \n \n def break_args_options(line):\n", "issue": "pip 7.0.1: you should use \"--trusted-host\". Hey, no such option \"--trusted-host\"!\n```\n$ cat req.txt \n--extra-index-url http://pip.mycompany.com/simple \nmylib\nmyanotherlib\n\n$ pip install -r req.txt\nCollecting mylib (from -r req.txt (line 2))\n.../urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.\n  InsecurePlatformWarning\n  The repository located at pip.mycompany.com is not a trusted or secure host and is being ignored. If this repository is available via HTTPS it is recommended to use HTTPS instead, otherwise you may silence this warning and allow it anyways with '--trusted-host pip.mycompany.com'.\n  Could not find a version that satisfies the requirement mylib (from -r req.txt (line 2)) (from versions: )\nNo matching distribution found for mylib (from -r req.txt (line 2))\n\n$ cat req1.txt \n--extra-index-url http://pip.mycompany.com/simple \n--trusted-host pip.mycompany.com\nmylib\nmyanotherlib\n\n$ pip install -r req1.txt \nUsage: pip [options]\n\npip: error: no such option: --trusted-host\n$ \n```\n\nI know that i can run `pip install -r file.txt --trusted-host=mycompany.com` but I configure my servers with Chef, not running pip directly.\n\n", "before_files": [{"content": "\"\"\"\nRequirements file parsing\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport os\nimport re\nimport shlex\nimport optparse\nimport warnings\n\nfrom pip._vendor.six.moves.urllib import parse as urllib_parse\nfrom pip._vendor.six.moves import filterfalse\n\nimport pip\nfrom pip.download import get_file_content\nfrom pip.req.req_install import InstallRequirement\nfrom pip.exceptions import (RequirementsFileParseError)\nfrom pip.utils.deprecation import RemovedInPip10Warning\nfrom pip import cmdoptions\n\n__all__ = ['parse_requirements']\n\nSCHEME_RE = re.compile(r'^(http|https|file):', re.I)\nCOMMENT_RE = re.compile(r'(^|\\s)+#.*$')\n\nSUPPORTED_OPTIONS = [\n    cmdoptions.constraints,\n    cmdoptions.editable,\n    cmdoptions.requirements,\n    cmdoptions.no_index,\n    cmdoptions.index_url,\n    cmdoptions.find_links,\n    cmdoptions.extra_index_url,\n    cmdoptions.allow_external,\n    cmdoptions.allow_all_external,\n    cmdoptions.no_allow_external,\n    cmdoptions.allow_unsafe,\n    cmdoptions.no_allow_unsafe,\n    cmdoptions.use_wheel,\n    cmdoptions.no_use_wheel,\n    cmdoptions.always_unzip,\n    cmdoptions.no_binary,\n    cmdoptions.only_binary,\n]\n\n# options to be passed to requirements\nSUPPORTED_OPTIONS_REQ = [\n    cmdoptions.install_options,\n    cmdoptions.global_options\n]\n\n# the 'dest' string values\nSUPPORTED_OPTIONS_REQ_DEST = [o().dest for o in SUPPORTED_OPTIONS_REQ]\n\n\ndef parse_requirements(filename, finder=None, comes_from=None, options=None,\n                       session=None, constraint=False, wheel_cache=None):\n    \"\"\"Parse a requirements file and yield InstallRequirement instances.\n\n    :param filename:    Path or url of requirements file.\n    :param finder:      Instance of pip.index.PackageFinder.\n    :param comes_from:  Origin description of requirements.\n    :param options:     Global options.\n    :param session:     Instance of pip.download.PipSession.\n    :param constraint:  If true, parsing a constraint file rather than\n        requirements file.\n    :param wheel_cache: Instance of pip.wheel.WheelCache\n    \"\"\"\n    if session is None:\n        raise TypeError(\n            \"parse_requirements() missing 1 required keyword argument: \"\n            \"'session'\"\n        )\n\n    _, content = get_file_content(\n        filename, comes_from=comes_from, session=session\n    )\n\n    lines = content.splitlines()\n    lines = ignore_comments(lines)\n    lines = join_lines(lines)\n    lines = skip_regex(lines, options)\n\n    for line_number, line in enumerate(lines, 1):\n        req_iter = process_line(line, filename, line_number, finder,\n                                comes_from, options, session, wheel_cache,\n                                constraint=constraint)\n        for req in req_iter:\n            yield req\n\n\ndef process_line(line, filename, line_number, finder=None, comes_from=None,\n                 options=None, session=None, wheel_cache=None,\n                 constraint=False):\n    \"\"\"Process a single requirements line; This can result in creating/yielding\n    requirements, or updating the finder.\n\n    For lines that contain requirements, the only options that have an effect\n    are from SUPPORTED_OPTIONS_REQ, and they are scoped to the\n    requirement. Other options from SUPPORTED_OPTIONS may be present, but are\n    ignored.\n\n    For lines that do not contain requirements, the only options that have an\n    effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may\n    be present, but are ignored. These lines may contain multiple options\n    (although our docs imply only one is supported), and all our parsed and\n    affect the finder.\n\n    :param constraint: If True, parsing a constraints file.\n    \"\"\"\n    parser = build_parser()\n    defaults = parser.get_default_values()\n    defaults.index_url = None\n    if finder:\n        # `finder.format_control` will be updated during parsing\n        defaults.format_control = finder.format_control\n    args_str, options_str = break_args_options(line)\n    opts, _ = parser.parse_args(shlex.split(options_str), defaults)\n\n    # preserve for the nested code path\n    line_comes_from = '%s %s (line %s)' % (\n        '-c' if constraint else '-r', filename, line_number)\n\n    # yield a line requirement\n    if args_str:\n        isolated = options.isolated_mode if options else False\n        if options:\n            cmdoptions.check_install_build_global(options, opts)\n        # get the options that apply to requirements\n        req_options = {}\n        for dest in SUPPORTED_OPTIONS_REQ_DEST:\n            if dest in opts.__dict__ and opts.__dict__[dest]:\n                req_options[dest] = opts.__dict__[dest]\n        yield InstallRequirement.from_line(\n            args_str, line_comes_from, constraint=constraint,\n            isolated=isolated, options=req_options, wheel_cache=wheel_cache\n        )\n\n    # yield an editable requirement\n    elif opts.editables:\n        isolated = options.isolated_mode if options else False\n        default_vcs = options.default_vcs if options else None\n        yield InstallRequirement.from_editable(\n            opts.editables[0], comes_from=line_comes_from,\n            constraint=constraint, default_vcs=default_vcs, isolated=isolated,\n            wheel_cache=wheel_cache\n        )\n\n    # parse a nested requirements file\n    elif opts.requirements or opts.constraints:\n        if opts.requirements:\n            req_path = opts.requirements[0]\n            nested_constraint = False\n        else:\n            req_path = opts.constraints[0]\n            nested_constraint = True\n        # original file is over http\n        if SCHEME_RE.search(filename):\n            # do a url join so relative paths work\n            req_path = urllib_parse.urljoin(filename, req_path)\n        # original file and nested file are paths\n        elif not SCHEME_RE.search(req_path):\n            # do a join so relative paths work\n            req_dir = os.path.dirname(filename)\n            req_path = os.path.join(os.path.dirname(filename), req_path)\n        # TODO: Why not use `comes_from='-r {} (line {})'` here as well?\n        parser = parse_requirements(\n            req_path, finder, comes_from, options, session,\n            constraint=nested_constraint, wheel_cache=wheel_cache\n        )\n        for req in parser:\n            yield req\n\n    # set finder options\n    elif finder:\n        if opts.allow_external:\n            warnings.warn(\n                \"--allow-external has been deprecated and will be removed in \"\n                \"the future. Due to changes in the repository protocol, it no \"\n                \"longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.allow_all_external:\n            warnings.warn(\n                \"--allow-all-external has been deprecated and will be removed \"\n                \"in the future. Due to changes in the repository protocol, it \"\n                \"no longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.allow_unverified:\n            warnings.warn(\n                \"--allow-unverified has been deprecated and will be removed \"\n                \"in the future. Due to changes in the repository protocol, it \"\n                \"no longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.index_url:\n            finder.index_urls = [opts.index_url]\n        if opts.use_wheel is False:\n            finder.use_wheel = False\n            pip.index.fmt_ctl_no_use_wheel(finder.format_control)\n        if opts.no_index is True:\n            finder.index_urls = []\n        if opts.extra_index_urls:\n            finder.index_urls.extend(opts.extra_index_urls)\n        if opts.find_links:\n            # FIXME: it would be nice to keep track of the source\n            # of the find_links: support a find-links local path\n            # relative to a requirements file.\n            value = opts.find_links[0]\n            req_dir = os.path.dirname(os.path.abspath(filename))\n            relative_to_reqs_file = os.path.join(req_dir, value)\n            if os.path.exists(relative_to_reqs_file):\n                value = relative_to_reqs_file\n            finder.find_links.append(value)\n\n\ndef break_args_options(line):\n    \"\"\"Break up the line into an args and options string.  We only want to shlex\n    (and then optparse) the options, not the args.  args can contain markers\n    which are corrupted by shlex.\n    \"\"\"\n    tokens = line.split(' ')\n    args = []\n    options = tokens[:]\n    for token in tokens:\n        if token.startswith('-') or token.startswith('--'):\n            break\n        else:\n            args.append(token)\n            options.pop(0)\n    return ' '.join(args), ' '.join(options)\n\n\ndef build_parser():\n    \"\"\"\n    Return a parser for parsing requirement lines\n    \"\"\"\n    parser = optparse.OptionParser(add_help_option=False)\n\n    option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ\n    for option_factory in option_factories:\n        option = option_factory()\n        parser.add_option(option)\n\n    # By default optparse sys.exits on parsing errors. We want to wrap\n    # that in our own exception.\n    def parser_exit(self, msg):\n        raise RequirementsFileParseError(msg)\n    parser.exit = parser_exit\n\n    return parser\n\n\ndef join_lines(iterator):\n    \"\"\"\n    Joins a line ending in '\\' with the previous line.\n    \"\"\"\n    lines = []\n    for line in iterator:\n        if not line.endswith('\\\\'):\n            if lines:\n                lines.append(line)\n                yield ''.join(lines)\n                lines = []\n            else:\n                yield line\n        else:\n            lines.append(line.strip('\\\\'))\n\n    # TODO: handle space after '\\'.\n    # TODO: handle '\\' on last line.\n\n\ndef ignore_comments(iterator):\n    \"\"\"\n    Strips and filters empty or commented lines.\n    \"\"\"\n    for line in iterator:\n        line = COMMENT_RE.sub('', line)\n        line = line.strip()\n        if line:\n            yield line\n\n\ndef skip_regex(lines, options):\n    \"\"\"\n    Optionally exclude lines that match '--skip-requirements-regex'\n    \"\"\"\n    skip_regex = options.skip_requirements_regex if options else None\n    if skip_regex:\n        lines = filterfalse(re.compile(skip_regex).search, lines)\n    return lines\n", "path": "pip/req/req_file.py"}], "after_files": [{"content": "\"\"\"\nRequirements file parsing\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport os\nimport re\nimport shlex\nimport optparse\nimport warnings\n\nfrom pip._vendor.six.moves.urllib import parse as urllib_parse\nfrom pip._vendor.six.moves import filterfalse\n\nimport pip\nfrom pip.download import get_file_content\nfrom pip.req.req_install import InstallRequirement\nfrom pip.exceptions import (RequirementsFileParseError)\nfrom pip.utils.deprecation import RemovedInPip10Warning\nfrom pip import cmdoptions\n\n__all__ = ['parse_requirements']\n\nSCHEME_RE = re.compile(r'^(http|https|file):', re.I)\nCOMMENT_RE = re.compile(r'(^|\\s)+#.*$')\n\nSUPPORTED_OPTIONS = [\n    cmdoptions.constraints,\n    cmdoptions.editable,\n    cmdoptions.requirements,\n    cmdoptions.no_index,\n    cmdoptions.index_url,\n    cmdoptions.find_links,\n    cmdoptions.extra_index_url,\n    cmdoptions.allow_external,\n    cmdoptions.allow_all_external,\n    cmdoptions.no_allow_external,\n    cmdoptions.allow_unsafe,\n    cmdoptions.no_allow_unsafe,\n    cmdoptions.use_wheel,\n    cmdoptions.no_use_wheel,\n    cmdoptions.always_unzip,\n    cmdoptions.no_binary,\n    cmdoptions.only_binary,\n    cmdoptions.trusted_host,\n]\n\n# options to be passed to requirements\nSUPPORTED_OPTIONS_REQ = [\n    cmdoptions.install_options,\n    cmdoptions.global_options\n]\n\n# the 'dest' string values\nSUPPORTED_OPTIONS_REQ_DEST = [o().dest for o in SUPPORTED_OPTIONS_REQ]\n\n\ndef parse_requirements(filename, finder=None, comes_from=None, options=None,\n                       session=None, constraint=False, wheel_cache=None):\n    \"\"\"Parse a requirements file and yield InstallRequirement instances.\n\n    :param filename:    Path or url of requirements file.\n    :param finder:      Instance of pip.index.PackageFinder.\n    :param comes_from:  Origin description of requirements.\n    :param options:     Global options.\n    :param session:     Instance of pip.download.PipSession.\n    :param constraint:  If true, parsing a constraint file rather than\n        requirements file.\n    :param wheel_cache: Instance of pip.wheel.WheelCache\n    \"\"\"\n    if session is None:\n        raise TypeError(\n            \"parse_requirements() missing 1 required keyword argument: \"\n            \"'session'\"\n        )\n\n    _, content = get_file_content(\n        filename, comes_from=comes_from, session=session\n    )\n\n    lines = content.splitlines()\n    lines = ignore_comments(lines)\n    lines = join_lines(lines)\n    lines = skip_regex(lines, options)\n\n    for line_number, line in enumerate(lines, 1):\n        req_iter = process_line(line, filename, line_number, finder,\n                                comes_from, options, session, wheel_cache,\n                                constraint=constraint)\n        for req in req_iter:\n            yield req\n\n\ndef process_line(line, filename, line_number, finder=None, comes_from=None,\n                 options=None, session=None, wheel_cache=None,\n                 constraint=False):\n    \"\"\"Process a single requirements line; This can result in creating/yielding\n    requirements, or updating the finder.\n\n    For lines that contain requirements, the only options that have an effect\n    are from SUPPORTED_OPTIONS_REQ, and they are scoped to the\n    requirement. Other options from SUPPORTED_OPTIONS may be present, but are\n    ignored.\n\n    For lines that do not contain requirements, the only options that have an\n    effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may\n    be present, but are ignored. These lines may contain multiple options\n    (although our docs imply only one is supported), and all our parsed and\n    affect the finder.\n\n    :param constraint: If True, parsing a constraints file.\n    \"\"\"\n    parser = build_parser()\n    defaults = parser.get_default_values()\n    defaults.index_url = None\n    if finder:\n        # `finder.format_control` will be updated during parsing\n        defaults.format_control = finder.format_control\n    args_str, options_str = break_args_options(line)\n    opts, _ = parser.parse_args(shlex.split(options_str), defaults)\n\n    # preserve for the nested code path\n    line_comes_from = '%s %s (line %s)' % (\n        '-c' if constraint else '-r', filename, line_number)\n\n    # yield a line requirement\n    if args_str:\n        isolated = options.isolated_mode if options else False\n        if options:\n            cmdoptions.check_install_build_global(options, opts)\n        # get the options that apply to requirements\n        req_options = {}\n        for dest in SUPPORTED_OPTIONS_REQ_DEST:\n            if dest in opts.__dict__ and opts.__dict__[dest]:\n                req_options[dest] = opts.__dict__[dest]\n        yield InstallRequirement.from_line(\n            args_str, line_comes_from, constraint=constraint,\n            isolated=isolated, options=req_options, wheel_cache=wheel_cache\n        )\n\n    # yield an editable requirement\n    elif opts.editables:\n        isolated = options.isolated_mode if options else False\n        default_vcs = options.default_vcs if options else None\n        yield InstallRequirement.from_editable(\n            opts.editables[0], comes_from=line_comes_from,\n            constraint=constraint, default_vcs=default_vcs, isolated=isolated,\n            wheel_cache=wheel_cache\n        )\n\n    # parse a nested requirements file\n    elif opts.requirements or opts.constraints:\n        if opts.requirements:\n            req_path = opts.requirements[0]\n            nested_constraint = False\n        else:\n            req_path = opts.constraints[0]\n            nested_constraint = True\n        # original file is over http\n        if SCHEME_RE.search(filename):\n            # do a url join so relative paths work\n            req_path = urllib_parse.urljoin(filename, req_path)\n        # original file and nested file are paths\n        elif not SCHEME_RE.search(req_path):\n            # do a join so relative paths work\n            req_dir = os.path.dirname(filename)\n            req_path = os.path.join(os.path.dirname(filename), req_path)\n        # TODO: Why not use `comes_from='-r {} (line {})'` here as well?\n        parser = parse_requirements(\n            req_path, finder, comes_from, options, session,\n            constraint=nested_constraint, wheel_cache=wheel_cache\n        )\n        for req in parser:\n            yield req\n\n    # set finder options\n    elif finder:\n        if opts.allow_external:\n            warnings.warn(\n                \"--allow-external has been deprecated and will be removed in \"\n                \"the future. Due to changes in the repository protocol, it no \"\n                \"longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.allow_all_external:\n            warnings.warn(\n                \"--allow-all-external has been deprecated and will be removed \"\n                \"in the future. Due to changes in the repository protocol, it \"\n                \"no longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.allow_unverified:\n            warnings.warn(\n                \"--allow-unverified has been deprecated and will be removed \"\n                \"in the future. Due to changes in the repository protocol, it \"\n                \"no longer has any effect.\",\n                RemovedInPip10Warning,\n            )\n\n        if opts.index_url:\n            finder.index_urls = [opts.index_url]\n        if opts.use_wheel is False:\n            finder.use_wheel = False\n            pip.index.fmt_ctl_no_use_wheel(finder.format_control)\n        if opts.no_index is True:\n            finder.index_urls = []\n        if opts.extra_index_urls:\n            finder.index_urls.extend(opts.extra_index_urls)\n        if opts.find_links:\n            # FIXME: it would be nice to keep track of the source\n            # of the find_links: support a find-links local path\n            # relative to a requirements file.\n            value = opts.find_links[0]\n            req_dir = os.path.dirname(os.path.abspath(filename))\n            relative_to_reqs_file = os.path.join(req_dir, value)\n            if os.path.exists(relative_to_reqs_file):\n                value = relative_to_reqs_file\n            finder.find_links.append(value)\n        if opts.trusted_hosts:\n            finder.secure_origins.extend(\n                (\"*\", host, \"*\") for host in opts.trusted_hosts)\n\n\ndef break_args_options(line):\n    \"\"\"Break up the line into an args and options string.  We only want to shlex\n    (and then optparse) the options, not the args.  args can contain markers\n    which are corrupted by shlex.\n    \"\"\"\n    tokens = line.split(' ')\n    args = []\n    options = tokens[:]\n    for token in tokens:\n        if token.startswith('-') or token.startswith('--'):\n            break\n        else:\n            args.append(token)\n            options.pop(0)\n    return ' '.join(args), ' '.join(options)\n\n\ndef build_parser():\n    \"\"\"\n    Return a parser for parsing requirement lines\n    \"\"\"\n    parser = optparse.OptionParser(add_help_option=False)\n\n    option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ\n    for option_factory in option_factories:\n        option = option_factory()\n        parser.add_option(option)\n\n    # By default optparse sys.exits on parsing errors. We want to wrap\n    # that in our own exception.\n    def parser_exit(self, msg):\n        raise RequirementsFileParseError(msg)\n    parser.exit = parser_exit\n\n    return parser\n\n\ndef join_lines(iterator):\n    \"\"\"\n    Joins a line ending in '\\' with the previous line.\n    \"\"\"\n    lines = []\n    for line in iterator:\n        if not line.endswith('\\\\'):\n            if lines:\n                lines.append(line)\n                yield ''.join(lines)\n                lines = []\n            else:\n                yield line\n        else:\n            lines.append(line.strip('\\\\'))\n\n    # TODO: handle space after '\\'.\n    # TODO: handle '\\' on last line.\n\n\ndef ignore_comments(iterator):\n    \"\"\"\n    Strips and filters empty or commented lines.\n    \"\"\"\n    for line in iterator:\n        line = COMMENT_RE.sub('', line)\n        line = line.strip()\n        if line:\n            yield line\n\n\ndef skip_regex(lines, options):\n    \"\"\"\n    Optionally exclude lines that match '--skip-requirements-regex'\n    \"\"\"\n    skip_regex = options.skip_requirements_regex if options else None\n    if skip_regex:\n        lines = filterfalse(re.compile(skip_regex).search, lines)\n    return lines\n", "path": "pip/req/req_file.py"}]}