Skip to content

Commit

Permalink
Merge pull request #481 from majuscule/dlloyd/pr418-testing
Browse files Browse the repository at this point in the history
#418 testing
  • Loading branch information
davidovich authored Mar 29, 2017
2 parents 54e8830 + 36ba0e1 commit cb331a8
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 16 deletions.
43 changes: 36 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,46 @@ $ pip install pip-tools
Example usage for `pip-compile`
===============================

Suppose you have a Flask project, and want to pin it for production. Write the
following line to a file:
Requirements from setup.py
--------------------------

Suppose you have a Flask project, and want to pin it for production. If you have a `setup.py` with
`install_requires=['Flask']`, then run `pip-compile` without any arguments:
```console
$ pip-compile
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt setup.py
#
flask==0.10.1
itsdangerous==0.24 # via flask
jinja2==2.7.3 # via flask
markupsafe==0.23 # via jinja2
werkzeug==0.10.4 # via flask
```

`pip-compile` will produce your `requirements.txt`, with all the Flask dependencies
(and all underlying dependencies) pinned. You should put your requirements file under version control.

Without setup.py
----------------

If you don't use `setup.py` ([it's easy to write one][1]), you can instead write the following line to a file:

# requirements.in
Flask

Now, run `pip-compile requirements.in`:
This time, run `pip-compile requirements.in`:

```console
$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# Make changes in requirements.in, then run this to update:
# To update, run:
#
# pip-compile requirements.in
# pip-compile --output-file requirements.txt requirements.in
#
flask==0.10.1
itsdangerous==0.24 # via flask
Expand All @@ -48,8 +73,12 @@ werkzeug==0.10.4 # via flask
```

And it will produce your `requirements.txt`, with all the Flask dependencies
(and all underlying dependencies) pinned. Put this file under version control
as well.
(and all underlying dependencies) pinned. Don't forget to put this file under version control as well.

[1]: https://packaging.python.org/distributing/#configuring-your-project

Updating requirements
---------------------

To update all packages, periodically re-run `pip-compile --upgrade`.

Expand Down
30 changes: 21 additions & 9 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,15 @@ def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,
log.verbose = verbose

if len(src_files) == 0:
if not os.path.exists(DEFAULT_REQUIREMENTS_FILE):
if os.path.exists(DEFAULT_REQUIREMENTS_FILE):
src_files = (DEFAULT_REQUIREMENTS_FILE,)
elif os.path.exists('setup.py'):
src_files = ('setup.py',)
if not output_file:
output_file = 'requirements.txt'
else:
raise click.BadParameter(("If you do not specify an input file, "
"the default is {}").format(DEFAULT_REQUIREMENTS_FILE))
src_files = (DEFAULT_REQUIREMENTS_FILE,)
"the default is {} or setup.py").format(DEFAULT_REQUIREMENTS_FILE))

if len(src_files) == 1 and src_files[0] == '-':
if not output_file:
Expand Down Expand Up @@ -152,15 +157,22 @@ def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,

constraints = []
for src_file in src_files:
if src_file == '-':
is_setup_file = os.path.basename(src_file) == 'setup.py'
if is_setup_file or src_file == '-':
# pip requires filenames and not files. Since we want to support
# piping from stdin, we need to briefly save the input from stdin
# to a temporary file and have pip read that.
with tempfile.NamedTemporaryFile(mode='wt') as tmpfile:
# to a temporary file and have pip read that. also used for
# reading requirements from install_requires in setup.py.
tmpfile = tempfile.NamedTemporaryFile(mode='wt', delete=False)
if is_setup_file:
from distutils.core import run_setup
dist = run_setup(src_file)
tmpfile.write('\n'.join(dist.install_requires))
else:
tmpfile.write(sys.stdin.read())
tmpfile.flush()
constraints.extend(parse_requirements(
tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options))
tmpfile.flush()
constraints.extend(parse_requirements(
tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options))
else:
constraints.extend(parse_requirements(
src_file, finder=repository.finder, session=repository.session, options=pip_options))
Expand Down
16 changes: 16 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ def test_command_line_overrides_pip_conf(pip_conf):
assert 'Using indexes:\n http://override.com' in out.output


def test_command_line_setuptools_read(pip_conf):

runner = CliRunner()
with runner.isolated_filesystem():
package = open('setup.py', 'w')
package.write(dedent("""\
from setuptools import setup
setup(install_requires=[])
"""))
package.close()
out = runner.invoke(cli)

# check that pip-compile generated a configuration
assert 'This file is autogenerated by pip-compile' in out.output


def test_find_links_option(pip_conf):

assert os.path.exists(pip_conf)
Expand Down

0 comments on commit cb331a8

Please sign in to comment.