We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Providing a source file which does not have an extension writes to a .txt file in current dir
If you happen to use an extensionless filename as a source of requirements in, pip-compile will deduce the wrong output filename and generate a ".txt" file (relative file, thus at current working dir).

##### Environment Versions

1. OS Type Should be cross platform, but observed on Windows
1. Python version: `$ python -V` 2.7.8
1. pip version:  `$ pip --version` 9.0.1
1. pip-tools version: `$ pip-compile --version` 1.8.1rc2

##### Steps to replicate

1. echo "request" > no_extension
2. pip-compile no_extension

##### Expected result

We should error out because it is difficult to deduce a new name if there is no extension to remove.

##### Actual result

a .txt file is generated at the current directory.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `piptools/scripts/compile.py`
Content:
```
1 # coding: utf-8
2 from __future__ import (absolute_import, division, print_function,
3                         unicode_literals)
4 
5 import optparse
6 import os
7 import sys
8 import tempfile
9 
10 import pip
11 from pip.req import InstallRequirement, parse_requirements
12 
13 from .. import click
14 from ..exceptions import PipToolsError
15 from ..logging import log
16 from ..repositories import LocalRequirementsRepository, PyPIRepository
17 from ..resolver import Resolver
18 from ..utils import (assert_compatible_pip_version, is_pinned_requirement,
19                      key_from_req, dedup)
20 from ..writer import OutputWriter
21 
22 # Make sure we're using a compatible version of pip
23 assert_compatible_pip_version()
24 
25 DEFAULT_REQUIREMENTS_FILE = 'requirements.in'
26 
27 
28 class PipCommand(pip.basecommand.Command):
29     name = 'PipCommand'
30 
31 
32 @click.command()
33 @click.version_option()
34 @click.option('-v', '--verbose', is_flag=True, help="Show more output")
35 @click.option('-n', '--dry-run', is_flag=True, help="Only show what would happen, don't change anything")
36 @click.option('-p', '--pre', is_flag=True, default=None, help="Allow resolving to prereleases (default is not)")
37 @click.option('-r', '--rebuild', is_flag=True, help="Clear any caches upfront, rebuild from scratch")
38 @click.option('-f', '--find-links', multiple=True, help="Look for archives in this directory or on this HTML page", envvar='PIP_FIND_LINKS')  # noqa
39 @click.option('-i', '--index-url', help="Change index URL (defaults to PyPI)", envvar='PIP_INDEX_URL')
40 @click.option('--extra-index-url', multiple=True, help="Add additional index URL to search", envvar='PIP_EXTRA_INDEX_URL')  # noqa
41 @click.option('--client-cert', help="Path to SSL client certificate, a single file containing the private key and the certificate in PEM format.")  # noqa
42 @click.option('--trusted-host', multiple=True, envvar='PIP_TRUSTED_HOST',
43               help="Mark this host as trusted, even though it does not have "
44                    "valid or any HTTPS.")
45 @click.option('--header/--no-header', is_flag=True, default=True,
46               help="Add header to generated file")
47 @click.option('--index/--no-index', is_flag=True, default=True,
48               help="Add index URL to generated file")
49 @click.option('--emit-trusted-host/--no-emit-trusted-host', is_flag=True,
50               default=True, help="Add trusted host option to generated file")
51 @click.option('--annotate/--no-annotate', is_flag=True, default=True,
52               help="Annotate results, indicating where dependencies come from")
53 @click.option('-U', '--upgrade', is_flag=True, default=False,
54               help='Try to upgrade all dependencies to their latest versions')
55 @click.option('-P', '--upgrade-package', 'upgrade_packages', nargs=1, multiple=True,
56               help="Specify particular packages to upgrade.")
57 @click.option('-o', '--output-file', nargs=1, type=str, default=None,
58               help=('Output file name. Required if more than one input file is given. '
59                     'Will be derived from input file otherwise.'))
60 @click.option('--allow-unsafe', is_flag=True, default=False,
61               help="Pin packages considered unsafe: pip, setuptools & distribute")
62 @click.option('--generate-hashes', is_flag=True, default=False,
63               help="Generate pip 8 style hashes in the resulting requirements file.")
64 @click.option('--max-rounds', default=10,
65               help="Maximum number of rounds before resolving the requirements aborts.")
66 @click.argument('src_files', nargs=-1, type=click.Path(exists=True, allow_dash=True))
67 def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,
68         client_cert, trusted_host, header, index, emit_trusted_host, annotate,
69         upgrade, upgrade_packages, output_file, allow_unsafe, generate_hashes,
70         src_files, max_rounds):
71     """Compiles requirements.txt from requirements.in specs."""
72     log.verbose = verbose
73 
74     if len(src_files) == 0:
75         if os.path.exists(DEFAULT_REQUIREMENTS_FILE):
76             src_files = (DEFAULT_REQUIREMENTS_FILE,)
77         elif os.path.exists('setup.py'):
78             src_files = ('setup.py',)
79             if not output_file:
80                 output_file = 'requirements.txt'
81         else:
82             raise click.BadParameter(("If you do not specify an input file, "
83                                       "the default is {} or setup.py").format(DEFAULT_REQUIREMENTS_FILE))
84 
85     if len(src_files) == 1 and src_files[0] == '-':
86         if not output_file:
87             raise click.BadParameter('--output-file is required if input is from stdin')
88 
89     if len(src_files) > 1 and not output_file:
90         raise click.BadParameter('--output-file is required if two or more input files are given.')
91 
92     if output_file:
93         dst_file = output_file
94     else:
95         base_name, _, _ = src_files[0].rpartition('.')
96         dst_file = base_name + '.txt'
97 
98     if upgrade and upgrade_packages:
99         raise click.BadParameter('Only one of --upgrade or --upgrade-package can be provided as an argument.')
100 
101     ###
102     # Setup
103     ###
104 
105     pip_command = get_pip_command()
106 
107     pip_args = []
108     if find_links:
109         for link in find_links:
110             pip_args.extend(['-f', link])
111     if index_url:
112         pip_args.extend(['-i', index_url])
113     if extra_index_url:
114         for extra_index in extra_index_url:
115             pip_args.extend(['--extra-index-url', extra_index])
116     if client_cert:
117         pip_args.extend(['--client-cert', client_cert])
118     if pre:
119         pip_args.extend(['--pre'])
120     if trusted_host:
121         for host in trusted_host:
122             pip_args.extend(['--trusted-host', host])
123 
124     pip_options, _ = pip_command.parse_args(pip_args)
125 
126     session = pip_command._build_session(pip_options)
127     repository = PyPIRepository(pip_options, session)
128 
129     # Pre-parse the inline package upgrade specs: they should take precedence
130     # over the stuff in the requirements files
131     upgrade_packages = [InstallRequirement.from_line(pkg)
132                         for pkg in upgrade_packages]
133 
134     # Proxy with a LocalRequirementsRepository if --upgrade is not specified
135     # (= default invocation)
136     if not (upgrade or upgrade_packages) and os.path.exists(dst_file):
137         ireqs = parse_requirements(dst_file, finder=repository.finder, session=repository.session, options=pip_options)
138         existing_pins = {key_from_req(ireq.req): ireq for ireq in ireqs if is_pinned_requirement(ireq)}
139         repository = LocalRequirementsRepository(existing_pins, repository)
140 
141     log.debug('Using indexes:')
142     # remove duplicate index urls before processing
143     repository.finder.index_urls = list(dedup(repository.finder.index_urls))
144     for index_url in repository.finder.index_urls:
145         log.debug('  {}'.format(index_url))
146 
147     if repository.finder.find_links:
148         log.debug('')
149         log.debug('Configuration:')
150         for find_link in repository.finder.find_links:
151             log.debug('  -f {}'.format(find_link))
152 
153     ###
154     # Parsing/collecting initial requirements
155     ###
156 
157     constraints = []
158     for src_file in src_files:
159         is_setup_file = os.path.basename(src_file) == 'setup.py'
160         if is_setup_file or src_file == '-':
161             # pip requires filenames and not files. Since we want to support
162             # piping from stdin, we need to briefly save the input from stdin
163             # to a temporary file and have pip read that.  also used for
164             # reading requirements from install_requires in setup.py.
165             tmpfile = tempfile.NamedTemporaryFile(mode='wt', delete=False)
166             if is_setup_file:
167                 from distutils.core import run_setup
168                 dist = run_setup(src_file)
169                 tmpfile.write('\n'.join(dist.install_requires))
170             else:
171                 tmpfile.write(sys.stdin.read())
172             tmpfile.flush()
173             constraints.extend(parse_requirements(
174                 tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options))
175         else:
176             constraints.extend(parse_requirements(
177                 src_file, finder=repository.finder, session=repository.session, options=pip_options))
178 
179     # Check the given base set of constraints first
180     Resolver.check_constraints(constraints)
181 
182     try:
183         resolver = Resolver(constraints, repository, prereleases=pre,
184                             clear_caches=rebuild, allow_unsafe=allow_unsafe)
185         results = resolver.resolve(max_rounds=max_rounds)
186         if generate_hashes:
187             hashes = resolver.resolve_hashes(results)
188         else:
189             hashes = None
190     except PipToolsError as e:
191         log.error(str(e))
192         sys.exit(2)
193 
194     log.debug('')
195 
196     ##
197     # Output
198     ##
199 
200     # Compute reverse dependency annotations statically, from the
201     # dependency cache that the resolver has populated by now.
202     #
203     # TODO (1a): reverse deps for any editable package are lost
204     #            what SHOULD happen is that they are cached in memory, just
205     #            not persisted to disk!
206     #
207     # TODO (1b): perhaps it's easiest if the dependency cache has an API
208     #            that could take InstallRequirements directly, like:
209     #
210     #                cache.set(ireq, ...)
211     #
212     #            then, when ireq is editable, it would store in
213     #
214     #              editables[egg_name][link_without_fragment] = deps
215     #              editables['pip-tools']['git+...ols.git@future'] = {'click>=3.0', 'six'}
216     #
217     #            otherwise:
218     #
219     #              self[as_name_version_tuple(ireq)] = {'click>=3.0', 'six'}
220     #
221     reverse_dependencies = None
222     if annotate:
223         reverse_dependencies = resolver.reverse_dependencies(results)
224 
225     writer = OutputWriter(src_files, dst_file, dry_run=dry_run,
226                           emit_header=header, emit_index=index,
227                           emit_trusted_host=emit_trusted_host,
228                           annotate=annotate,
229                           generate_hashes=generate_hashes,
230                           default_index_url=repository.DEFAULT_INDEX_URL,
231                           index_urls=repository.finder.index_urls,
232                           trusted_hosts=pip_options.trusted_hosts,
233                           format_control=repository.finder.format_control)
234     writer.write(results=results,
235                  reverse_dependencies=reverse_dependencies,
236                  primary_packages={key_from_req(ireq.req) for ireq in constraints if not ireq.constraint},
237                  markers={key_from_req(ireq.req): ireq.markers
238                           for ireq in constraints if ireq.markers},
239                  hashes=hashes)
240 
241     if dry_run:
242         log.warning('Dry-run, so nothing updated.')
243 
244 
245 def get_pip_command():
246     # Use pip's parser for pip.conf management and defaults.
247     # General options (find_links, index_url, extra_index_url, trusted_host,
248     # and pre) are defered to pip.
249     pip_command = PipCommand()
250     index_opts = pip.cmdoptions.make_option_group(
251         pip.cmdoptions.index_group,
252         pip_command.parser,
253     )
254     pip_command.parser.insert_option_group(0, index_opts)
255     pip_command.parser.add_option(optparse.Option('--pre', action='store_true', default=False))
256 
257     return pip_command
258
```
--- 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/piptools/scripts/compile.py b/piptools/scripts/compile.py
--- a/piptools/scripts/compile.py
+++ b/piptools/scripts/compile.py
@@ -92,7 +92,7 @@
     if output_file:
         dst_file = output_file
     else:
-        base_name, _, _ = src_files[0].rpartition('.')
+        base_name = src_files[0].rsplit('.', 1)[0]
         dst_file = base_name + '.txt'
 
     if upgrade and upgrade_packages:

{"golden_diff": "diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py\n--- a/piptools/scripts/compile.py\n+++ b/piptools/scripts/compile.py\n@@ -92,7 +92,7 @@\n     if output_file:\n         dst_file = output_file\n     else:\n-        base_name, _, _ = src_files[0].rpartition('.')\n+        base_name = src_files[0].rsplit('.', 1)[0]\n         dst_file = base_name + '.txt'\n \n     if upgrade and upgrade_packages:\n", "issue": "Providing a source file which does not have an extension writes to a .txt file in current dir\nIf you happen to use an extensionless filename as a source of requirements in, pip-compile will deduce the wrong output filename and generate a \".txt\" file (relative file, thus at current working dir).\r\n\r\n##### Environment Versions\r\n\r\n1. OS Type Should be cross platform, but observed on Windows\r\n1. Python version: `$ python -V` 2.7.8\r\n1. pip version:  `$ pip --version` 9.0.1\r\n1. pip-tools version: `$ pip-compile --version` 1.8.1rc2\r\n\r\n##### Steps to replicate\r\n\r\n1. echo \"request\" > no_extension\r\n2. pip-compile no_extension\r\n\r\n##### Expected result\r\n\r\nWe should error out because it is difficult to deduce a new name if there is no extension to remove.\r\n\r\n##### Actual result\r\n\r\na .txt file is generated at the current directory.\r\n\n", "before_files": [{"content": "# coding: utf-8\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport optparse\nimport os\nimport sys\nimport tempfile\n\nimport pip\nfrom pip.req import InstallRequirement, parse_requirements\n\nfrom .. import click\nfrom ..exceptions import PipToolsError\nfrom ..logging import log\nfrom ..repositories import LocalRequirementsRepository, PyPIRepository\nfrom ..resolver import Resolver\nfrom ..utils import (assert_compatible_pip_version, is_pinned_requirement,\n                     key_from_req, dedup)\nfrom ..writer import OutputWriter\n\n# Make sure we're using a compatible version of pip\nassert_compatible_pip_version()\n\nDEFAULT_REQUIREMENTS_FILE = 'requirements.in'\n\n\nclass PipCommand(pip.basecommand.Command):\n    name = 'PipCommand'\n\n\n@click.command()\n@click.version_option()\n@click.option('-v', '--verbose', is_flag=True, help=\"Show more output\")\n@click.option('-n', '--dry-run', is_flag=True, help=\"Only show what would happen, don't change anything\")\n@click.option('-p', '--pre', is_flag=True, default=None, help=\"Allow resolving to prereleases (default is not)\")\n@click.option('-r', '--rebuild', is_flag=True, help=\"Clear any caches upfront, rebuild from scratch\")\n@click.option('-f', '--find-links', multiple=True, help=\"Look for archives in this directory or on this HTML page\", envvar='PIP_FIND_LINKS')  # noqa\n@click.option('-i', '--index-url', help=\"Change index URL (defaults to PyPI)\", envvar='PIP_INDEX_URL')\n@click.option('--extra-index-url', multiple=True, help=\"Add additional index URL to search\", envvar='PIP_EXTRA_INDEX_URL')  # noqa\n@click.option('--client-cert', help=\"Path to SSL client certificate, a single file containing the private key and the certificate in PEM format.\")  # noqa\n@click.option('--trusted-host', multiple=True, envvar='PIP_TRUSTED_HOST',\n              help=\"Mark this host as trusted, even though it does not have \"\n                   \"valid or any HTTPS.\")\n@click.option('--header/--no-header', is_flag=True, default=True,\n              help=\"Add header to generated file\")\n@click.option('--index/--no-index', is_flag=True, default=True,\n              help=\"Add index URL to generated file\")\n@click.option('--emit-trusted-host/--no-emit-trusted-host', is_flag=True,\n              default=True, help=\"Add trusted host option to generated file\")\n@click.option('--annotate/--no-annotate', is_flag=True, default=True,\n              help=\"Annotate results, indicating where dependencies come from\")\n@click.option('-U', '--upgrade', is_flag=True, default=False,\n              help='Try to upgrade all dependencies to their latest versions')\n@click.option('-P', '--upgrade-package', 'upgrade_packages', nargs=1, multiple=True,\n              help=\"Specify particular packages to upgrade.\")\n@click.option('-o', '--output-file', nargs=1, type=str, default=None,\n              help=('Output file name. Required if more than one input file is given. '\n                    'Will be derived from input file otherwise.'))\n@click.option('--allow-unsafe', is_flag=True, default=False,\n              help=\"Pin packages considered unsafe: pip, setuptools & distribute\")\n@click.option('--generate-hashes', is_flag=True, default=False,\n              help=\"Generate pip 8 style hashes in the resulting requirements file.\")\n@click.option('--max-rounds', default=10,\n              help=\"Maximum number of rounds before resolving the requirements aborts.\")\n@click.argument('src_files', nargs=-1, type=click.Path(exists=True, allow_dash=True))\ndef cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,\n        client_cert, trusted_host, header, index, emit_trusted_host, annotate,\n        upgrade, upgrade_packages, output_file, allow_unsafe, generate_hashes,\n        src_files, max_rounds):\n    \"\"\"Compiles requirements.txt from requirements.in specs.\"\"\"\n    log.verbose = verbose\n\n    if len(src_files) == 0:\n        if os.path.exists(DEFAULT_REQUIREMENTS_FILE):\n            src_files = (DEFAULT_REQUIREMENTS_FILE,)\n        elif os.path.exists('setup.py'):\n            src_files = ('setup.py',)\n            if not output_file:\n                output_file = 'requirements.txt'\n        else:\n            raise click.BadParameter((\"If you do not specify an input file, \"\n                                      \"the default is {} or setup.py\").format(DEFAULT_REQUIREMENTS_FILE))\n\n    if len(src_files) == 1 and src_files[0] == '-':\n        if not output_file:\n            raise click.BadParameter('--output-file is required if input is from stdin')\n\n    if len(src_files) > 1 and not output_file:\n        raise click.BadParameter('--output-file is required if two or more input files are given.')\n\n    if output_file:\n        dst_file = output_file\n    else:\n        base_name, _, _ = src_files[0].rpartition('.')\n        dst_file = base_name + '.txt'\n\n    if upgrade and upgrade_packages:\n        raise click.BadParameter('Only one of --upgrade or --upgrade-package can be provided as an argument.')\n\n    ###\n    # Setup\n    ###\n\n    pip_command = get_pip_command()\n\n    pip_args = []\n    if find_links:\n        for link in find_links:\n            pip_args.extend(['-f', link])\n    if index_url:\n        pip_args.extend(['-i', index_url])\n    if extra_index_url:\n        for extra_index in extra_index_url:\n            pip_args.extend(['--extra-index-url', extra_index])\n    if client_cert:\n        pip_args.extend(['--client-cert', client_cert])\n    if pre:\n        pip_args.extend(['--pre'])\n    if trusted_host:\n        for host in trusted_host:\n            pip_args.extend(['--trusted-host', host])\n\n    pip_options, _ = pip_command.parse_args(pip_args)\n\n    session = pip_command._build_session(pip_options)\n    repository = PyPIRepository(pip_options, session)\n\n    # Pre-parse the inline package upgrade specs: they should take precedence\n    # over the stuff in the requirements files\n    upgrade_packages = [InstallRequirement.from_line(pkg)\n                        for pkg in upgrade_packages]\n\n    # Proxy with a LocalRequirementsRepository if --upgrade is not specified\n    # (= default invocation)\n    if not (upgrade or upgrade_packages) and os.path.exists(dst_file):\n        ireqs = parse_requirements(dst_file, finder=repository.finder, session=repository.session, options=pip_options)\n        existing_pins = {key_from_req(ireq.req): ireq for ireq in ireqs if is_pinned_requirement(ireq)}\n        repository = LocalRequirementsRepository(existing_pins, repository)\n\n    log.debug('Using indexes:')\n    # remove duplicate index urls before processing\n    repository.finder.index_urls = list(dedup(repository.finder.index_urls))\n    for index_url in repository.finder.index_urls:\n        log.debug('  {}'.format(index_url))\n\n    if repository.finder.find_links:\n        log.debug('')\n        log.debug('Configuration:')\n        for find_link in repository.finder.find_links:\n            log.debug('  -f {}'.format(find_link))\n\n    ###\n    # Parsing/collecting initial requirements\n    ###\n\n    constraints = []\n    for src_file in src_files:\n        is_setup_file = os.path.basename(src_file) == 'setup.py'\n        if is_setup_file or src_file == '-':\n            # pip requires filenames and not files. Since we want to support\n            # piping from stdin, we need to briefly save the input from stdin\n            # to a temporary file and have pip read that.  also used for\n            # reading requirements from install_requires in setup.py.\n            tmpfile = tempfile.NamedTemporaryFile(mode='wt', delete=False)\n            if is_setup_file:\n                from distutils.core import run_setup\n                dist = run_setup(src_file)\n                tmpfile.write('\\n'.join(dist.install_requires))\n            else:\n                tmpfile.write(sys.stdin.read())\n            tmpfile.flush()\n            constraints.extend(parse_requirements(\n                tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options))\n        else:\n            constraints.extend(parse_requirements(\n                src_file, finder=repository.finder, session=repository.session, options=pip_options))\n\n    # Check the given base set of constraints first\n    Resolver.check_constraints(constraints)\n\n    try:\n        resolver = Resolver(constraints, repository, prereleases=pre,\n                            clear_caches=rebuild, allow_unsafe=allow_unsafe)\n        results = resolver.resolve(max_rounds=max_rounds)\n        if generate_hashes:\n            hashes = resolver.resolve_hashes(results)\n        else:\n            hashes = None\n    except PipToolsError as e:\n        log.error(str(e))\n        sys.exit(2)\n\n    log.debug('')\n\n    ##\n    # Output\n    ##\n\n    # Compute reverse dependency annotations statically, from the\n    # dependency cache that the resolver has populated by now.\n    #\n    # TODO (1a): reverse deps for any editable package are lost\n    #            what SHOULD happen is that they are cached in memory, just\n    #            not persisted to disk!\n    #\n    # TODO (1b): perhaps it's easiest if the dependency cache has an API\n    #            that could take InstallRequirements directly, like:\n    #\n    #                cache.set(ireq, ...)\n    #\n    #            then, when ireq is editable, it would store in\n    #\n    #              editables[egg_name][link_without_fragment] = deps\n    #              editables['pip-tools']['git+...ols.git@future'] = {'click>=3.0', 'six'}\n    #\n    #            otherwise:\n    #\n    #              self[as_name_version_tuple(ireq)] = {'click>=3.0', 'six'}\n    #\n    reverse_dependencies = None\n    if annotate:\n        reverse_dependencies = resolver.reverse_dependencies(results)\n\n    writer = OutputWriter(src_files, dst_file, dry_run=dry_run,\n                          emit_header=header, emit_index=index,\n                          emit_trusted_host=emit_trusted_host,\n                          annotate=annotate,\n                          generate_hashes=generate_hashes,\n                          default_index_url=repository.DEFAULT_INDEX_URL,\n                          index_urls=repository.finder.index_urls,\n                          trusted_hosts=pip_options.trusted_hosts,\n                          format_control=repository.finder.format_control)\n    writer.write(results=results,\n                 reverse_dependencies=reverse_dependencies,\n                 primary_packages={key_from_req(ireq.req) for ireq in constraints if not ireq.constraint},\n                 markers={key_from_req(ireq.req): ireq.markers\n                          for ireq in constraints if ireq.markers},\n                 hashes=hashes)\n\n    if dry_run:\n        log.warning('Dry-run, so nothing updated.')\n\n\ndef get_pip_command():\n    # Use pip's parser for pip.conf management and defaults.\n    # General options (find_links, index_url, extra_index_url, trusted_host,\n    # and pre) are defered to pip.\n    pip_command = PipCommand()\n    index_opts = pip.cmdoptions.make_option_group(\n        pip.cmdoptions.index_group,\n        pip_command.parser,\n    )\n    pip_command.parser.insert_option_group(0, index_opts)\n    pip_command.parser.add_option(optparse.Option('--pre', action='store_true', default=False))\n\n    return pip_command\n", "path": "piptools/scripts/compile.py"}], "after_files": [{"content": "# coding: utf-8\nfrom __future__ import (absolute_import, division, print_function,\n                        unicode_literals)\n\nimport optparse\nimport os\nimport sys\nimport tempfile\n\nimport pip\nfrom pip.req import InstallRequirement, parse_requirements\n\nfrom .. import click\nfrom ..exceptions import PipToolsError\nfrom ..logging import log\nfrom ..repositories import LocalRequirementsRepository, PyPIRepository\nfrom ..resolver import Resolver\nfrom ..utils import (assert_compatible_pip_version, is_pinned_requirement,\n                     key_from_req, dedup)\nfrom ..writer import OutputWriter\n\n# Make sure we're using a compatible version of pip\nassert_compatible_pip_version()\n\nDEFAULT_REQUIREMENTS_FILE = 'requirements.in'\n\n\nclass PipCommand(pip.basecommand.Command):\n    name = 'PipCommand'\n\n\n@click.command()\n@click.version_option()\n@click.option('-v', '--verbose', is_flag=True, help=\"Show more output\")\n@click.option('-n', '--dry-run', is_flag=True, help=\"Only show what would happen, don't change anything\")\n@click.option('-p', '--pre', is_flag=True, default=None, help=\"Allow resolving to prereleases (default is not)\")\n@click.option('-r', '--rebuild', is_flag=True, help=\"Clear any caches upfront, rebuild from scratch\")\n@click.option('-f', '--find-links', multiple=True, help=\"Look for archives in this directory or on this HTML page\", envvar='PIP_FIND_LINKS')  # noqa\n@click.option('-i', '--index-url', help=\"Change index URL (defaults to PyPI)\", envvar='PIP_INDEX_URL')\n@click.option('--extra-index-url', multiple=True, help=\"Add additional index URL to search\", envvar='PIP_EXTRA_INDEX_URL')  # noqa\n@click.option('--client-cert', help=\"Path to SSL client certificate, a single file containing the private key and the certificate in PEM format.\")  # noqa\n@click.option('--trusted-host', multiple=True, envvar='PIP_TRUSTED_HOST',\n              help=\"Mark this host as trusted, even though it does not have \"\n                   \"valid or any HTTPS.\")\n@click.option('--header/--no-header', is_flag=True, default=True,\n              help=\"Add header to generated file\")\n@click.option('--index/--no-index', is_flag=True, default=True,\n              help=\"Add index URL to generated file\")\n@click.option('--emit-trusted-host/--no-emit-trusted-host', is_flag=True,\n              default=True, help=\"Add trusted host option to generated file\")\n@click.option('--annotate/--no-annotate', is_flag=True, default=True,\n              help=\"Annotate results, indicating where dependencies come from\")\n@click.option('-U', '--upgrade', is_flag=True, default=False,\n              help='Try to upgrade all dependencies to their latest versions')\n@click.option('-P', '--upgrade-package', 'upgrade_packages', nargs=1, multiple=True,\n              help=\"Specify particular packages to upgrade.\")\n@click.option('-o', '--output-file', nargs=1, type=str, default=None,\n              help=('Output file name. Required if more than one input file is given. '\n                    'Will be derived from input file otherwise.'))\n@click.option('--allow-unsafe', is_flag=True, default=False,\n              help=\"Pin packages considered unsafe: pip, setuptools & distribute\")\n@click.option('--generate-hashes', is_flag=True, default=False,\n              help=\"Generate pip 8 style hashes in the resulting requirements file.\")\n@click.option('--max-rounds', default=10,\n              help=\"Maximum number of rounds before resolving the requirements aborts.\")\n@click.argument('src_files', nargs=-1, type=click.Path(exists=True, allow_dash=True))\ndef cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,\n        client_cert, trusted_host, header, index, emit_trusted_host, annotate,\n        upgrade, upgrade_packages, output_file, allow_unsafe, generate_hashes,\n        src_files, max_rounds):\n    \"\"\"Compiles requirements.txt from requirements.in specs.\"\"\"\n    log.verbose = verbose\n\n    if len(src_files) == 0:\n        if os.path.exists(DEFAULT_REQUIREMENTS_FILE):\n            src_files = (DEFAULT_REQUIREMENTS_FILE,)\n        elif os.path.exists('setup.py'):\n            src_files = ('setup.py',)\n            if not output_file:\n                output_file = 'requirements.txt'\n        else:\n            raise click.BadParameter((\"If you do not specify an input file, \"\n                                      \"the default is {} or setup.py\").format(DEFAULT_REQUIREMENTS_FILE))\n\n    if len(src_files) == 1 and src_files[0] == '-':\n        if not output_file:\n            raise click.BadParameter('--output-file is required if input is from stdin')\n\n    if len(src_files) > 1 and not output_file:\n        raise click.BadParameter('--output-file is required if two or more input files are given.')\n\n    if output_file:\n        dst_file = output_file\n    else:\n        base_name = src_files[0].rsplit('.', 1)[0]\n        dst_file = base_name + '.txt'\n\n    if upgrade and upgrade_packages:\n        raise click.BadParameter('Only one of --upgrade or --upgrade-package can be provided as an argument.')\n\n    ###\n    # Setup\n    ###\n\n    pip_command = get_pip_command()\n\n    pip_args = []\n    if find_links:\n        for link in find_links:\n            pip_args.extend(['-f', link])\n    if index_url:\n        pip_args.extend(['-i', index_url])\n    if extra_index_url:\n        for extra_index in extra_index_url:\n            pip_args.extend(['--extra-index-url', extra_index])\n    if client_cert:\n        pip_args.extend(['--client-cert', client_cert])\n    if pre:\n        pip_args.extend(['--pre'])\n    if trusted_host:\n        for host in trusted_host:\n            pip_args.extend(['--trusted-host', host])\n\n    pip_options, _ = pip_command.parse_args(pip_args)\n\n    session = pip_command._build_session(pip_options)\n    repository = PyPIRepository(pip_options, session)\n\n    # Pre-parse the inline package upgrade specs: they should take precedence\n    # over the stuff in the requirements files\n    upgrade_packages = [InstallRequirement.from_line(pkg)\n                        for pkg in upgrade_packages]\n\n    # Proxy with a LocalRequirementsRepository if --upgrade is not specified\n    # (= default invocation)\n    if not (upgrade or upgrade_packages) and os.path.exists(dst_file):\n        ireqs = parse_requirements(dst_file, finder=repository.finder, session=repository.session, options=pip_options)\n        existing_pins = {key_from_req(ireq.req): ireq for ireq in ireqs if is_pinned_requirement(ireq)}\n        repository = LocalRequirementsRepository(existing_pins, repository)\n\n    log.debug('Using indexes:')\n    # remove duplicate index urls before processing\n    repository.finder.index_urls = list(dedup(repository.finder.index_urls))\n    for index_url in repository.finder.index_urls:\n        log.debug('  {}'.format(index_url))\n\n    if repository.finder.find_links:\n        log.debug('')\n        log.debug('Configuration:')\n        for find_link in repository.finder.find_links:\n            log.debug('  -f {}'.format(find_link))\n\n    ###\n    # Parsing/collecting initial requirements\n    ###\n\n    constraints = []\n    for src_file in src_files:\n        is_setup_file = os.path.basename(src_file) == 'setup.py'\n        if is_setup_file or src_file == '-':\n            # pip requires filenames and not files. Since we want to support\n            # piping from stdin, we need to briefly save the input from stdin\n            # to a temporary file and have pip read that.  also used for\n            # reading requirements from install_requires in setup.py.\n            tmpfile = tempfile.NamedTemporaryFile(mode='wt', delete=False)\n            if is_setup_file:\n                from distutils.core import run_setup\n                dist = run_setup(src_file)\n                tmpfile.write('\\n'.join(dist.install_requires))\n            else:\n                tmpfile.write(sys.stdin.read())\n            tmpfile.flush()\n            constraints.extend(parse_requirements(\n                tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options))\n        else:\n            constraints.extend(parse_requirements(\n                src_file, finder=repository.finder, session=repository.session, options=pip_options))\n\n    # Check the given base set of constraints first\n    Resolver.check_constraints(constraints)\n\n    try:\n        resolver = Resolver(constraints, repository, prereleases=pre,\n                            clear_caches=rebuild, allow_unsafe=allow_unsafe)\n        results = resolver.resolve(max_rounds=max_rounds)\n        if generate_hashes:\n            hashes = resolver.resolve_hashes(results)\n        else:\n            hashes = None\n    except PipToolsError as e:\n        log.error(str(e))\n        sys.exit(2)\n\n    log.debug('')\n\n    ##\n    # Output\n    ##\n\n    # Compute reverse dependency annotations statically, from the\n    # dependency cache that the resolver has populated by now.\n    #\n    # TODO (1a): reverse deps for any editable package are lost\n    #            what SHOULD happen is that they are cached in memory, just\n    #            not persisted to disk!\n    #\n    # TODO (1b): perhaps it's easiest if the dependency cache has an API\n    #            that could take InstallRequirements directly, like:\n    #\n    #                cache.set(ireq, ...)\n    #\n    #            then, when ireq is editable, it would store in\n    #\n    #              editables[egg_name][link_without_fragment] = deps\n    #              editables['pip-tools']['git+...ols.git@future'] = {'click>=3.0', 'six'}\n    #\n    #            otherwise:\n    #\n    #              self[as_name_version_tuple(ireq)] = {'click>=3.0', 'six'}\n    #\n    reverse_dependencies = None\n    if annotate:\n        reverse_dependencies = resolver.reverse_dependencies(results)\n\n    writer = OutputWriter(src_files, dst_file, dry_run=dry_run,\n                          emit_header=header, emit_index=index,\n                          emit_trusted_host=emit_trusted_host,\n                          annotate=annotate,\n                          generate_hashes=generate_hashes,\n                          default_index_url=repository.DEFAULT_INDEX_URL,\n                          index_urls=repository.finder.index_urls,\n                          trusted_hosts=pip_options.trusted_hosts,\n                          format_control=repository.finder.format_control)\n    writer.write(results=results,\n                 reverse_dependencies=reverse_dependencies,\n                 primary_packages={key_from_req(ireq.req) for ireq in constraints if not ireq.constraint},\n                 markers={key_from_req(ireq.req): ireq.markers\n                          for ireq in constraints if ireq.markers},\n                 hashes=hashes)\n\n    if dry_run:\n        log.warning('Dry-run, so nothing updated.')\n\n\ndef get_pip_command():\n    # Use pip's parser for pip.conf management and defaults.\n    # General options (find_links, index_url, extra_index_url, trusted_host,\n    # and pre) are defered to pip.\n    pip_command = PipCommand()\n    index_opts = pip.cmdoptions.make_option_group(\n        pip.cmdoptions.index_group,\n        pip_command.parser,\n    )\n    pip_command.parser.insert_option_group(0, index_opts)\n    pip_command.parser.add_option(optparse.Option('--pre', action='store_true', default=False))\n\n    return pip_command\n", "path": "piptools/scripts/compile.py"}]}