Create check_constraints command
The check_constraints utility wraps a new check_exists cmd. This command looks at a project's requirements and checks: - That the requirement name alone exists in both g-r and u-c - If it exists in both, then check that the version in u-c is covered. - Added an extra g-r check as a flag, but not quite happy with it. It needs more work.. but would be a _little_ more correct if/when g-r stops defining the minimum. This patch is currently WIP as tests are still required. But is the starting point for the fuzzy checking for projects managing their own lower-constraints. Change-Id: I36690fddcfc24d49aab0d28d7d46dcd8d9128b2a
This commit is contained in:
parent
9eb6e51f98
commit
302ba18d81
113
openstack_requirements/cmds/check_exists.py
Normal file
113
openstack_requirements/cmds/check_exists.py
Normal file
@ -0,0 +1,113 @@
|
||||
# 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.
|
||||
|
||||
"""Check to see if a package from a project's requrements file exist in g-r or
|
||||
u-c.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
|
||||
from packaging.specifiers import SpecifierSet
|
||||
from packaging.version import Version
|
||||
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements import requirement
|
||||
|
||||
|
||||
def read_requirements_file(filename):
|
||||
with open(filename, 'rt') as f:
|
||||
body = f.read()
|
||||
return requirement.parse(body)
|
||||
|
||||
|
||||
def main(args=None):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'project',
|
||||
default='',
|
||||
help='path to the project source root folder.')
|
||||
parser.add_argument(
|
||||
'-u', '--upper-constraints',
|
||||
default='upper-constraints.txt',
|
||||
help='path to the upper-constraints.txt file')
|
||||
parser.add_argument(
|
||||
'-g', '--global-requirements',
|
||||
default='global-requirements.txt',
|
||||
help='Path to the global-requirements.txt file')
|
||||
parser.add_argument(
|
||||
'-b', '--blacklist',
|
||||
default='blacklist.txt',
|
||||
help='Path to the blacklist.txt file')
|
||||
parser.add_argument(
|
||||
'-G', '--gr-check', action='store_true',
|
||||
help='Do a specifier check of global-requirements')
|
||||
args = parser.parse_args(args)
|
||||
|
||||
upper_constraints = read_requirements_file(args.upper_constraints)
|
||||
global_requirements = read_requirements_file(args.global_requirements)
|
||||
blacklist = read_requirements_file(args.blacklist)
|
||||
project_data = project.read(args.project)
|
||||
error_count = 0
|
||||
|
||||
for require_file, data in project_data.get('requirements', {}).items():
|
||||
print(u'\nComparing %s with global-requirements and upper-constraints'
|
||||
% require_file)
|
||||
requirements = requirement.parse(data)
|
||||
for name, spec_list in requirements.items():
|
||||
if not name or name in blacklist:
|
||||
continue
|
||||
if name not in global_requirements:
|
||||
print(u'%s from %s not found in global-requirements' % (
|
||||
name, require_file))
|
||||
error_count += 1
|
||||
continue
|
||||
if name not in upper_constraints:
|
||||
print(u'%s from %s not found in upper-constraints' % (
|
||||
name, require_file))
|
||||
error_count += 1
|
||||
continue
|
||||
elif spec_list:
|
||||
uc = upper_constraints[name][0][0]
|
||||
gr = global_requirements[name][0][0]
|
||||
spec_gr = SpecifierSet(gr.specifiers)
|
||||
for req, _ in spec_list:
|
||||
specs = SpecifierSet(req.specifiers)
|
||||
# This assumes uc will only have == specifiers
|
||||
for uc_spec in SpecifierSet(uc.specifiers):
|
||||
# if the uc version isn't in the lower specifier
|
||||
# then something is wrong.
|
||||
if Version(uc_spec.version) not in specs:
|
||||
print(
|
||||
u'%s must be <= %s from upper-constraints and '
|
||||
'include the upper-constraints version' %
|
||||
(name, uc_spec.version))
|
||||
error_count += 1
|
||||
continue
|
||||
if args.gr_check:
|
||||
for spec in specs:
|
||||
# g-r will mostly define blocked versions. And a
|
||||
# local project may define there own, so there is
|
||||
# no point checking a != specifier
|
||||
if spec.operator == '!=':
|
||||
continue
|
||||
if spec.version not in spec_gr:
|
||||
print(
|
||||
u'Specifier %s from %s is failing check '
|
||||
'from global-requirements specifiers %s' %
|
||||
(spec.version, name, str(spec_gr)))
|
||||
error_count += 1
|
||||
continue
|
||||
|
||||
return 1 if error_count else 0
|
@ -89,6 +89,11 @@ def make_project(fixture):
|
||||
|
||||
global_reqs = requirement.parse(
|
||||
open("openstack_requirements/tests/files/gr-base.txt", "rt").read())
|
||||
upper_constraints = requirement.parse(
|
||||
open("openstack_requirements/tests/files/upper-constraints.txt",
|
||||
"rt").read())
|
||||
blacklist = requirement.parse(
|
||||
open("openstack_requirements/tests/files/blacklist.txt", "rt").read())
|
||||
pbr_project = make_project(pbr_fixture)
|
||||
project_project = make_project(project_fixture)
|
||||
bad_project = make_project(bad_project_fixture)
|
||||
|
11
openstack_requirements/tests/files/blacklist.txt
Normal file
11
openstack_requirements/tests/files/blacklist.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# linters - each project may have a different version with loose convergence
|
||||
# over time.
|
||||
flake8
|
||||
flake8_docstrings
|
||||
flake8-import-order
|
||||
hacking
|
||||
mccabe
|
||||
pep257
|
||||
pep8
|
||||
pyflakes
|
||||
pylint
|
@ -4,7 +4,7 @@
|
||||
greenlet>=0.3.1
|
||||
|
||||
# < 0.8.0/0.8 does not work, see https://bugs.launchpad.net/bugs/1153983
|
||||
SQLAlchemy>=0.7.8,<=0.7.99
|
||||
SQLAlchemy>=0.7.8,<=1.0.17
|
||||
anyjson>=0.3.3
|
||||
eventlet>=0.9.12
|
||||
PasteDeploy
|
||||
@ -22,7 +22,7 @@ oslo.config>=1.1.0
|
||||
|
||||
|
||||
# For Swift storage backend.
|
||||
python-swiftclient>=1.2,<2
|
||||
python-swiftclient>=1.2,<4
|
||||
|
||||
# Note you will need gcc buildtools installed and must
|
||||
# have installed libxml headers for lxml to be successfully
|
||||
|
@ -4,7 +4,7 @@ discover
|
||||
feedparser
|
||||
fixtures>=0.3.12
|
||||
mox==0.5.3
|
||||
mox3==0.7.3
|
||||
mox3==0.21.0
|
||||
MySQL-python
|
||||
psycopg2
|
||||
pylint==0.25.2
|
||||
|
507
openstack_requirements/tests/files/upper-constraints.txt
Normal file
507
openstack_requirements/tests/files/upper-constraints.txt
Normal file
@ -0,0 +1,507 @@
|
||||
voluptuous===0.9.3
|
||||
chardet===2.3.0
|
||||
enum-compat===0.0.2
|
||||
rsa===3.4.2
|
||||
restructuredtext-lint===1.0.1
|
||||
netmiko===1.2.8
|
||||
PasteDeploy===1.5.2
|
||||
typing===3.5.3.0
|
||||
python-saharaclient===1.1.0
|
||||
Routes===2.4.1
|
||||
rtslib-fb===2.1.63
|
||||
smmap===0.9.0
|
||||
XStatic-Angular-Bootstrap===2.2.0.0
|
||||
WebOb===1.6.3
|
||||
pecan===1.2.1
|
||||
ryu===4.12
|
||||
os-api-ref===1.3.0
|
||||
oslo.concurrency===3.19.0
|
||||
websocket-client===0.40.0
|
||||
osprofiler===1.6.0
|
||||
bandit===1.4.0
|
||||
tabulate===0.7.7
|
||||
python-ironic-inspector-client===1.11.0
|
||||
lxml===3.7.3
|
||||
python-kingbirdclient===0.1.0
|
||||
pytest===3.0.6
|
||||
python-etcd===0.4.5
|
||||
cursive===0.1.1
|
||||
oslo.service===1.20.0
|
||||
django-appconf===1.0.2
|
||||
pykerberos===1.1.14
|
||||
certifi===2017.1.23
|
||||
requests-aws===0.1.8
|
||||
alabaster===0.7.10
|
||||
pbr===2.0.0
|
||||
microversion-parse===0.1.4
|
||||
Pint===0.7.2
|
||||
oslo.i18n===3.13.0
|
||||
jsonpath-rw-ext===1.1.1
|
||||
python-mistralclient===3.0.0
|
||||
oslo.context===2.13.0
|
||||
python-senlinclient===1.2.0
|
||||
rcssmin===1.0.6
|
||||
pycadf===2.5.0
|
||||
pysendfile===2.0.1
|
||||
fixtures===3.0.0
|
||||
neutron-lib===1.2.0
|
||||
pystache===0.5.4
|
||||
XStatic-Font-Awesome===4.7.0.0
|
||||
nose===1.3.7
|
||||
click-spinner===0.1.7
|
||||
nosehtmloutput===0.0.5
|
||||
waitress===1.0.2
|
||||
mistral===4.0.0
|
||||
os-refresh-config===6.0.0
|
||||
jsbeautifier===1.6.11;python_version=='3.4'
|
||||
jsbeautifier===1.6.11;python_version=='3.5'
|
||||
pysnmp===4.3.4
|
||||
Mako===1.0.6
|
||||
XStatic-angular-ui-router===0.3.1.2
|
||||
pyScss===1.3.4
|
||||
XStatic-jQuery===1.10.2.1
|
||||
jsonmodels===2.1.5
|
||||
ddt===1.1.1
|
||||
ipaddress===1.0.18
|
||||
python-freezerclient===1.2.0
|
||||
os-xenapi===0.1.1
|
||||
python-vitrageclient===1.1.1
|
||||
nosexcover===1.0.11
|
||||
krest===1.3.1
|
||||
psycopg2===2.7
|
||||
networkx===1.11
|
||||
bashate===0.5.1
|
||||
XStatic-Angular===1.5.8.0
|
||||
pyngus===2.2.0
|
||||
Pillow===4.0.0
|
||||
python-mimeparse===1.6.0
|
||||
tripleo-common===6.0.0
|
||||
Tempita===0.5.2
|
||||
ply===3.10
|
||||
simplejson===3.10.0
|
||||
suds-jurko===0.6
|
||||
python-swiftclient===3.3.0
|
||||
pyOpenSSL===16.2.0
|
||||
monasca-common===1.5.0
|
||||
hyperframe===4.0.2;python_version=='3.4'
|
||||
hyperframe===4.0.2;python_version=='3.5'
|
||||
cssutils===1.0.2;python_version=='3.4'
|
||||
cssutils===1.0.2;python_version=='3.5'
|
||||
scipy===0.19.0
|
||||
MySQL-python===1.2.5;python_version=='2.7'
|
||||
XStatic-Jasmine===2.4.1.1
|
||||
python-glanceclient===2.6.0
|
||||
pyinotify===0.9.6
|
||||
debtcollector===1.12.0
|
||||
requests-unixsocket===0.1.5
|
||||
asn1crypto===0.21.1
|
||||
croniter===0.3.15
|
||||
python-watcherclient===1.0.0
|
||||
MarkupSafe===1.0
|
||||
pypowervm===1.0.0.4.1
|
||||
doc8===0.7.0
|
||||
pymongo===3.4.0
|
||||
sqlparse===0.2.3
|
||||
oslotest===2.14.0
|
||||
jsonpointer===1.10
|
||||
netaddr===0.7.19
|
||||
pyghmi===1.0.18
|
||||
sphinxcontrib-blockdiag===1.5.5
|
||||
kaitaistruct===0.6;python_version=='3.4'
|
||||
kaitaistruct===0.6;python_version=='3.5'
|
||||
thrift===0.10.0;python_version=='2.7'
|
||||
gnocchiclient===3.1.1
|
||||
wcwidth===0.1.7
|
||||
jsonpath-rw===1.4.0
|
||||
prettytable===0.7.2
|
||||
vine===1.1.3
|
||||
taskflow===2.10.0
|
||||
traceback2===1.4.0
|
||||
semantic-version===2.6.0
|
||||
tablib===0.11.4
|
||||
astroid===1.3.8
|
||||
deprecation===1.0
|
||||
SQLAlchemy===1.0.17
|
||||
pyroute2===0.4.13
|
||||
kazoo===2.2.1
|
||||
XStatic-roboto-fontface===0.5.0.0
|
||||
pyudev===0.21.0
|
||||
eventlet===0.19.0
|
||||
openstack-doc-tools===1.5.0
|
||||
frozendict===1.2
|
||||
oslo.messaging===5.18.0
|
||||
extras===1.0.0
|
||||
PyJWT===1.4.2
|
||||
paramiko===2.1.2
|
||||
ordereddict===1.1
|
||||
reno===2.1.2
|
||||
unicodecsv===0.14.1;python_version=='2.7'
|
||||
imagesize===0.7.1
|
||||
pathlib===1.0.1;python_version=='2.7'
|
||||
urllib3===1.20
|
||||
graphviz===0.6
|
||||
PyKMIP===0.6.0
|
||||
python-subunit===1.2.0
|
||||
tornado===4.4.2;python_version=='3.4'
|
||||
tornado===4.4.2;python_version=='3.5'
|
||||
pycparser===2.17
|
||||
mock===2.0.0
|
||||
PyYAML===3.12
|
||||
beautifulsoup4===4.5.3
|
||||
ovs===2.7.0
|
||||
cryptography===1.8.1
|
||||
backports.ssl-match-hostname===3.5.0.1
|
||||
pylxd===2.2.3
|
||||
anyjson===0.3.3
|
||||
requests-mock===1.3.0
|
||||
os-apply-config===6.0.0
|
||||
oslosphinx===4.11.0
|
||||
mox3===0.21.0
|
||||
gunicorn===19.7.0
|
||||
unittest2===1.1.0
|
||||
django-compressor===2.1.1
|
||||
libvirt-python===3.1.0
|
||||
tzlocal===1.3
|
||||
python-novaclient===7.1.0
|
||||
bcrypt===3.1.3
|
||||
os-client-config===1.26.0
|
||||
XStatic-Angular-Gettext===2.3.8.0
|
||||
Pygments===2.2.0
|
||||
XStatic-Hogan===2.0.0.2
|
||||
XStatic-objectpath===1.2.1.0
|
||||
python-manilaclient===1.14.0
|
||||
requests===2.12.5
|
||||
snowballstemmer===1.2.1
|
||||
Jinja2===2.9.5
|
||||
XStatic-Bootstrap-SCSS===3.3.7.1
|
||||
pyzabbix===0.7.4
|
||||
ptyprocess===0.5.1
|
||||
amqp===2.1.3
|
||||
ruamel.yaml===0.13.14;python_version=='3.4'
|
||||
ruamel.yaml===0.13.14;python_version=='3.5'
|
||||
websockify===0.8.0
|
||||
html2text===2016.9.19;python_version=='3.4'
|
||||
html2text===2016.9.19;python_version=='3.5'
|
||||
XStatic-JQuery.quicksearch===2.0.3.1
|
||||
mpmath===0.19
|
||||
XStatic-JQuery-Migrate===1.2.1.1
|
||||
appdirs===1.4.3
|
||||
tinyrpc===0.5
|
||||
influxdb===4.0.0
|
||||
funcparserlib===0.3.6
|
||||
passlib===1.7.1
|
||||
dib-utils===0.0.11
|
||||
cliff===2.4.0
|
||||
os-brick===1.11.0
|
||||
trollius===2.1
|
||||
scp===0.10.2
|
||||
python-zaqarclient===1.4.0
|
||||
funcsigs===1.0.2;python_version=='2.7'
|
||||
zhmcclient===0.10.0
|
||||
dnspython3===1.15.0;python_version=='3.4'
|
||||
dnspython3===1.15.0;python_version=='3.5'
|
||||
ldappool===2.0.0
|
||||
termcolor===1.1.0
|
||||
hpack===2.3.0;python_version=='3.4'
|
||||
hpack===2.3.0;python_version=='3.5'
|
||||
hiredis===0.2.0
|
||||
google-api-python-client===1.6.2
|
||||
castellan===0.5.0
|
||||
oslo.versionedobjects===1.22.0
|
||||
webcolors===1.7
|
||||
aodhclient===0.9.0
|
||||
autobahn===0.17.2
|
||||
SQLAlchemy-Utils===0.32.12
|
||||
coverage===4.3.4
|
||||
freezegun===0.3.8
|
||||
python-pytun===2.2.1
|
||||
pyperclip===1.5.27;python_version=='3.4'
|
||||
pyperclip===1.5.27;python_version=='3.5'
|
||||
cassandra-driver===3.8.0
|
||||
mox===0.5.3
|
||||
XStatic-Angular-Schema-Form===0.8.13.0
|
||||
gabbi===1.32.0
|
||||
XStatic-bootswatch===3.3.7.0
|
||||
XStatic-term.js===0.0.7.0
|
||||
oslo.log===3.21.0
|
||||
nodeenv===1.1.2
|
||||
pylev===1.3.0
|
||||
python-searchlightclient===1.1.0
|
||||
oslo.middleware===3.24.0
|
||||
brotlipy===0.6.0;python_version=='3.4'
|
||||
brotlipy===0.6.0;python_version=='3.5'
|
||||
XStatic-mdi===1.4.57.0
|
||||
django-pyscss===2.0.2
|
||||
uritemplate===3.0.0
|
||||
django-babel===0.5.1
|
||||
docutils===0.13.1
|
||||
notifier===1.0.3
|
||||
pycrypto===2.6.1
|
||||
ujson===1.35
|
||||
selenium===3.3.0
|
||||
mypy===0.501;python_version=='3.4'
|
||||
mypy===0.501;python_version=='3.5'
|
||||
dogtag-pki===10.3.5.1
|
||||
sphinxcontrib-seqdiag===0.8.5
|
||||
os-win===1.4.1
|
||||
retrying===1.3.3
|
||||
pathlib2===2.2.1
|
||||
pydotplus===2.0.2
|
||||
urwid===1.3.1;python_version=='3.4'
|
||||
urwid===1.3.1;python_version=='3.5'
|
||||
singledispatch===3.4.0.3;python_version=='2.7'
|
||||
oslo.serialization===2.17.0
|
||||
warlock===1.2.0
|
||||
sphinxcontrib-httpdomain===1.5.0
|
||||
murano-pkg-check===0.3.0
|
||||
oslo.vmware===2.18.0
|
||||
sqlalchemy-migrate===0.11.0
|
||||
gitdb===0.6.4
|
||||
python-monascaclient===1.5.0
|
||||
ldap3===2.2.1
|
||||
automaton===1.8.0
|
||||
argh===0.26.2;python_version=='3.4'
|
||||
argh===0.26.2;python_version=='3.5'
|
||||
keyring===10.3
|
||||
testscenarios===0.5.0
|
||||
sphinxcontrib-pecanwsme===0.8.0
|
||||
enum34===1.1.6
|
||||
packaging===16.8
|
||||
nose-exclude===0.5.0
|
||||
psutil===5.2.0
|
||||
py===1.4.32
|
||||
txaio===2.6.1
|
||||
elasticsearch===2.4.1
|
||||
django-nose===1.4.4
|
||||
XStatic-JQuery.TableSorter===2.14.5.1
|
||||
pifpaf===0.25.1
|
||||
pysmi===0.0.7
|
||||
blockdiag===1.5.3
|
||||
testtools===2.2.0
|
||||
Parsley===1.3
|
||||
XStatic-tv4===1.2.7.0
|
||||
positional===1.1.1
|
||||
XStatic-JSEncrypt===2.3.1.1
|
||||
python-cinderclient===1.11.0
|
||||
keystonemiddleware===4.14.0
|
||||
django-formtools===2.0
|
||||
python-ceilometerclient===2.8.0
|
||||
XStatic-Spin===1.2.5.2
|
||||
SecretStorage===2.3.1
|
||||
XStatic-Rickshaw===1.5.0.0
|
||||
iso8601===0.1.11
|
||||
tooz===1.50.0
|
||||
linecache2===1.0.0
|
||||
oauth2client===3.0.0
|
||||
idna===2.5
|
||||
python-karborclient===0.1.3
|
||||
weakrefmethod===1.0.3;python_version=='2.7'
|
||||
PuLP===1.6.5
|
||||
crc16===0.1.1
|
||||
os-dpm===1.0.0
|
||||
python-neutronclient===6.1.0
|
||||
pika===0.10.0
|
||||
oslo.cache===1.18.0
|
||||
WebTest===2.0.26
|
||||
openstack.nose-plugin===0.11
|
||||
os-collect-config===6.0.0
|
||||
python-qpid-proton===0.17.0
|
||||
pysaml2===4.0.2
|
||||
oslo.reports===1.18.0
|
||||
ceilometermiddleware===1.0.1
|
||||
python-nss===1.0.1
|
||||
testrepository===0.0.20
|
||||
sympy===1.0
|
||||
sphinxmark===0.1.17
|
||||
osc-lib===1.3.0
|
||||
python-consul===0.7.0
|
||||
seqdiag===0.9.5
|
||||
numpy===1.12.0
|
||||
repoze.who===2.3
|
||||
Sphinx===1.5.3
|
||||
oslo.config===3.23.0
|
||||
tempest===15.0.0
|
||||
django-floppyforms===1.7.0
|
||||
openstackdocstheme===1.6.1
|
||||
progressbar2===3.12.0
|
||||
zake===0.2.2
|
||||
python-solumclient===2.2.0
|
||||
PyMySQL===0.7.10
|
||||
kubernetes===1.0.0
|
||||
httplib2===0.10.3
|
||||
os-cloud-config===6.0.0
|
||||
bottle===0.12.13
|
||||
betamax===0.8.0
|
||||
construct===2.8.10
|
||||
pyparsing===2.2.0
|
||||
dogpile.cache===0.6.2
|
||||
python-barbicanclient===4.2.0
|
||||
blinker===1.4;python_version=='3.4'
|
||||
blinker===1.4;python_version=='3.5'
|
||||
WSME===0.9.2
|
||||
msgpack-python===0.4.8
|
||||
proboscis===1.2.6.0
|
||||
fortiosclient===0.0.2
|
||||
stevedore===1.21.0
|
||||
botocore===1.5.24
|
||||
xmltodict===0.10.2
|
||||
pyasn1===0.2.3
|
||||
python-utils===2.0.1
|
||||
oslo.rootwrap===5.5.0
|
||||
Django===1.8.17
|
||||
pexpect===4.2.1
|
||||
cmd2===0.7.0
|
||||
redis===2.10.5
|
||||
jmespath===0.9.2
|
||||
click===6.7
|
||||
docker-pycreds===0.2.1
|
||||
XStatic-smart-table===1.4.13.2
|
||||
kuryr-lib===0.3.0
|
||||
scrypt===0.8.0
|
||||
jsonpatch===1.15
|
||||
typed-ast===1.0.2;python_version=='3.4'
|
||||
typed-ast===1.0.2;python_version=='3.5'
|
||||
os-testr===0.8.0
|
||||
stomp.py===4.1.17
|
||||
xattr===0.9.1
|
||||
python-memcached===1.58
|
||||
openstacksdk===0.9.13
|
||||
six===1.10.0
|
||||
h2===2.6.0;python_version=='3.4'
|
||||
h2===2.6.0;python_version=='3.5'
|
||||
dulwich===0.17.1
|
||||
pykafka===2.5.0
|
||||
kombu===4.0.1
|
||||
mitmproxy===2.0.0;python_version=='3.4'
|
||||
mitmproxy===2.0.0;python_version=='3.5'
|
||||
yaql===1.1.3
|
||||
requestsexceptions===1.2.0
|
||||
testresources===2.0.1
|
||||
falcon===1.1.0
|
||||
pycryptodome===3.4.5
|
||||
pyldap===2.4.28
|
||||
Flask-RESTful===0.3.5
|
||||
GitPython===2.1.3
|
||||
python-ironicclient===1.11.1
|
||||
XStatic===1.0.1
|
||||
click-repl===0.1.1
|
||||
XStatic-Angular-FileUpload===12.0.4.0
|
||||
python-openstackclient===3.9.0
|
||||
pika-pool===0.1.3
|
||||
pyzmq===16.0.2
|
||||
EditorConfig===0.12.1;python_version=='3.4'
|
||||
EditorConfig===0.12.1;python_version=='3.5'
|
||||
oslo.db===4.18.0
|
||||
simplegeneric===0.8.1
|
||||
abclient===0.2.3
|
||||
pymemcache===1.4.2
|
||||
wrapt===1.10.8
|
||||
oslo.privsep===1.17.0
|
||||
zope.interface===4.3.3
|
||||
oslo.policy===1.19.0
|
||||
python-muranoclient===0.12.0
|
||||
pyeclib===1.4.0
|
||||
django-openstack-auth===3.1.1
|
||||
wsgi-intercept===1.5.0
|
||||
ndg-httpsclient===0.4.2;python_version=='2.7'
|
||||
tempest-lib===1.0.0
|
||||
spec-cleaner===0.9.2
|
||||
repoze.lru===0.6
|
||||
rfc3986===0.4.1
|
||||
tenacity===4.0.0
|
||||
logilab-common===1.3.0
|
||||
XStatic-Magic-Search===0.2.5.1
|
||||
python-designateclient===2.6.0
|
||||
Paste===2.0.3
|
||||
pycodestyle===2.3.1
|
||||
boto===2.46.1
|
||||
functools32===3.2.3.post2;python_version=='2.7'
|
||||
watchdog===0.8.3;python_version=='3.4'
|
||||
watchdog===0.8.3;python_version=='3.5'
|
||||
gevent===1.2.1
|
||||
os-vif===1.4.0
|
||||
Werkzeug===0.12
|
||||
pyasn1-modules===0.0.8
|
||||
APScheduler===3.3.1
|
||||
monotonic===1.2
|
||||
python-smaugclient===0.0.8
|
||||
python-troveclient===2.8.0
|
||||
cliff-tablib===2.0
|
||||
XStatic-Bootstrap-Datepicker===1.3.1.0
|
||||
CouchDB===1.1
|
||||
netifaces===0.10.5
|
||||
cachetools===2.0.0
|
||||
ws4py===0.3.4
|
||||
backports-abc===0.5;python_version=='3.4'
|
||||
backports-abc===0.5;python_version=='3.5'
|
||||
keystoneauth1===2.18.0
|
||||
statsd===3.2.1
|
||||
XenAPI===1.2
|
||||
python-keystoneclient===3.10.0
|
||||
demjson===2.2.4
|
||||
diskimage-builder===1.28.0
|
||||
heat-translator===0.7.0
|
||||
python-magnumclient===2.5.0
|
||||
docker===2.1.0
|
||||
prompt-toolkit===1.0.13
|
||||
pathtools===0.1.2;python_version=='3.4'
|
||||
pathtools===0.1.2;python_version=='3.5'
|
||||
qpid-python===0.32.1;python_version=='2.7'
|
||||
contextlib2===0.5.4
|
||||
XStatic-Angular-lrdragndrop===1.0.2.2
|
||||
python-congressclient===1.6.0
|
||||
aniso8601===1.2.0
|
||||
rjsmin===1.0.12
|
||||
icalendar===3.11.3
|
||||
decorator===4.0.11
|
||||
cffi===1.9.1
|
||||
futurist===0.22.0
|
||||
jsonschema===2.6.0
|
||||
alembic===0.9.1
|
||||
glance-store===0.20.0
|
||||
sphinx-testing===0.7.1
|
||||
dnspython===1.15.0
|
||||
oauthlib===2.0.1
|
||||
Babel===2.3.4
|
||||
logutils===0.3.4.1
|
||||
scandir===1.5
|
||||
sphinxcontrib-fulltoc===1.1
|
||||
smmap2===2.0.1
|
||||
olefile===0.44
|
||||
greenlet===0.4.12
|
||||
xvfbwrapper===0.2.9
|
||||
futures===3.0.5
|
||||
tosca-parser===0.7.0
|
||||
Flask===0.12
|
||||
pymod2pkg===0.7.2
|
||||
happybase===0.9;python_version=='2.7'
|
||||
marathon===0.8.11
|
||||
docker-py===1.10.6
|
||||
fasteners===0.14.1
|
||||
sortedcontainers===1.5.7;python_version=='3.4'
|
||||
sortedcontainers===1.5.7;python_version=='3.5'
|
||||
python-tackerclient===0.9.0
|
||||
python-heatclient===1.8.0
|
||||
kafka-python===1.3.2
|
||||
oslo.utils===3.23.0
|
||||
python-editor===1.0.3
|
||||
gitdb2===2.0.0
|
||||
requests-kerberos===0.11.0
|
||||
itsdangerous===0.24
|
||||
XStatic-jquery-ui===1.12.0.1
|
||||
monasca-statsd===1.5.0
|
||||
python-dateutil===2.6.0
|
||||
virtualenv===15.1.0
|
||||
colorama===0.3.7
|
||||
ironic-lib===2.6.0
|
||||
pytz===2016.10
|
||||
XStatic-D3===3.5.17.0
|
||||
sysv-ipc===0.7.0
|
||||
scikit-learn===0.18.1
|
||||
wsgiref==0.1.2
|
||||
discover==0.4.0
|
||||
oslo.sphinx==0.9.27
|
||||
python-ldap==2.3.13
|
||||
argparse==1.4.0
|
||||
setuptools-git==25.1.4
|
||||
feedparser==5.2.1
|
196
openstack_requirements/tests/test_check_constraints.py
Normal file
196
openstack_requirements/tests/test_check_constraints.py
Normal file
@ -0,0 +1,196 @@
|
||||
# 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.
|
||||
from __future__ import print_function
|
||||
|
||||
import io
|
||||
import mock
|
||||
import os
|
||||
import testscenarios
|
||||
import testtools
|
||||
|
||||
from openstack_requirements.cmds import check_exists
|
||||
from openstack_requirements import project
|
||||
from openstack_requirements.tests import common
|
||||
|
||||
load_tests = testscenarios.load_tests_apply_scenarios
|
||||
|
||||
|
||||
def mock_read_requirements_file(filename):
|
||||
if os.path.basename(filename) == 'upper-constraints.txt':
|
||||
return common.upper_constraints
|
||||
elif os.path.basename(filename) == 'global-requirements.txt':
|
||||
return common.global_reqs
|
||||
elif os.path.basename(filename) == 'blacklist.txt':
|
||||
return common.blacklist
|
||||
else:
|
||||
raise IOError('No such file or directory: %s' % filename)
|
||||
|
||||
|
||||
class CheckExistsTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CheckExistsTest, self).setUp()
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
@mock.patch('openstack_requirements.project.read',
|
||||
return_value=common.project_project)
|
||||
def test_good_project(self, mock_project_read):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
def test_project_missing_from_uc(self):
|
||||
self.useFixture(common.project_fixture)
|
||||
orig_mocked_read_req = check_exists.read_requirements_file
|
||||
read_req_path = ('openstack_requirements.cmds.check_exists.'
|
||||
'read_requirements_file')
|
||||
|
||||
def remove_req_read_reqs_file(filename):
|
||||
if filename == 'upper-constraints.txt':
|
||||
upper_cons = common.upper_constraints.copy()
|
||||
upper_cons.pop('six')
|
||||
return upper_cons
|
||||
|
||||
return orig_mocked_read_req(filename)
|
||||
|
||||
expected_out = ('six from requirements.txt not found in'
|
||||
' upper-constraints')
|
||||
|
||||
# Start capturing some output
|
||||
mock_stdout = io.StringIO()
|
||||
with mock.patch('openstack_requirements.project.read',
|
||||
return_value=common.project_project), \
|
||||
mock.patch('sys.stdout', mock_stdout), \
|
||||
mock.patch(read_req_path, remove_req_read_reqs_file):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 1)
|
||||
self.assertIn(expected_out, mock_stdout.getvalue())
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
def test_project_missing_from_gr(self):
|
||||
self.useFixture(common.project_fixture)
|
||||
|
||||
# Add some random package that wont exist in G-R
|
||||
with open(common.project_fixture.req_file, 'a') as req_file:
|
||||
req_file.write(u'SomeRandomModule #Some random module\n')
|
||||
req_file.flush()
|
||||
|
||||
expected_out = ('somerandommodule from requirements.txt not found in'
|
||||
' global-requirements')
|
||||
|
||||
# Start capturing some output
|
||||
mock_stdout = io.StringIO()
|
||||
proj_read = project.read(common.project_fixture.root)
|
||||
with mock.patch('openstack_requirements.project.read',
|
||||
return_value=proj_read), \
|
||||
mock.patch('sys.stdout', mock_stdout):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 1)
|
||||
self.assertIn(expected_out, mock_stdout.getvalue())
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
def test_project_multiple_missing_from_uc_and_gr(self):
|
||||
self.useFixture(common.project_fixture)
|
||||
orig_mocked_read_req = check_exists.read_requirements_file
|
||||
read_req_path = ('openstack_requirements.cmds.check_exists.'
|
||||
'read_requirements_file')
|
||||
|
||||
def remove_req_read_reqs_file(filename):
|
||||
if filename == 'upper-constraints.txt':
|
||||
upper_cons = common.upper_constraints.copy()
|
||||
upper_cons.pop('lxml')
|
||||
return upper_cons
|
||||
|
||||
return orig_mocked_read_req(filename)
|
||||
|
||||
new_reqs = '>1.10.0\nsomerandommodule\n'
|
||||
|
||||
# lets change the six requirement not include the u-c version
|
||||
proj_read = project.read(common.project_fixture.root)
|
||||
proj_read['requirements']['requirements.txt'] = \
|
||||
proj_read['requirements']['requirements.txt'][:-1] + new_reqs
|
||||
proj_read['requirements']['test-requirements.txt'] = \
|
||||
proj_read['requirements']['test-requirements.txt'] + \
|
||||
'anotherrandommodule\n'
|
||||
|
||||
expected_outs = [
|
||||
'lxml from requirements.txt not found in upper-constraints',
|
||||
'somerandommodule from requirements.txt not found in '
|
||||
'global-requirements',
|
||||
'anotherrandommodule from test-requirements.txt not found in '
|
||||
'global-requirements',
|
||||
'six must be <= 1.10.0 from upper-constraints and include the '
|
||||
'upper-constraints version']
|
||||
|
||||
# Start capturing some output
|
||||
mock_stdout = io.StringIO()
|
||||
with mock.patch('openstack_requirements.project.read',
|
||||
return_value=proj_read), \
|
||||
mock.patch('sys.stdout', mock_stdout), \
|
||||
mock.patch(read_req_path, remove_req_read_reqs_file):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 1)
|
||||
for expected in expected_outs:
|
||||
self.assertIn(expected, mock_stdout.getvalue())
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
def test_project_req_bigger_then_uc(self):
|
||||
self.useFixture(common.project_fixture)
|
||||
|
||||
# lets change the six requirement not include the u-c version
|
||||
proj_read = project.read(common.project_fixture.root)
|
||||
proj_read['requirements']['requirements.txt'] = \
|
||||
proj_read['requirements']['requirements.txt'][:-1] + '>1.10.0\n'
|
||||
expected_out = ('six must be <= 1.10.0 from upper-constraints and '
|
||||
'include the upper-constraints version')
|
||||
|
||||
# Start capturing some output
|
||||
mock_stdout = io.StringIO()
|
||||
with mock.patch('openstack_requirements.project.read',
|
||||
return_value=proj_read), \
|
||||
mock.patch('sys.stdout', mock_stdout):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 1)
|
||||
self.assertIn(expected_out, mock_stdout.getvalue())
|
||||
|
||||
@mock.patch(
|
||||
'openstack_requirements.cmds.check_exists.read_requirements_file',
|
||||
mock_read_requirements_file)
|
||||
def test_project_req_not_include_uc_version(self):
|
||||
self.useFixture(common.project_fixture)
|
||||
|
||||
# lets change the six requirement not include the u-c version
|
||||
proj_read = project.read(common.project_fixture.root)
|
||||
proj_read['requirements']['requirements.txt'] = \
|
||||
proj_read['requirements']['requirements.txt'][:-1] + \
|
||||
'<1.10.0,>1.10.0\n'
|
||||
expected_out = ('six must be <= 1.10.0 from upper-constraints and '
|
||||
'include the upper-constraints version')
|
||||
|
||||
# Start capturing some output
|
||||
mock_stdout = io.StringIO()
|
||||
with mock.patch('openstack_requirements.project.read',
|
||||
return_value=proj_read), \
|
||||
mock.patch('sys.stdout', mock_stdout):
|
||||
ret = check_exists.main([common.project_fixture.root])
|
||||
self.assertEqual(ret, 1)
|
||||
self.assertIn(expected_out, mock_stdout.getvalue())
|
@ -52,7 +52,7 @@ class SmokeTest(testtools.TestCase):
|
||||
expected = ('Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, pycrypto, 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,<=0.7.99 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
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
|
||||
@ -61,14 +61,14 @@ class SmokeTest(testtools.TestCase):
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
pycrypto>=2.1.0alpha1 -> pycrypto>=2.6
|
||||
python-swiftclient>=1.2,<2 -> python-swiftclient>=1.2
|
||||
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.7.3 -> mox3>=0.7.0
|
||||
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)
|
||||
@ -157,7 +157,7 @@ class UpdateTest(testtools.TestCase):
|
||||
expected = ('Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, pycrypto, 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,<=0.7.99 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
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
|
||||
@ -166,14 +166,14 @@ class UpdateTest(testtools.TestCase):
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
pycrypto>=2.1.0alpha1 -> pycrypto>=2.6
|
||||
python-swiftclient>=1.2,<2 -> python-swiftclient>=1.2
|
||||
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.7.3 -> mox3>=0.7.0
|
||||
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'])
|
||||
@ -190,7 +190,7 @@ Updated %(project)s/test-requirements.txt:
|
||||
Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb, wsgiref, boto, kombu, pycrypto, 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,<=0.7.99 -> SQLAlchemy<=0.7.99,>=0.7
|
||||
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
|
||||
@ -199,7 +199,7 @@ Version change for: greenlet, SQLAlchemy, eventlet, PasteDeploy, routes, WebOb,
|
||||
boto -> boto>=2.4.0
|
||||
kombu>2.4.7 -> kombu>=2.4.8
|
||||
pycrypto>=2.1.0alpha1 -> pycrypto>=2.6
|
||||
python-swiftclient>=1.2,<2 -> python-swiftclient>=1.2
|
||||
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
|
||||
@ -207,7 +207,7 @@ 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.7.3 -> mox3>=0.7.0
|
||||
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
|
||||
|
@ -39,4 +39,5 @@ console_scripts =
|
||||
validate-constraints = openstack_requirements.cmds.validate:main
|
||||
validate-projects = openstack_requirements.cmds.validate_projects:main
|
||||
normalize-requirements = openstack_requirements.cmds.normalize_requirements:main
|
||||
check-python2-support = openstack_requirements.cmds.check_py2:main
|
||||
check-python2-support = openstack_requirements.cmds.check_py2:main
|
||||
check-constraints = openstack_requirements.cmds.check_exists:main
|
||||
|
Loading…
Reference in New Issue
Block a user