Improve terminology in the requirements tree

There is no real reason we should be using some of the
terms we do, they're outdated, and we're behind other
open-source projects in this respect. Let's switch to
using more inclusive terms in all possible places.

Change-Id: I90ac679c1745a31474c6f24ec7953624ad056d79
This commit is contained in:
Brian Haley 2024-04-30 12:34:26 -04:00
parent 091035a031
commit ea345875cd
16 changed files with 112 additions and 112 deletions

View File

@ -20,7 +20,7 @@ pycodestyle
pylint
yamllint
# The following Neutron libraries need to be blacklisted
# The following Neutron libraries need to be denylisted
# as they do not use cycle-with-intermediary. The only time they
# would be updated is at release time.
networking-bagpipe

View File

@ -242,7 +242,7 @@ keyring # MIT/PSF
ldappool # MPL
# Do not make mock conditional on Python version: we depend on newer code than
# in [most] releases of the Python std library.
# https://github.com/testing-cabal/mock/issues/487 for 4.0.[0-1] blacklist
# https://github.com/testing-cabal/mock/issues/487 for 4.0.[0-1] denylist
mock!=4.0.0,!=4.0.1 # BSD
moto # Apache-2.0
mypy # MIT
@ -486,16 +486,16 @@ storpool.spopenstack # Apache-2.0
## section:internal
##
## Tooling-related caps and blacklists.
## Tooling-related caps and denylists.
pip # MIT
# While setuptools cannot deal with pre-installed incompatible versions,
# setting a lower bound is not harmful - it makes error messages cleaner. DO
# NOT set an upper bound on setuptools, as that will lead to uninstallable
# situations as progressive releases of projects are done.
# Blacklist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951
# Blacklist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086
# Blacklist setuptools 48.0.0, 49.0.0 due to https://github.com/pypa/setuptools/issues/2232
# Denylist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951
# Denylist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086
# Denylist setuptools 48.0.0, 49.0.0 due to https://github.com/pypa/setuptools/issues/2232
setuptools!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0,!=48.0.0,!=49.0.0 # PSF/ZPL
wheel # MIT

View File

@ -215,15 +215,15 @@ def _get_python3_reqs(reqs):
def _validate_one(
name,
reqs,
blacklist,
denylist,
global_reqs,
backports,
allow_3_only=False,
):
"""Returns True if there is a failure."""
if name in blacklist:
# Blacklisted items are not synced and are managed
if name in denylist:
# Denylisted items are not synced and are managed
# by project teams as they see fit, so no further
# testing is needed.
return False
@ -279,7 +279,7 @@ def _validate_one(
def validate(
head_reqs,
blacklist,
denylist,
global_reqs,
backports,
allow_3_only=False,
@ -294,7 +294,7 @@ def validate(
_validate_one(
name,
reqs,
blacklist,
denylist,
global_reqs,
backports,
allow_3_only,
@ -344,7 +344,7 @@ def _find_constraint(req, constraints):
return None
def validate_lower_constraints(req_list, constraints, blacklist):
def validate_lower_constraints(req_list, constraints, denylist):
"""Return True if there is an error.
:param reqs: RequirementsList for the head of the branch
@ -369,7 +369,7 @@ def validate_lower_constraints(req_list, constraints, blacklist):
for name, reqs in freqs.items():
if name in blacklist:
if name in denylist:
continue
if name not in parsed_constraints:

View File

@ -52,12 +52,12 @@ def main():
except pkg_resources.ContextualVersionConflict as e:
if e.dist.key in xfails:
xfail_requirement = xfails[e.dist.key][0][0]
xfail_blacklists = set(xfail_requirement.markers.split(','))
xfail_denylists = set(xfail_requirement.markers.split(','))
conflict = e.dist.as_requirement()
conflict_specifiers = ''.join(conflict.specs[0])
conflict_name = conflict.name.lower()
if (e.required_by.issubset(xfail_blacklists) and
if (e.required_by.issubset(xfail_denylists) and
xfail_requirement.package == conflict_name and
conflict_specifiers == xfail_requirement.specifiers):

View File

@ -40,9 +40,9 @@ def main(args=None):
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')
'-b', '-d', '--denylist',
default='denylist.txt',
help='Path to the denylist.txt file')
parser.add_argument(
'-G', '--gr-check', action='store_true',
help='Do a specifier check of global-requirements')
@ -50,7 +50,7 @@ def main(args=None):
upper_constraints = read_requirements_file(args.upper_constraints)
global_requirements = read_requirements_file(args.global_requirements)
blacklist = read_requirements_file(args.blacklist)
denylist = read_requirements_file(args.denylist)
project_data = project.read(args.project)
error_count = 0
@ -59,7 +59,7 @@ def main(args=None):
% require_file)
requirements = requirement.parse(data)
for name, spec_list in requirements.items():
if not name or name in blacklist:
if not name or name in denylist:
continue
if name not in global_requirements:
print(u'%s from %s not found in global-requirements' % (

View File

@ -108,7 +108,7 @@ def _freeze(requirements, python):
fh.write(b'\n'.join(output))
def _combine_freezes(freezes, blacklist=None):
def _combine_freezes(freezes, denylist=None):
"""Combine multiple freezes into a single structure.
This deals with the variation between different python versions by
@ -116,13 +116,13 @@ def _combine_freezes(freezes, blacklist=None):
versions of a dependency.
:param freezes: A list of (python_version, frozen_requirements) tuples.
:param blacklist: An iterable of package names to exclude. These packages
:param denylist: An iterable of package names to exclude. These packages
won't be included in the output.
:return: A list of '\n' terminated lines for a requirements file.
"""
packages = {} # {package : {version : [py_version]}}
excludes = frozenset((requirement.canonical_name(s)
for s in blacklist) if blacklist else ())
for s in denylist) if denylist else ())
reference_versions = []
for py_version, freeze in freezes:
if py_version in reference_versions:
@ -180,10 +180,10 @@ def _validate_options(options):
raise Exception(
"Requirements file %(req)s not found."
% dict(req=options.requirements))
if options.blacklist and not os.path.exists(options.blacklist):
if options.denylist and not os.path.exists(options.denylist):
raise Exception(
"Blacklist file %(path)s not found."
% dict(path=options.blacklist))
"Denylist file %(path)s not found."
% dict(path=options.denylist))
version_map = {}
for map_entry in options.version_map:
if ':' not in map_entry:
@ -196,7 +196,7 @@ def _validate_options(options):
options.version_map = version_map
def _parse_blacklist(path):
def _parse_denylist(path):
"""Return the strings from path if it is not None."""
if path is None:
return []
@ -226,7 +226,7 @@ def main(argv=None, stdout=None):
parser.add_option(
"-r", dest="requirements", help="Requirements file to process.")
parser.add_option(
"-b", dest="blacklist",
"-b", "-d", dest="denylist",
help="Filename of a list of package names to exclude.")
parser.add_option(
"--version-map", dest='version_map', default=[], action='append',
@ -242,8 +242,8 @@ def main(argv=None, stdout=None):
freezes = [
_freeze(options.requirements, python) for python in options.pythons]
_clone_versions(freezes, options)
blacklist = _parse_blacklist(options.blacklist)
denylist = _parse_denylist(options.denylist)
frozen = [
*sorted(_combine_freezes(freezes, blacklist), key=_make_sort_key)]
*sorted(_combine_freezes(freezes, denylist), key=_make_sort_key)]
stdout.writelines(frozen)
stdout.flush()

View File

@ -35,9 +35,9 @@ def main():
help='path to the upper-constraints.txt file',
)
parser.add_argument(
'blacklist',
default='blacklist.txt',
help='path to the blacklist.txt file',
'denylist',
default='denylist.txt',
help='path to the denylist.txt file',
)
args = parser.parse_args()
@ -76,11 +76,11 @@ def main():
error_count += 1
# Check that all of the items in the global-requirements list
# appear in exactly one of the constraints file or the blacklist.
print('\nChecking %s' % args.blacklist)
blacklist = read_requirements_file(args.blacklist)
for msg in constraints.check_blacklist_coverage(
global_reqs, constraints_txt, blacklist,
# appear in exactly one of the constraints file or the denylist.
print('\nChecking %s' % args.denylist)
denylist = read_requirements_file(args.denylist)
for msg in constraints.check_denylist_coverage(
global_reqs, constraints_txt, denylist,
os.path.basename(args.upper_constraints)):
print(msg)
error_count += 1

View File

@ -14,7 +14,7 @@ from packaging import specifiers
# FIXME(dhellmann): These items were not in the constraints list but
# should not be blacklisted. We don't know yet what versions they
# should not be denylisted. We don't know yet what versions they
# should have, so just ignore them for a little while until we have
# time to figure that out.
UNCONSTRAINABLE = set([
@ -29,28 +29,28 @@ UNCONSTRAINABLE = set([
])
def check_blacklist_coverage(global_reqs, constraints, blacklist,
constraints_list_name):
def check_denylist_coverage(global_reqs, constraints, denylist,
constraints_list_name):
"""Report any items that are not properly constrained.
Check that all of the items in the global-requirements list
appear either in the constraints file or the blacklist.
appear either in the constraints file or the denylist.
"""
to_be_constrained = (
set(global_reqs.keys()) - set(blacklist.keys())
set(global_reqs.keys()) - set(denylist.keys())
- UNCONSTRAINABLE
)
constrained = set(constraints.keys()) - set([''])
unconstrained = to_be_constrained - constrained
for u in sorted(unconstrained):
yield ('%r appears in global-requirements.txt '
'but not %s or blacklist.txt' % (u, constraints_list_name))
'but not %s or denylist.txt' % (u, constraints_list_name))
# Verify that the blacklist packages are not also listed in
# Verify that the denylist packages are not also listed in
# the constraints file.
dupes = constrained.intersection(set(blacklist.keys()))
dupes = constrained.intersection(set(denylist.keys()))
for d in dupes:
yield ('%r appears in both blacklist.txt and %s'
yield ('%r appears in both denylist.txt and %s'
% (d, constraints_list_name))

View File

@ -78,10 +78,10 @@ class GlobalRequirements(fixtures.Fixture):
self.req_file = os.path.join(self.root, "global-requirements.txt")
shutil.copy(
"openstack_requirements/tests/files/gr-base.txt", self.req_file)
self.blacklist_file = os.path.join(self.root, "blacklist.txt")
self.denylist_file = os.path.join(self.root, "denylist.txt")
shutil.copy(
"openstack_requirements/tests/files/blacklist.txt",
self.blacklist_file)
"openstack_requirements/tests/files/denylist.txt",
self.denylist_file)
# Static data for unit testing.
@ -95,8 +95,8 @@ global_reqs = requirement.parse(
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())
denylist = requirement.parse(
open("openstack_requirements/tests/files/denylist.txt", "rt").read())
pbr_project = make_project(pbr_fixture)
project_project = make_project(project_fixture)
bad_project = make_project(bad_project_fixture)

View File

@ -226,14 +226,14 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
)
def test_blacklisted(self):
# If the package is blacklisted, everything is OK.
def test_denylisted(self):
# If the package is denylisted, everything is OK.
reqs = [
r
for r, line in requirement.parse('name>=1.2,!=1.4')['name']
@ -243,14 +243,14 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse('name'),
denylist=requirement.parse('name'),
backports=self.backports,
global_reqs=global_reqs,
)
)
def test_blacklisted_mismatch(self):
# If the package is blacklisted, it doesn't matter if the
def test_denylisted_mismatch(self):
# If the package is denylisted, it doesn't matter if the
# version matches.
reqs = [
r
@ -261,7 +261,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse('name'),
denylist=requirement.parse('name'),
backports=self.backports,
global_reqs=global_reqs,
)
@ -278,7 +278,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -295,7 +295,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -313,7 +313,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -331,7 +331,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -349,7 +349,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -375,7 +375,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -400,7 +400,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -426,7 +426,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
)
@ -453,7 +453,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
allow_3_only=True,
@ -481,7 +481,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
allow_3_only=True,
@ -508,7 +508,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
allow_3_only=True,
@ -533,7 +533,7 @@ class TestValidateOne(testtools.TestCase):
check._validate_one(
'name',
reqs=reqs,
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
backports=self.backports,
global_reqs=global_reqs,
allow_3_only=True,
@ -561,7 +561,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -579,7 +579,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -597,7 +597,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -614,11 +614,11 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
def test_mismatch_blacklisted(self):
def test_mismatch_denylisted(self):
constraints_content = textwrap.dedent("""
name==1.2
""")
@ -632,7 +632,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse('name'),
denylist=requirement.parse('name'),
)
)
@ -650,7 +650,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -668,7 +668,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -686,7 +686,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -712,7 +712,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -737,7 +737,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -762,7 +762,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)
@ -786,7 +786,7 @@ class TestValidateLowerConstraints(testtools.TestCase):
check.validate_lower_constraints(
req_list=head_reqs,
constraints=project_data['lower-constraints.txt'],
blacklist=requirement.parse(''),
denylist=requirement.parse(''),
)
)

View File

@ -29,8 +29,8 @@ def mock_read_requirements_file(filename):
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
elif os.path.basename(filename) == 'denylist.txt':
return common.denylist
else:
raise IOError('No such file or directory: %s' % filename)

View File

@ -64,42 +64,42 @@ class TestCheckFormat(testtools.TestCase):
)
class TestBlacklistCoverage(testtools.TestCase):
class TestDenylistCoverage(testtools.TestCase):
def test_constrained(self):
global_reqs = requirement.parse("foo>=1.2\nbar>2.0\n")
good_constraints = requirement.parse("foo===1.2.5\nbar==2.1")
blacklist = requirement.parse('flake8\nhacking')
denylist = requirement.parse('flake8\nhacking')
self.assertEqual(
[],
list(constraints.check_blacklist_coverage(
global_reqs, good_constraints, blacklist, 'test'))
list(constraints.check_denylist_coverage(
global_reqs, good_constraints, denylist, 'test'))
)
def test_blacklisted(self):
def test_denylisted(self):
global_reqs = requirement.parse("foo>=1.2\nbar>2.0\n")
good_constraints = requirement.parse("foo===1.2.5\n")
blacklist = requirement.parse('flake8\nhacking\nbar')
denylist = requirement.parse('flake8\nhacking\nbar')
self.assertEqual(
[],
list(constraints.check_blacklist_coverage(
global_reqs, good_constraints, blacklist, 'test'))
list(constraints.check_denylist_coverage(
global_reqs, good_constraints, denylist, 'test'))
)
def test_both(self):
global_reqs = requirement.parse("foo>=1.2\nbar>2.0\n")
good_constraints = requirement.parse("foo===1.2.5\nbar>2.0")
blacklist = requirement.parse('flake8\nhacking\nbar')
results = list(constraints.check_blacklist_coverage(
global_reqs, good_constraints, blacklist, 'test'))
denylist = requirement.parse('flake8\nhacking\nbar')
results = list(constraints.check_denylist_coverage(
global_reqs, good_constraints, denylist, 'test'))
self.assertEqual(1, len(results))
self.assertIn("'bar' appears in both", results[0])
def test_neither(self):
global_reqs = requirement.parse("foo>=1.2\nbar>2.0\n")
good_constraints = requirement.parse("foo===1.2.5\n")
blacklist = requirement.parse('flake8\nhacking')
results = list(constraints.check_blacklist_coverage(
global_reqs, good_constraints, blacklist, 'test'))
denylist = requirement.parse('flake8\nhacking')
results = list(constraints.check_denylist_coverage(
global_reqs, good_constraints, denylist, 'test'))
self.assertEqual(1, len(results))
self.assertIn("'bar' appears in global-requirements.txt", results[0])

View File

@ -97,23 +97,23 @@ class TestCombine(testtools.TestCase):
with testtools.ExpectedException(Exception):
list(generate._combine_freezes([('2.7', []), ('2.7', [])]))
def test_blacklist(self):
blacklist = ['Fixtures']
def test_denylist(self):
denylist = ['Fixtures']
freeze_27 = ('2.7', [('fixtures', '1.2.0')])
freeze_34 = ('3.4', [('fixtures', '1.2.0'), ('enum', '1.5.0')])
self.assertEqual(
["enum===1.5.0;python_version=='3.4'\n"],
list(generate._combine_freezes(
[freeze_27, freeze_34], blacklist=blacklist)))
[freeze_27, freeze_34], denylist=denylist)))
def test_blacklist_with_safe_name(self):
blacklist = ['flake8_docstrings']
def test_denylist_with_safe_name(self):
denylist = ['flake8_docstrings']
freeze_27 = ('2.7', [('flake8-docstrings', '0.2.1.post1'),
('enum', '1.5.0')])
self.assertEqual(
['enum===1.5.0\n'],
list(generate._combine_freezes(
[freeze_27], blacklist=blacklist)))
[freeze_27], denylist=denylist)))
class Namespace(object):

View File

@ -111,8 +111,8 @@ def main():
with tempdir():
with open(reqdir + '/global-requirements.txt', 'rt') as f:
global_reqs = check.get_global_reqs(f.read())
blacklist = requirement.parse(
open(reqdir + '/blacklist.txt', 'rt').read())
denylist = requirement.parse(
open(reqdir + '/denylist.txt', 'rt').read())
backports_file = reqdir + '/backports.txt'
if os.path.exists(backports_file):
backports = requirement.parse(open(backports_file, 'rt').read())
@ -139,7 +139,7 @@ def main():
failed = check.validate(
head_reqs,
blacklist,
denylist,
global_reqs,
list(backports.keys()),
allow_3_only=python_3_branch,
@ -149,7 +149,7 @@ def main():
check.validate_lower_constraints(
head_reqs,
head_proj['lower-constraints.txt'],
blacklist,
denylist,
)
or failed
)

View File

@ -51,13 +51,13 @@ description = Regenerates upper-constraints.txt
# Generate needs an unconstrained install to get new dependencies
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = generate-constraints {posargs: -b blacklist.txt -r global-requirements.txt -p python3.8 -p python3.9 -p python3.10 -p python3.11 > upper-constraints.txt}
commands = generate-constraints {posargs: -d denylist.txt -r global-requirements.txt -p python3.8 -p python3.9 -p python3.10 -p python3.11 > upper-constraints.txt}
[testenv:validate]
allowlist_externals =
validate-constraints
commands =
validate-constraints {toxinidir}/global-requirements.txt {toxinidir}/upper-constraints.txt {toxinidir}/blacklist.txt
validate-constraints {toxinidir}/global-requirements.txt {toxinidir}/upper-constraints.txt {toxinidir}/denylist.txt
[testenv:validate-projects]
allowlist_externals =