Remove 'update-requirements' tool
Requirements haven't been centrally managed for a long time now. Remove the tool. Change-Id: I5689985fd8ab2a061c04776c5320188343b2f077 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
69e21be288
commit
ae953e17cb
@ -1,298 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
A simple script to update the requirements files from a global set of
|
||||
allowable requirements.
|
||||
|
||||
The script can be called like this:
|
||||
|
||||
$> python update.py ../myproj
|
||||
|
||||
Any requirements listed in the target files will have their versions
|
||||
updated to match the global requirements. Requirements not in the global
|
||||
files will be dropped.
|
||||
"""
|
||||
|
||||
import itertools
|
||||
import optparse
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements import requirement
|
||||
|
||||
_setup_py_text = """\
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr>=2.0.0'],
|
||||
pbr=True)
|
||||
"""
|
||||
|
||||
|
||||
# Pure --
|
||||
|
||||
class Change(object):
|
||||
def __init__(self, name, old, new):
|
||||
self.name = name
|
||||
self.old = old.strip()
|
||||
self.new = new.strip()
|
||||
|
||||
def __repr__(self):
|
||||
return "%-30.30s -> %s" % (self.old, self.new)
|
||||
|
||||
|
||||
def _check_setup_py(proj):
|
||||
actions = []
|
||||
# If it doesn't have a setup.py, then we don't want to update it
|
||||
if 'setup.py' not in proj:
|
||||
return actions
|
||||
# If it doesn't use pbr, we don't want to update it.
|
||||
elif 'pbr' not in proj['setup.py']:
|
||||
return actions
|
||||
# We don't update pbr's setup.py because it can't use itself.
|
||||
if 'setup.cfg' in proj and 'name = pbr' in proj['setup.cfg']:
|
||||
return actions
|
||||
actions.append(project.Verbose("Syncing setup.py"))
|
||||
actions.append(project.File('setup.py', _setup_py_text))
|
||||
return actions
|
||||
|
||||
|
||||
def _sync_requirements_file(
|
||||
source_reqs, dest_sequence, dest_label, softupdate, hacking,
|
||||
non_std_reqs, blacklist={}):
|
||||
actions = []
|
||||
dest_reqs = requirement.to_dict(dest_sequence)
|
||||
changes = []
|
||||
output_requirements = []
|
||||
processed_packages = set()
|
||||
|
||||
for req, req_line in dest_sequence:
|
||||
# Skip the instructions header
|
||||
if req_line in requirement._REQS_HEADER:
|
||||
continue
|
||||
elif req is None:
|
||||
# Unparsable lines.
|
||||
output_requirements.append(
|
||||
requirement.Requirement('', '', '', '', req_line.rstrip()))
|
||||
continue
|
||||
elif not req.package:
|
||||
# Comment-only lines
|
||||
output_requirements.append(req)
|
||||
continue
|
||||
elif req.package.lower() in processed_packages:
|
||||
continue
|
||||
|
||||
processed_packages.add(req.package.lower())
|
||||
# Special cases:
|
||||
# projects need to align hacking version on their own time
|
||||
if req.package == "hacking" and not hacking:
|
||||
output_requirements.append(req)
|
||||
continue
|
||||
# the overall blacklist is similarly synced by projects as
|
||||
# needed
|
||||
if req.package in blacklist:
|
||||
output_requirements.append(req)
|
||||
continue
|
||||
|
||||
reference = source_reqs.get(req.package.lower())
|
||||
if reference:
|
||||
actual = dest_reqs.get(req.package.lower())
|
||||
for req, ref in itertools.zip_longest(actual, reference):
|
||||
if not req:
|
||||
# More in globals
|
||||
changes.append(Change(ref[0].package, '', ref[1]))
|
||||
elif not ref:
|
||||
# less in globals
|
||||
changes.append(Change(req[0].package, req[1], ''))
|
||||
elif req[0] != ref[0]:
|
||||
# NOTE(jamielennox): extras are allowed to be specified in
|
||||
# a project's requirements and the version be updated and
|
||||
# extras maintained. Create a new ref object the same as
|
||||
# the original but with the req's extras.
|
||||
|
||||
merged_ref = requirement.Requirement(ref[0].package,
|
||||
ref[0].location,
|
||||
ref[0].specifiers,
|
||||
ref[0].markers,
|
||||
ref[0].comment,
|
||||
req[0].extras)
|
||||
|
||||
ref = (merged_ref, merged_ref.to_line())
|
||||
|
||||
if req[0] != ref[0]:
|
||||
# A change on this entry
|
||||
changes.append(Change(req[0].package, req[1], ref[1]))
|
||||
|
||||
if ref:
|
||||
output_requirements.append(ref[0])
|
||||
elif softupdate:
|
||||
# under softupdate we pass through anything unknown packages,
|
||||
# this is intended for ecosystem projects that want to stay in
|
||||
# sync with existing requirements, but also add their own above
|
||||
# and beyond.
|
||||
output_requirements.append(req)
|
||||
else:
|
||||
# What do we do if we find something unexpected?
|
||||
#
|
||||
# In the default cause we should die horribly, because
|
||||
# the point of global requirements was a single lever
|
||||
# to control all the pip installs in the gate.
|
||||
#
|
||||
# However, we do have other projects using
|
||||
# devstack jobs that might have legitimate reasons to
|
||||
# override. For those we support NON_STANDARD_REQS=1
|
||||
# environment variable to turn this into a warning only.
|
||||
# However this drops the unknown requirement.
|
||||
actions.append(project.Error(
|
||||
"'%s' is not in global-requirements.txt or blacklist.txt"
|
||||
% req.package))
|
||||
# always print out what we did if we did a thing
|
||||
if changes:
|
||||
actions.append(project.StdOut(
|
||||
"Version change for: %s\n"
|
||||
% ", ".join([x.name for x in changes])))
|
||||
actions.append(project.StdOut("Updated %s:\n" % dest_label))
|
||||
for change in changes:
|
||||
actions.append(project.StdOut(" %s\n" % change))
|
||||
return actions, requirement.Requirements(output_requirements)
|
||||
|
||||
|
||||
def _copy_requires(
|
||||
suffix, softupdate, hacking, proj, global_reqs, non_std_reqs,
|
||||
blacklist={}):
|
||||
"""Copy requirements files."""
|
||||
actions = []
|
||||
for source, content in sorted(proj['requirements'].items()):
|
||||
dest_path = os.path.join(proj['root'], source)
|
||||
# this is specifically for global-requirements gate jobs so we don't
|
||||
# modify the git tree
|
||||
if suffix:
|
||||
dest_path = "%s.%s" % (dest_path, suffix)
|
||||
dest_name = "%s.%s" % (source, suffix)
|
||||
else:
|
||||
dest_name = source
|
||||
dest_sequence = list(requirement.to_reqs(content))
|
||||
actions.append(project.Verbose("Syncing %s" % dest_path))
|
||||
_actions, reqs = _sync_requirements_file(
|
||||
global_reqs, dest_sequence, dest_path, softupdate, hacking,
|
||||
non_std_reqs, blacklist)
|
||||
actions.extend(_actions)
|
||||
actions.append(project.File(dest_name, requirement.to_content(reqs)))
|
||||
extras = project.extras(proj)
|
||||
output_extras = {}
|
||||
for extra, content in sorted(extras.items()):
|
||||
dest_name = 'extra-%s' % extra
|
||||
dest_path = "%s[%s]" % (proj['root'], extra)
|
||||
dest_sequence = list(requirement.to_reqs(content))
|
||||
actions.append(project.Verbose("Syncing extra [%s]" % extra))
|
||||
_actions, reqs = _sync_requirements_file(
|
||||
global_reqs, dest_sequence, dest_path, softupdate, hacking,
|
||||
non_std_reqs, blacklist)
|
||||
actions.extend(_actions)
|
||||
output_extras[extra] = reqs
|
||||
dest_path = 'setup.cfg'
|
||||
if suffix:
|
||||
dest_path = "%s.%s" % (dest_path, suffix)
|
||||
actions.append(project.File(
|
||||
dest_path, project.merge_setup_cfg(proj['setup.cfg'], output_extras)))
|
||||
return actions
|
||||
|
||||
|
||||
def _process_project(
|
||||
project, global_reqs, suffix, softupdate, hacking, non_std_reqs,
|
||||
blacklist={}):
|
||||
"""Project a project.
|
||||
|
||||
:return: The actions to take as a result.
|
||||
"""
|
||||
actions = _copy_requires(
|
||||
suffix, softupdate, hacking, project, global_reqs, non_std_reqs,
|
||||
blacklist)
|
||||
actions.extend(_check_setup_py(project))
|
||||
return actions
|
||||
|
||||
|
||||
# IO --
|
||||
|
||||
def main(argv=None, stdout=None, _worker=None):
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("-o", "--output-suffix", dest="suffix", default="",
|
||||
help="output suffix for updated files (i.e. .global)")
|
||||
parser.add_option("-s", "--soft-update", dest="softupdate",
|
||||
action="store_true",
|
||||
help="Pass through extra requirements without warning.")
|
||||
parser.add_option("-H", "--hacking", dest="hacking",
|
||||
action="store_true",
|
||||
help="Include the hacking project.")
|
||||
parser.add_option("-v", "--verbose", dest="verbose",
|
||||
action="store_true",
|
||||
help="Add further verbosity to output")
|
||||
parser.add_option("--source", dest="source", default=".",
|
||||
help="Dir where global-requirements.txt is located.")
|
||||
options, args = parser.parse_args(argv)
|
||||
if len(args) != 1:
|
||||
print("Must specify directory to update")
|
||||
raise Exception("Must specify one and only one directory to update.")
|
||||
if not os.path.isdir(args[0]):
|
||||
print("%s is not a directory." % (args[0]))
|
||||
raise Exception("%s is not a directory." % (args[0]))
|
||||
if stdout is None:
|
||||
stdout = sys.stdout
|
||||
if _worker is None:
|
||||
_worker = _do_main
|
||||
non_std_reqs = os.getenv('NON_STANDARD_REQS', '0') == '1'
|
||||
_worker(
|
||||
args[0], options.source, options.suffix, options.softupdate,
|
||||
options.hacking, stdout, options.verbose, non_std_reqs)
|
||||
|
||||
|
||||
def _do_main(
|
||||
root, source, suffix, softupdate, hacking, stdout, verbose,
|
||||
non_std_reqs):
|
||||
"""No options or environment variable access from here on in."""
|
||||
proj = project.read(root)
|
||||
global_req_content = open(
|
||||
os.path.join(source, 'global-requirements.txt'), 'rt').read()
|
||||
global_reqs = requirement.parse(global_req_content)
|
||||
blacklist_content = open(
|
||||
os.path.join(source, 'blacklist.txt'), 'rt').read()
|
||||
blacklist = requirement.parse(blacklist_content)
|
||||
actions = _process_project(
|
||||
proj, global_reqs, suffix, softupdate, hacking, non_std_reqs,
|
||||
blacklist)
|
||||
project.write(proj, actions, stdout=stdout, verbose=verbose)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -15,7 +15,6 @@ import shutil
|
||||
|
||||
import fixtures
|
||||
|
||||
from openstack_requirements.cmds import update
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements import requirement
|
||||
|
||||
@ -102,16 +101,3 @@ pbr_project = make_project(pbr_fixture)
|
||||
project_project = make_project(project_fixture)
|
||||
bad_project = make_project(bad_project_fixture)
|
||||
oslo_project = make_project(oslo_fixture)
|
||||
|
||||
|
||||
def project_file(
|
||||
fail, proj, action_filename, suffix=None, softupdate=None,
|
||||
non_std_reqs=False, blacklist={}):
|
||||
actions = update._process_project(
|
||||
proj, global_reqs, suffix, softupdate, None,
|
||||
non_std_reqs, blacklist)
|
||||
for action in actions:
|
||||
if type(action) is project.File:
|
||||
if action.filename == action_filename:
|
||||
return action.content.splitlines()
|
||||
fail('File %r not found in %r' % (action_filename, actions))
|
||||
|
@ -1,456 +0,0 @@
|
||||
# Copyright 2013 IBM Corp.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import io
|
||||
import sys
|
||||
import textwrap
|
||||
from unittest import mock
|
||||
|
||||
import fixtures
|
||||
import testscenarios
|
||||
import testtools
|
||||
from testtools import matchers
|
||||
|
||||
from openstack_requirements.cmds import update
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements import requirement
|
||||
from openstack_requirements.tests import common
|
||||
|
||||
|
||||
load_tests = testscenarios.load_tests_apply_scenarios
|
||||
|
||||
|
||||
class SmokeTest(testtools.TestCase):
|
||||
|
||||
def test_project(self):
|
||||
global_env = self.useFixture(common.GlobalRequirements())
|
||||
global_reqs = common._file_to_list(global_env.req_file)
|
||||
# This is testing our test input data. Perhaps remove? (lifeless)
|
||||
self.assertIn("jsonschema!=1.4.0,<2,>=1.0.0", global_reqs)
|
||||
# And test the end to end call of update.py, UI and all.
|
||||
self.project = self.useFixture(common.project_fixture)
|
||||
capture = io.StringIO()
|
||||
update.main(['--source', global_env.root, self.project.root], capture)
|
||||
reqs = common._file_to_list(self.project.req_file)
|
||||
# ensure various updates take
|
||||
self.assertIn("jsonschema!=1.4.0,<2,>=1.0.0", reqs)
|
||||
self.assertIn("python-keystoneclient>=0.4.1", reqs)
|
||||
self.assertIn("SQLAlchemy<=0.7.99,>=0.7", reqs)
|
||||
expected = ('Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, python-swiftclient, lxml, jsonschema, python-keystoneclient\n' # noqa
|
||||
"""Updated %(project)s/requirements.txt:
|
||||
greenlet>=0.3.1 -> greenlet>=0.3.2
|
||||
SQLAlchemy>=0.7.8,<=1.0.17 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
eventlet>=0.9.12 -> eventlet>=0.12.0
|
||||
PasteDeploy -> PasteDeploy>=1.5.0
|
||||
routes -> Routes>=1.12.3
|
||||
WebOb>=1.2 -> WebOb<1.3,>=1.2.3
|
||||
wsgiref -> wsgiref>=0.1.2
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
python-swiftclient>=1.2,<4 -> python-swiftclient>=1.2
|
||||
lxml -> lxml>=2.3
|
||||
jsonschema -> jsonschema!=1.4.0,<2,>=1.0.0
|
||||
python-keystoneclient>=0.2.0 -> python-keystoneclient>=0.4.1
|
||||
Version change for: mox, mox3, testrepository, testtools
|
||||
Updated %(project)s/test-requirements.txt:
|
||||
mox==0.5.3 -> mox>=0.5.3
|
||||
mox3==0.21.0 -> mox3>=0.7.0
|
||||
testrepository>=0.0.13 -> testrepository>=0.0.17
|
||||
testtools>=0.9.27 -> testtools>=0.9.32
|
||||
""") % dict(project=self.project.root)
|
||||
self.assertEqual(expected, capture.getvalue())
|
||||
|
||||
|
||||
class UpdateTest(testtools.TestCase):
|
||||
|
||||
def test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.project_project, 'requirements.txt')
|
||||
# ensure various updates take
|
||||
self.assertIn("jsonschema!=1.4.0,<2,>=1.0.0", reqs)
|
||||
self.assertIn("python-keystoneclient>=0.4.1", reqs)
|
||||
self.assertIn("SQLAlchemy<=0.7.99,>=0.7", reqs)
|
||||
|
||||
def test_requirements_header(self):
|
||||
_REQS_HEADER = [
|
||||
'# The order of packages is significant, because pip processes '
|
||||
'them in the order',
|
||||
'# of appearance. Changing the order has an impact on the overall '
|
||||
'integration',
|
||||
'# process, which may cause wedges in the gate later.',
|
||||
]
|
||||
reqs = common.project_file(
|
||||
self.fail, common.project_project, 'requirements.txt')
|
||||
self.assertEqual(_REQS_HEADER, reqs[:3])
|
||||
|
||||
def test_project_with_oslo(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.oslo_project, 'requirements.txt')
|
||||
oslo_tar = ("-f http://tarballs.openstack.org/oslo.config/"
|
||||
"oslo.config-1.2.0a3.tar.gz#egg=oslo.config-1.2.0a3")
|
||||
self.assertIn(oslo_tar, reqs)
|
||||
|
||||
def test_test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.project_project, 'test-requirements.txt')
|
||||
self.assertIn("testtools>=0.9.32", reqs)
|
||||
self.assertIn("testrepository>=0.0.17", reqs)
|
||||
# make sure we didn't add something we shouldn't
|
||||
self.assertNotIn("sphinxcontrib-pecanwsme>=0.2", reqs)
|
||||
|
||||
def test_install_setup(self):
|
||||
setup_contents = common.project_file(
|
||||
self.fail, common.project_project, 'setup.py', suffix='global')
|
||||
self.assertIn("# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO"
|
||||
" - DO NOT EDIT", setup_contents)
|
||||
|
||||
def test_no_install_setup(self):
|
||||
actions = update._process_project(
|
||||
common.oslo_project, common.global_reqs, None, None, None,
|
||||
False)
|
||||
for action in actions:
|
||||
if type(action) is project.File:
|
||||
self.assertNotEqual(action.filename, 'setup.py')
|
||||
|
||||
# These are tests which don't need to run the project update in advance
|
||||
def test_requirement_not_in_global(self):
|
||||
actions = update._process_project(
|
||||
common.bad_project, common.global_reqs, None, None, None, False)
|
||||
errors = [a for a in actions if type(a) is project.Error]
|
||||
msg = u"'thisisnotarealdependency' is not in global-requirements.txt"
|
||||
self.assertIn(msg, errors[0].message)
|
||||
|
||||
def test_requirement_in_blacklist(self):
|
||||
actions = update._process_project(
|
||||
common.bad_project, common.global_reqs, None, None, None, False,
|
||||
blacklist={'thisisnotarealdependency': None})
|
||||
errors = [a for a in actions if type(a) is project.Error]
|
||||
self.assertEqual([], errors)
|
||||
|
||||
def test_requirement_not_in_global_non_fatal(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.bad_project, 'requirements.txt',
|
||||
non_std_reqs=True)
|
||||
self.assertNotIn("thisisnotarealdependency", reqs)
|
||||
|
||||
def test_requirement_soft_update(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.bad_project, 'requirements.txt',
|
||||
softupdate=True)
|
||||
self.assertIn("thisisnotarealdependency", reqs)
|
||||
|
||||
# testing output
|
||||
def test_non_verbose_output(self):
|
||||
actions = update._process_project(
|
||||
common.project_project, common.global_reqs, None, None, None,
|
||||
False)
|
||||
capture = io.StringIO()
|
||||
project.write(
|
||||
common.project_project, actions, capture, False, True)
|
||||
expected = ('Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, python-swiftclient, lxml, jsonschema, python-keystoneclient\n' # noqa
|
||||
"""Updated %(project)s/requirements.txt:
|
||||
greenlet>=0.3.1 -> greenlet>=0.3.2
|
||||
SQLAlchemy>=0.7.8,<=1.0.17 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
eventlet>=0.9.12 -> eventlet>=0.12.0
|
||||
PasteDeploy -> PasteDeploy>=1.5.0
|
||||
routes -> Routes>=1.12.3
|
||||
WebOb>=1.2 -> WebOb<1.3,>=1.2.3
|
||||
wsgiref -> wsgiref>=0.1.2
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
python-swiftclient>=1.2,<4 -> python-swiftclient>=1.2
|
||||
lxml -> lxml>=2.3
|
||||
jsonschema -> jsonschema!=1.4.0,<2,>=1.0.0
|
||||
python-keystoneclient>=0.2.0 -> python-keystoneclient>=0.4.1
|
||||
Version change for: mox, mox3, testrepository, testtools
|
||||
Updated %(project)s/test-requirements.txt:
|
||||
mox==0.5.3 -> mox>=0.5.3
|
||||
mox3==0.21.0 -> mox3>=0.7.0
|
||||
testrepository>=0.0.13 -> testrepository>=0.0.17
|
||||
testtools>=0.9.27 -> testtools>=0.9.32
|
||||
""") % dict(project=common.project_project['root'])
|
||||
self.assertEqual(expected, capture.getvalue())
|
||||
|
||||
def test_verbose_output(self):
|
||||
actions = update._process_project(
|
||||
common.project_project, common.global_reqs, None, None, None,
|
||||
False)
|
||||
capture = io.StringIO()
|
||||
project.write(
|
||||
common.project_project, actions, capture, True, True)
|
||||
expected = ("""Syncing %(project)s/requirements.txt
|
||||
Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, python-swiftclient, lxml, jsonschema, python-keystoneclient\n""" # noqa
|
||||
"""Updated %(project)s/requirements.txt:
|
||||
greenlet>=0.3.1 -> greenlet>=0.3.2
|
||||
SQLAlchemy>=0.7.8,<=1.0.17 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
eventlet>=0.9.12 -> eventlet>=0.12.0
|
||||
PasteDeploy -> PasteDeploy>=1.5.0
|
||||
routes -> Routes>=1.12.3
|
||||
WebOb>=1.2 -> WebOb<1.3,>=1.2.3
|
||||
wsgiref -> wsgiref>=0.1.2
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
python-swiftclient>=1.2,<4 -> python-swiftclient>=1.2
|
||||
lxml -> lxml>=2.3
|
||||
jsonschema -> jsonschema!=1.4.0,<2,>=1.0.0
|
||||
python-keystoneclient>=0.2.0 -> python-keystoneclient>=0.4.1
|
||||
Syncing %(project)s/test-requirements.txt
|
||||
Version change for: mox, mox3, testrepository, testtools
|
||||
Updated %(project)s/test-requirements.txt:
|
||||
mox==0.5.3 -> mox>=0.5.3
|
||||
mox3==0.21.0 -> mox3>=0.7.0
|
||||
testrepository>=0.0.13 -> testrepository>=0.0.17
|
||||
testtools>=0.9.27 -> testtools>=0.9.32
|
||||
Syncing setup.py
|
||||
""") % dict(project=common.project_project['root'])
|
||||
self.assertEqual(expected, capture.getvalue())
|
||||
|
||||
|
||||
class TestMain(testtools.TestCase):
|
||||
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
def test_smoke(self, mock_isdir):
|
||||
def check_params(
|
||||
root, source, suffix, softupdate, hacking, stdout, verbose,
|
||||
non_std_reqs):
|
||||
self.expectThat(root, matchers.Equals('/dev/zero'))
|
||||
self.expectThat(source, matchers.Equals('/dev/null'))
|
||||
self.expectThat(suffix, matchers.Equals(''))
|
||||
self.expectThat(softupdate, matchers.Equals(None))
|
||||
self.expectThat(hacking, matchers.Equals(None))
|
||||
self.expectThat(stdout, matchers.Equals(sys.stdout))
|
||||
self.expectThat(verbose, matchers.Equals(None))
|
||||
self.expectThat(non_std_reqs, matchers.Equals(True))
|
||||
|
||||
with fixtures.EnvironmentVariable('NON_STANDARD_REQS', '1'):
|
||||
update.main(
|
||||
['--source', '/dev/null', '/dev/zero'], _worker=check_params)
|
||||
self.expectThat(mock_isdir.called, matchers.Equals(True))
|
||||
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
def test_suffix(self, mock_isdir):
|
||||
def check_params(
|
||||
root, source, suffix, softupdate, hacking, stdout, verbose,
|
||||
non_std_reqs):
|
||||
self.expectThat(suffix, matchers.Equals('global'))
|
||||
|
||||
update.main(['-o', 'global', '/dev/zero'], _worker=check_params)
|
||||
self.expectThat(mock_isdir.called, matchers.Equals(True))
|
||||
|
||||
def test_isdirectory(self):
|
||||
def never_called(
|
||||
root, source, suffix, softupdate, hacking, stdout, verbose,
|
||||
non_std_reqs):
|
||||
self.expectThat(False, matchers.Equals(True),
|
||||
message=("update.main() should riase an "
|
||||
"exception before getting here"))
|
||||
|
||||
with testtools.ExpectedException(Exception,
|
||||
"/dev/zero is not a directory"):
|
||||
update.main(['/dev/zero'], _worker=never_called)
|
||||
|
||||
|
||||
class TestSyncRequirementsFile(testtools.TestCase):
|
||||
|
||||
def test_multiple_lines_in_global_one_in_project(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement(
|
||||
'foo', '', '<2', "python_version=='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'foo', '', '>1', "python_version!='2.7'", '')]),
|
||||
reqs)
|
||||
self.assertEqual(project.StdOut(
|
||||
" foo "
|
||||
"-> foo<2;python_version=='2.7'\n"), actions[2])
|
||||
self.assertEqual(project.StdOut(
|
||||
" "
|
||||
"-> foo>1;python_version!='2.7'\n"), actions[3])
|
||||
self.assertThat(actions, matchers.HasLength(4))
|
||||
|
||||
def test_multiple_lines_separated_in_project_nochange(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
# mumbo gumbo
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement(
|
||||
'foo', '', '<2', "python_version=='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'foo', '', '>1', "python_version!='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'', '', '', '', "# mumbo gumbo")]),
|
||||
reqs)
|
||||
self.assertThat(actions, matchers.HasLength(0))
|
||||
|
||||
def test_multiple_lines_separated_in_project(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo<1.8;python_version=='2.7'
|
||||
# mumbo gumbo
|
||||
foo>0.9;python_version!='2.7'
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement(
|
||||
'foo', '', '<2', "python_version=='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'foo', '', '>1', "python_version!='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'', '', '', '', "# mumbo gumbo")]),
|
||||
reqs)
|
||||
self.assertEqual(project.StdOut(
|
||||
" foo<1.8;python_version=='2.7' -> "
|
||||
"foo<2;python_version=='2.7'\n"), actions[2])
|
||||
self.assertEqual(project.StdOut(
|
||||
" foo>0.9;python_version!='2.7' -> "
|
||||
"foo>1;python_version!='2.7'\n"), actions[3])
|
||||
self.assertThat(actions, matchers.HasLength(4))
|
||||
|
||||
def test_multiple_lines_nochange(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement(
|
||||
'foo', '', '<2', "python_version=='2.7'", ''),
|
||||
requirement.Requirement(
|
||||
'foo', '', '>1', "python_version!='2.7'", '')]),
|
||||
reqs)
|
||||
self.assertThat(actions, matchers.HasLength(0))
|
||||
|
||||
def test_single_global_multiple_in_project(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo>1
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo<2;python_version=='2.7'
|
||||
foo>1;python_version!='2.7'
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement('foo', '', '>1', "", '')]),
|
||||
reqs)
|
||||
self.assertEqual(project.StdOut(
|
||||
" foo<2;python_version=='2.7' -> foo>1\n"), actions[2])
|
||||
self.assertEqual(project.StdOut(
|
||||
" foo>1;python_version!='2.7' -> \n"), actions[3])
|
||||
self.assertThat(actions, matchers.HasLength(4))
|
||||
|
||||
def test_unparseable_line(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
foo
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
foo
|
||||
-e https://git.openstack.org/openstack/neutron.git#egg=neutron
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
n = '-e https://git.openstack.org/openstack/neutron.git#egg=neutron'
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement('foo', '', '', '', ''),
|
||||
requirement.Requirement('', '', '', '', n)]),
|
||||
reqs)
|
||||
|
||||
def test_extras_kept(self):
|
||||
global_content = textwrap.dedent("""\
|
||||
oslo.db>1.4.1
|
||||
""")
|
||||
project_content = textwrap.dedent("""\
|
||||
oslo.db[fixture,mysql]>1.3
|
||||
""")
|
||||
global_reqs = requirement.parse(global_content)
|
||||
project_reqs = list(requirement.to_reqs(project_content))
|
||||
actions, reqs = update._sync_requirements_file(
|
||||
global_reqs, project_reqs, 'f', False, False, False)
|
||||
self.assertEqual(requirement.Requirements([
|
||||
requirement.Requirement(
|
||||
'oslo.db', '', '>1.4.1', '', '', ['fixture', 'mysql'])]),
|
||||
reqs)
|
||||
self.assertThat(actions, matchers.HasLength(3))
|
||||
self.assertEqual(project.StdOut(
|
||||
" oslo.db[fixture,mysql]>1.3 -> "
|
||||
"oslo.db[fixture,mysql]>1.4.1\n"), actions[2])
|
||||
|
||||
|
||||
class TestCopyRequires(testtools.TestCase):
|
||||
|
||||
def test_extras_no_change(self):
|
||||
global_content = textwrap.dedent(u"""\
|
||||
foo<2;python_version=='2.7' # BSD
|
||||
foo>1;python_version!='2.7'
|
||||
freddy
|
||||
""")
|
||||
setup_cfg = textwrap.dedent(u"""\
|
||||
[metadata]
|
||||
name = openstack.requirements
|
||||
|
||||
[extras]
|
||||
test =
|
||||
foo<2:python_version=='2.7' # BSD
|
||||
foo>1:python_version!='2.7'
|
||||
opt =
|
||||
freddy
|
||||
""")
|
||||
proj = {}
|
||||
proj['root'] = '/dev/null'
|
||||
proj['requirements'] = {}
|
||||
proj['setup.cfg'] = setup_cfg
|
||||
global_reqs = requirement.parse(global_content)
|
||||
actions = update._copy_requires(
|
||||
u'', False, False, proj, global_reqs, False)
|
||||
self.assertEqual([
|
||||
project.Verbose('Syncing extra [opt]'),
|
||||
project.Verbose('Syncing extra [test]'),
|
||||
project.File('setup.cfg', setup_cfg)], actions)
|
@ -1,50 +0,0 @@
|
||||
# Copyright 2013 IBM Corp.
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Based on test_update.py
|
||||
|
||||
import testtools
|
||||
|
||||
from openstack_requirements.cmds import update
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements.tests import common
|
||||
|
||||
|
||||
class UpdateTestPbr(testtools.TestCase):
|
||||
|
||||
def test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.pbr_project, 'requirements.txt')
|
||||
# ensure various updates take
|
||||
self.assertIn("jsonschema!=1.4.0,<2,>=1.0.0", reqs)
|
||||
self.assertIn("python-keystoneclient>=0.4.1", reqs)
|
||||
self.assertIn("SQLAlchemy<=0.7.99,>=0.7", reqs)
|
||||
|
||||
def test_test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.pbr_project, 'test-requirements.txt')
|
||||
self.assertIn("testtools>=0.9.32", reqs)
|
||||
self.assertIn("testrepository>=0.0.17", reqs)
|
||||
# make sure we didn't add something we shouldn't
|
||||
self.assertNotIn("sphinxcontrib-pecanwsme>=0.2", reqs)
|
||||
|
||||
def test_no_install_setup(self):
|
||||
actions = update._process_project(
|
||||
common.pbr_project, common.global_reqs, None, None, None,
|
||||
False)
|
||||
for action in actions:
|
||||
if type(action) is project.File:
|
||||
self.assertNotEqual(action.filename, 'setup.py')
|
@ -1,62 +0,0 @@
|
||||
# Copyright 2013 IBM Corp.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import testtools
|
||||
|
||||
from openstack_requirements.cmds import update
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements.tests import common
|
||||
|
||||
|
||||
class UpdateTestWithSuffix(testtools.TestCase):
|
||||
|
||||
def test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.project_project, 'requirements.txt.global',
|
||||
suffix='global')
|
||||
# ensure various updates take
|
||||
self.assertIn("jsonschema!=1.4.0,<2,>=1.0.0", reqs)
|
||||
self.assertIn("python-keystoneclient>=0.4.1", reqs)
|
||||
self.assertIn("SQLAlchemy<=0.7.99,>=0.7", reqs)
|
||||
|
||||
def test_project_with_oslo(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.oslo_project, 'requirements.txt.global',
|
||||
suffix='global')
|
||||
oslo_tar = ("-f http://tarballs.openstack.org/oslo.config/"
|
||||
"oslo.config-1.2.0a3.tar.gz#egg=oslo.config-1.2.0a3")
|
||||
self.assertIn(oslo_tar, reqs)
|
||||
|
||||
def test_test_project(self):
|
||||
reqs = common.project_file(
|
||||
self.fail, common.project_project, 'test-requirements.txt.global',
|
||||
suffix='global')
|
||||
self.assertIn("testtools>=0.9.32", reqs)
|
||||
self.assertIn("testrepository>=0.0.17", reqs)
|
||||
# make sure we didn't add something we shouldn't
|
||||
self.assertNotIn("sphinxcontrib-pecanwsme>=0.2", reqs)
|
||||
|
||||
def test_install_setup(self):
|
||||
setup_contents = common.project_file(
|
||||
self.fail, common.project_project, 'setup.py', suffix='global')
|
||||
self.assertIn("# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO"
|
||||
" - DO NOT EDIT", setup_contents)
|
||||
|
||||
def test_no_install_setup(self):
|
||||
actions = update._process_project(
|
||||
common.oslo_project, common.global_reqs, 'global', None, None,
|
||||
False)
|
||||
for action in actions:
|
||||
if type(action) is project.File:
|
||||
self.assertNotEqual(action.filename, 'setup.py')
|
@ -31,7 +31,6 @@ console_scripts =
|
||||
edit-constraints = openstack_requirements.cmds.edit_constraint:main
|
||||
generate-constraints = openstack_requirements.cmds.generate:main
|
||||
check-conflicts = openstack_requirements.cmds.check_conflicts:main
|
||||
update-requirements = openstack_requirements.cmds.update:main
|
||||
validate-constraints = openstack_requirements.cmds.validate:main
|
||||
validate-projects = openstack_requirements.cmds.validate_projects:main
|
||||
normalize-requirements = openstack_requirements.cmds.normalize_requirements:main
|
||||
|
Loading…
Reference in New Issue
Block a user