[Dependencies][Changed] The roles member

- Each dependency can really have 1 role (even when plural)
- The registered dependency can have multiple roles
- The code assumed the general case, but is impossible
This commit is contained in:
Salvador E. Tropea 2024-01-24 10:35:24 -03:00
parent 6d6075ba6f
commit f5a0231fb4
7 changed files with 61 additions and 96 deletions

View File

@ -1273,7 +1273,7 @@ def print_dependencies(markdown=True, jsn=False, rst=False):
# Compute the importance of each dependency
for dep in RegDependency.get_registered().values():
importance = 0
for r in dep.roles:
for r in dep.role:
local = r.output != 'global'
if r.mandatory:
importance += LOCAL_MANDATORY if local else GLOBAL_MANDATORY
@ -1331,7 +1331,7 @@ def print_dependencies(markdown=True, jsn=False, rst=False):
optional = []
version = None
max_version = None
for r in dep.roles:
for r in dep.role:
if r.mandatory:
needed.append(global2human(r.output))
else:

View File

@ -649,9 +649,9 @@ def check_tool_binary_version(full_name, dep, no_cache=False):
return full_name, None
# Do we need a particular version?
needs = (0, 0, 0)
for r in dep.roles:
if r.version and r.version > needs:
needs = r.version
ver = dep.role.version
if ver and ver > needs:
needs = ver
if needs == (0, 0, 0):
# Any version is Ok
logger.debugl(2, '- No particular version needed')
@ -766,9 +766,9 @@ def check_tool_python_version(mod, dep):
version_check_fail = False
# Do we need a particular version?
needs = (0, 0, 0)
for r in dep.roles:
if r.version and r.version > needs:
needs = r.version
ver = dep.role.version
if ver and ver > needs:
needs = ver
if needs == (0, 0, 0):
# Any version is Ok
logger.debugl(2, '- No particular version needed')
@ -824,23 +824,12 @@ def get_version(role):
return ''
def show_roles(roles, fatal):
optional = []
for r in roles:
if not r.mandatory:
optional.append(r)
output = r.output
if output != 'global':
do_log_err('Output that needs it: '+output, fatal)
if optional:
if len(optional) == 1:
o = optional[0]
desc = o.desc[0].lower()+o.desc[1:]
do_log_err('Used to {}{}'.format(desc, get_version(o)), fatal)
else:
do_log_err('Used to:', fatal)
for o in optional:
do_log_err('- {}{}'.format(o.desc, get_version(o)), fatal)
def show_roles(role, fatal):
if role.output != 'global':
do_log_err('Output that needs it: '+role.output, fatal)
if not role.mandatory:
desc = role.desc[0].lower()+role.desc[1:]
do_log_err('Used to {}{}'.format(desc, get_version(role)), fatal)
def get_dep_data(context, dep):
@ -881,7 +870,7 @@ def check_tool_dep_get_ver(context, dep, fatal=False):
do_log_err('- Recommended extra Arch packages: '+' '.join(dep.extra_arch), fatal)
for comment in dep.comments:
do_log_err(comment, fatal)
show_roles(dep.roles, fatal)
show_roles(dep.role, fatal)
do_log_err(TRY_INSTALL_CHECK, fatal)
if fatal:
exit(MISSING_TOOL)
@ -915,7 +904,7 @@ class ToolDependencyRole(object):
class ToolDependency(object):
""" Class used to define tools needed for an output """
def __init__(self, output, name, url=None, url_down=None, is_python=False, deb=None, in_debian=True, extra_deb=None,
roles=None, plugin_dirs=None, command=None, pypi_name=None, module_name=None, no_cmd_line_version=False,
role=None, plugin_dirs=None, command=None, pypi_name=None, module_name=None, no_cmd_line_version=False,
help_option=None, no_cmd_line_version_old=False, downloader=None, arch=None, extra_arch=None, tests=None):
# The associated output
self.output = output
@ -956,13 +945,10 @@ class ToolDependency(object):
self.help_option = help_option if help_option is not None else '--version'
self.tests = tests
# Roles
if roles is None:
roles = [ToolDependencyRole()]
elif not isinstance(roles, list):
roles = [roles]
for r in roles:
r.output = output
self.roles = roles
if role is None:
role = ToolDependencyRole()
role.output = output
self.role = role
def register_dep(context, dep):
@ -1017,7 +1003,7 @@ def register_dep(context, dep):
tests = dep.get('tests', [])
# logger.error('{}:{} {} {}'.format(context, name, downloader, pypi_name))
# TODO: Make it *ARGS
td = ToolDependency(context, name, roles=role, url=url, url_down=url_down, deb=deb, in_debian=in_debian,
td = ToolDependency(context, name, role=role, url=url, url_down=url_down, deb=deb, in_debian=in_debian,
extra_deb=extra_deb, is_python=is_python, module_name=module_name, plugin_dirs=plugin_dirs,
command=command, help_option=help_option, pypi_name=pypi_name,
no_cmd_line_version_old=no_cmd_line_version_old, downloader=downloader, arch=arch,

View File

@ -15,6 +15,7 @@ Dependencies:
python_module: true
debian: python3-xlsxwriter
arch: python-xlsxwriter
version: 1.1.2
downloader: python
"""
import csv

View File

@ -239,9 +239,11 @@ class RegDependency(Registrable):
if name in cl._registered:
# Already registered, add the roles
old_reg = cl._registered[name]
old_reg.roles.extend(aclass.roles)
old_reg.role.append(aclass.role)
else:
cl._registered[name] = aclass
cp = copy(aclass)
cp.role = [aclass.role]
cl._registered[name] = cp
def solve_variant(variant):

View File

@ -39,7 +39,7 @@ deps = '{\
"output": "pcb_replace",\
"plugin_dirs": null,\
"pypi_name": "Bash",\
"roles": [\
"role": [\
{\
"desc": "Run external commands to create replacement text",\
"mandatory": false,\
@ -86,7 +86,7 @@ deps = '{\
"output": "blender_export",\
"plugin_dirs": null,\
"pypi_name": "Blender",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -124,7 +124,7 @@ deps = '{\
"output": "global",\
"plugin_dirs": null,\
"pypi_name": "Colorama",\
"roles": [\
"role": [\
{\
"desc": "Get color messages in a portable way",\
"mandatory": false,\
@ -157,7 +157,7 @@ deps = '{\
"output": "navigate_results",\
"plugin_dirs": null,\
"pypi_name": "Ghostscript",\
"roles": [\
"role": [\
{\
"desc": "Create outputs preview",\
"mandatory": false,\
@ -197,7 +197,7 @@ deps = '{\
"output": "diff",\
"plugin_dirs": null,\
"pypi_name": "Git",\
"roles": [\
"role": [\
{\
"desc": "Compare with files in the repo",\
"mandatory": false,\
@ -267,7 +267,7 @@ deps = '{\
"output": "blender_export",\
"plugin_dirs": null,\
"pypi_name": "ImageMagick",\
"roles": [\
"role": [\
{\
"desc": "Automatically crop images",\
"mandatory": false,\
@ -333,7 +333,7 @@ deps = '{\
"org_openscopeproject_InteractiveHtmlBom/InteractiveHtmlBom"\
],\
"pypi_name": "Interactive HTML BoM",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -370,7 +370,7 @@ deps = '{\
"output": "kibom",\
"plugin_dirs": null,\
"pypi_name": "KiBoM",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -407,7 +407,7 @@ deps = '{\
"output": "diff",\
"plugin_dirs": null,\
"pypi_name": "kiauto",\
"roles": [\
"role": [\
{\
"desc": "Compare schematics",\
"mandatory": false,\
@ -642,7 +642,7 @@ deps = '{\
"output": "diff",\
"plugin_dirs": null,\
"pypi_name": "kidiff",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -690,7 +690,7 @@ deps = '{\
"output": "bom",\
"plugin_dirs": null,\
"pypi_name": "KiCost",\
"roles": [\
"role": [\
{\
"desc": "Find components costs and specs",\
"mandatory": false,\
@ -741,7 +741,7 @@ deps = '{\
"output": "global",\
"plugin_dirs": null,\
"pypi_name": "KiKit",\
"roles": [\
"role": [\
{\
"desc": "Separate multiboard projects",\
"mandatory": false,\
@ -816,7 +816,7 @@ deps = '{\
"output": "pcb_print",\
"plugin_dirs": null,\
"pypi_name": "LXML",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -857,7 +857,7 @@ deps = '{\
"output": "global",\
"plugin_dirs": null,\
"pypi_name": "Lark",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -890,7 +890,7 @@ deps = '{\
"output": "stencil_3d",\
"plugin_dirs": null,\
"pypi_name": "OpenSCAD",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -938,7 +938,7 @@ deps = '{\
"output": "report",\
"plugin_dirs": null,\
"pypi_name": "Pandoc",\
"roles": [\
"role": [\
{\
"desc": "Create PDF/ODF/DOCX files",\
"mandatory": false,\
@ -972,7 +972,7 @@ deps = '{\
"output": "global",\
"plugin_dirs": null,\
"pypi_name": "PyYAML",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1006,7 +1006,7 @@ deps = '{\
"output": "qr_lib",\
"plugin_dirs": null,\
"pypi_name": "QRCodeGen",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1039,7 +1039,7 @@ deps = '{\
"output": "compress",\
"plugin_dirs": null,\
"pypi_name": "RAR",\
"roles": [\
"role": [\
{\
"desc": "Compress in RAR format",\
"mandatory": false,\
@ -1072,7 +1072,7 @@ deps = '{\
"output": "navigate_results",\
"plugin_dirs": null,\
"pypi_name": "RSVG tools",\
"roles": [\
"role": [\
{\
"desc": "Create outputs preview",\
"mandatory": false,\
@ -1137,7 +1137,7 @@ deps = '{\
"output": "global",\
"plugin_dirs": null,\
"pypi_name": "Requests",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1171,7 +1171,7 @@ deps = '{\
"output": "bom",\
"plugin_dirs": null,\
"pypi_name": "XLSXWriter",\
"roles": [\
"role": [\
{\
"desc": "Create XLSX files",\
"mandatory": false,\
@ -1204,7 +1204,7 @@ deps = '{\
"output": "stencil_3d",\
"plugin_dirs": null,\
"pypi_name": "Xvfb",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1245,7 +1245,7 @@ deps = '{\
"output": "stencil_3d",\
"plugin_dirs": null,\
"pypi_name": "Xvfbwrapper",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1286,7 +1286,7 @@ deps = '{\
"output": "kikit_present",\
"plugin_dirs": null,\
"pypi_name": "markdown2",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1320,7 +1320,7 @@ deps = '{\
"output": "populate",\
"plugin_dirs": null,\
"pypi_name": "mistune",\
"roles": [\
"role": [\
{\
"desc": null,\
"mandatory": true,\
@ -1354,7 +1354,7 @@ deps = '{\
"output": "pcbdraw",\
"plugin_dirs": null,\
"pypi_name": "numpy",\
"roles": [\
"role": [\
{\
"desc": "Automatically adjust SVG margin",\
"mandatory": false,\
@ -1805,7 +1805,7 @@ for name, d in dependencies.items():
version = 'Ok'
except:
version = NOT_AVAIL
sev, ver = check_version(version, d['roles'])
sev, ver = check_version(version, d['role'])
d['sev'] = sev
version = version.split('\n')[0]
print(name+': '+do_color(version, sev, version=ver))
@ -1828,7 +1828,7 @@ for name, d in dependencies.items():
# It will just confuse run_command thinking we need to check Python
cmd.insert(0, 'python3')
version = run_command(cmd, no_err_2=d['no_cmd_line_version_old'])
sev, ver = check_version(version, d['roles'], tests=d['tests'])
sev, ver = check_version(version, d['role'], tests=d['tests'])
d['sev'] = sev
version = version.split('\n')[0]
pypi_name = d['pypi_name']
@ -1898,10 +1898,10 @@ if not kibot_ok:
for name, d in dependencies.items():
if d['is_python']:
python_module(d['sev'], d['pypi_name'], d['deb_package'], d['roles'], d['arch'])
python_module(d['sev'], d['pypi_name'], d['deb_package'], d['role'], d['arch'])
else:
binary_tool(d['sev'], d['name'], d['url'], d['url_down'], d['deb_package'], d['in_debian'], d['extra_deb'],
d['roles'], d['downloader_str'], d['comments'], d['arch'], d['extra_arch'])
d['role'], d['downloader_str'], d['comments'], d['arch'], d['extra_arch'])
if sys.stdout.isatty():
labels = ('ok', 'optional for an output', 'optional for general use', 'mandatory for an output', 'mandatory for general use')

View File

@ -455,7 +455,7 @@ for name, d in dependencies.items():
version = 'Ok'
except:
version = NOT_AVAIL
sev, ver = check_version(version, d['roles'])
sev, ver = check_version(version, d['role'])
d['sev'] = sev
version = version.split('\n')[0]
print(name+': '+do_color(version, sev, version=ver))
@ -478,7 +478,7 @@ for name, d in dependencies.items():
# It will just confuse run_command thinking we need to check Python
cmd.insert(0, 'python3')
version = run_command(cmd, no_err_2=d['no_cmd_line_version_old'])
sev, ver = check_version(version, d['roles'], tests=d['tests'])
sev, ver = check_version(version, d['role'], tests=d['tests'])
d['sev'] = sev
version = version.split('\n')[0]
pypi_name = d['pypi_name']
@ -548,10 +548,10 @@ if not kibot_ok:
for name, d in dependencies.items():
if d['is_python']:
python_module(d['sev'], d['pypi_name'], d['deb_package'], d['roles'], d['arch'])
python_module(d['sev'], d['pypi_name'], d['deb_package'], d['role'], d['arch'])
else:
binary_tool(d['sev'], d['name'], d['url'], d['url_down'], d['deb_package'], d['in_debian'], d['extra_deb'],
d['roles'], d['downloader_str'], d['comments'], d['arch'], d['extra_arch'])
d['role'], d['downloader_str'], d['comments'], d['arch'], d['extra_arch'])
if sys.stdout.isatty():
labels = ('ok', 'optional for an output', 'optional for general use', 'mandatory for an output', 'mandatory for general use')

View File

@ -232,30 +232,6 @@ def test_check_tool_dep_get_ver_1(test_dir, caplog, monkeypatch):
assert pytest_wrapped_e.value.code == MISSING_TOOL
@pytest.mark.indep
def test_check_tool_dep_get_ver_2(test_dir, caplog, monkeypatch):
""" Check for missing stuff in show_roles """
# Create a context to get an output directory
ctx = context.TestContext(test_dir, 'bom', 'bom')
dep = """
- name: FooBar
command: foobar
- from: FooBar
role: Do this and this
"""
dep2 = """
Dependencies:
- from: FooBar
role: Do other stuff
"""
pytest_wrapped_e = try_function(ctx, caplog, monkeypatch, do_test_check_tool_dep_get_ver_fatal, dep=dep, dep2=dep2)
# Check the messages
assert "Do this and this" in caplog.text
assert "Do other stuff" in caplog.text
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == MISSING_TOOL
def do_check_tool_python(mod):
mod.python_downloader = lambda x: True
return mod.check_tool_python(mod.used_deps['test:foobar'])