Skip to content

Commit

Permalink
new --skip option to skip updating packages
Browse files Browse the repository at this point in the history
  • Loading branch information
alanhamlett committed May 10, 2016
1 parent 50f3d2e commit 7221b79
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 17 deletions.
15 changes: 12 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,18 @@ your ``requirements.txt`` file.
Options
-------

There is an optional ``--output`` argument to write the new
``requirements.txt`` file to a different location than the default. By
default, pur overwrites your ``requirements.txt`` file.
-r, --requirement PATH The requirements.txt file to update; Defaults to
using requirements.txt from the current directory
if it exist.
-o, --output PATH Output updated packages to this file; Defaults to
overwriting the input requirements.txt file.
-z, --nonzero-exit-code Exit with status l0 when all packages up-to-date,
11 when some packages were updated. Defaults to
exit status zero on success and non-zero on
failure.
-s, --skip TEXT Comma separated list of packages to skip updating.
--version Show the version and exit.
--help Show this message and exit.


Contributing
Expand Down
28 changes: 18 additions & 10 deletions pur/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,40 @@


@click.command()
@click.argument('requirements_file', type=click.Path(), required=False)
@click.option('--output', type=click.Path(),
@click.option('-r', '--requirement', type=click.Path(),
help='The requirements.txt file to update; Defaults to using ' +
'requirements.txt from the current directory if it exist.')
@click.option('-o', '--output', type=click.Path(),
help='Output updated packages to this file; Defaults to ' +
'writing back to REQUIREMENTS_FILE.')
@click.option('--nonzero-exit-code', is_flag=True, default=False,
'overwriting the input requirements.txt file.')
@click.option('-z', '--nonzero-exit-code', is_flag=True, default=False,
help='Exit with status l0 when all packages up-to-date, 11 ' +
'when some packages were updated. Defaults to exit status zero ' +
'on success and non-zero on failure.')
@click.option('-s', '--skip', type=click.STRING, help='Comma separated list of ' +
'packages to skip updating.')
@click.version_option(__version__)
def pur(requirements_file, **options):
def pur(**options):
"""Command line entry point."""

if not requirements_file:
requirements_file = 'requirements.txt'
if not options.get('requirement'):
options['requirement'] = 'requirements.txt'
if not options.get('output'):
options['output'] = requirements_file
options['output'] = options['requirement']
try:
options['skip'] = set(x.strip() for x in options['skip'].split(','))
except AttributeError:
options['skip'] = set()

# prevent processing nested requirements files
patch_pip()

requirements = get_requirements_and_latest(requirements_file)
requirements = get_requirements_and_latest(options['requirement'])

buf = StringIO()
updated = 0
for line, req, spec_ver, latest_ver in requirements:
if req:
if req and req.name not in options['skip']:
if spec_ver < latest_ver:
new_line = line.replace(str(spec_ver), str(latest_ver), 1)
buf.write(new_line)
Expand Down
7 changes: 7 additions & 0 deletions tests/samples/output/test_skip_package
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
flask==0.9
flask==12.0
# a comment
-r another-requirements.txt
# an empty line below

-e git://github.com/kennethreitz/inbox.py.git@551b4f44b144564504c687cebdb4c543cb8e9adf#egg=inbox
50 changes: 46 additions & 4 deletions tests/test_pur.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,28 @@ def test_updates_package(self):
tempdir = tempfile.mkdtemp()
requirements = os.path.join(tempdir, 'requirements.txt')
shutil.copy('tests/samples/requirements.txt', requirements)
args = [requirements]
args = ['-r', requirements]

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
version = '0.10.1'
link = Link('')
candidate = InstallationCandidate(project, version, link)
mock_find_all_candidates.return_value = [candidate]

result = self.runner.invoke(pur, args)
self.assertIsNone(result.exception)
expected_output = "Updated flask: 0.9 -> 0.10.1\nAll requirements up-to-date.\n"
self.assertEquals(u(result.output), u(expected_output))
self.assertEquals(result.exit_code, 0)
expected_requirements = open('tests/samples/output/test_updates_package').read()
self.assertEquals(open(requirements).read(), expected_requirements)

def test_requirements_long_option_accepted(self):
tempdir = tempfile.mkdtemp()
requirements = os.path.join(tempdir, 'requirements.txt')
shutil.copy('tests/samples/requirements.txt', requirements)
args = ['--requirement', requirements]

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
Expand All @@ -60,7 +81,7 @@ def test_updates_package_to_output_file(self):
tempdir = tempfile.mkdtemp()
output = os.path.join(tempdir, 'output.txt')
requirements = open('tests/samples/requirements.txt').read()
args = ['tests/samples/requirements.txt', '--output', output]
args = ['-r', 'tests/samples/requirements.txt', '--output', output]

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
Expand All @@ -80,7 +101,7 @@ def test_exit_code_from_no_updates(self):
tempdir = tempfile.mkdtemp()
requirements = os.path.join(tempdir, 'requirements.txt')
shutil.copy('tests/samples/requirements-up-to-date.txt', requirements)
args = [requirements, '--nonzero-exit-code']
args = ['-r', requirements, '--nonzero-exit-code']

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
Expand All @@ -101,7 +122,7 @@ def test_exit_code_from_some_updates(self):
tempdir = tempfile.mkdtemp()
requirements = os.path.join(tempdir, 'requirements.txt')
shutil.copy('tests/samples/requirements.txt', requirements)
args = [requirements, '--nonzero-exit-code']
args = ['-r', requirements, '--nonzero-exit-code']

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
Expand All @@ -117,3 +138,24 @@ def test_exit_code_from_some_updates(self):
self.assertEquals(result.exit_code, 11)
expected_requirements = open('tests/samples/output/test_updates_package').read()
self.assertEquals(open(requirements).read(), expected_requirements)

def test_skip_package(self):
tempdir = tempfile.mkdtemp()
requirements = os.path.join(tempdir, 'requirements.txt')
shutil.copy('tests/samples/requirements.txt', requirements)
args = ['-r', requirements, '-s', 'flask']

with utils.mock.patch('pip.index.PackageFinder.find_all_candidates') as mock_find_all_candidates:
project = 'flask'
version = '0.10.1'
link = Link('')
candidate = InstallationCandidate(project, version, link)
mock_find_all_candidates.return_value = [candidate]

result = self.runner.invoke(pur, args)
self.assertIsNone(result.exception)
expected_output = "All requirements up-to-date.\n"
self.assertEquals(u(result.output), u(expected_output))
self.assertEquals(result.exit_code, 0)
expected_requirements = open('tests/samples/output/test_skip_package').read()
self.assertEquals(open(requirements).read(), expected_requirements)

0 comments on commit 7221b79

Please sign in to comment.