Files
pyp2spec/conf2spec.py
T

152 lines
4.7 KiB
Python

from pathlib import Path
import click
from jinja2 import Template
from config import ConfigFile
TEMPLATE_PATH = Path().resolve(__file__) / 'template.spec'
def generate_extra_build_requires(config):
"""If defined in config file, return extra build requires.
If none were defined, return `-r` - runtime extra BRs`."""
# TODO: custom tox env (-e)
options = {
"tox": "-t",
"extra": "-x",
}
extra_brs = config.get_list("extra_build_requires")
# No extra BuildRequires were defined - return `-r` = runtime
if not extra_brs:
return "-r"
generated_brs = []
add = generated_brs.append
for extra_br in extra_brs:
if extra_br == "extra":
add(options.get(extra_br))
add(",".join(config.get_list("extra_test_env")))
else:
add(options.get(extra_br))
return " ".join(generated_brs)
def generate_check(config):
"""Generate valid check section.
If defined in config file, use applicable test macro.
If no test method was defined, return `%py3_check_import` with module name."""
test_method = config.get_string("test_method")
if test_method == "pytest":
return generate_pytest(config)
elif test_method == "tox":
return generate_tox(config)
else:
# If no tests were defined, run at least smoke import check
# This is mandatory as defined in Fedora Packaging Guidelines
# https://docs.fedoraproject.org/en-US/packaging-guidelines/Python/#_tests
modules = " ".join(config.get_list("modules"))
return f"%py3_check_import {modules}"
def generate_pytest(config):
"""Return valid pytest macro with unwanted tests (if defined)."""
if (unwanted_tests := generate_unwanted_tests(config)):
return f"%pytest {unwanted_tests}"
return "%pytest"
def generate_tox(config):
"""Return valid tox macro. If additional unwanted are defined,
raise NotImplementedError."""
if (unwanted_tests := generate_unwanted_tests(config)):
raise NotImplementedError
return "%tox"
def generate_unwanted_tests(config):
"""If defined in config file, get the unwanted tests.
Given the unwanted tests are [a, b], return `-k "not a and\\\nnot b"`."""
unwanted_tests = config.get_list("unwanted_tests")
if not unwanted_tests:
return ""
else:
prep_unwanteds = [f"not {test}" for test in unwanted_tests]
unwanteds_as_str = " and \\\n".join(prep_unwanteds)
formatted_unwanteds = f"-k \"{unwanteds_as_str}\""
return formatted_unwanteds
def fill_in_template(config):
"""Return template rendered with data from config file."""
with open(TEMPLATE_PATH) as template_file:
spec_template = Template(template_file.read())
result = spec_template.render(
archive_name=config.get_string("archive_name"),
binary_files=config.get_list("binary_files"),
changelog_head=config.get_string("changelog_head"),
changelog_msg=config.get_string("changelog_msg"),
description=config.get_string("description"),
doc_files=" ".join(config.get_list("doc_files")),
extra_build_requires=generate_extra_build_requires(config),
license_files=" ".join(config.get_list("license_files")),
license=config.get_string("license"),
manual_build_requires=config.get_list("manual_build_requires"),
modules=" ".join(config.get_list("modules")),
name=config.get_string("pypi_name"),
python_name=config.get_string("python_name"),
release=config.get_string("release"),
source=config.get_string("source"),
summary=config.get_string("summary"),
test_method=generate_check(config),
url=config.get_string("url"),
version=config.get_string("version"),
)
return result
def save_spec_file(config, output=None):
"""Save the spec file in the current directory.
Return the saved file name"""
result = fill_in_template(config)
if output:
spec_file_name = output
else:
spec_file_name = config.get_string("python_name") + ".spec"
with open(spec_file_name, "w") as spec_file:
spec_file.write(result)
print(f"Spec file {spec_file_name} was saved.")
return spec_file_name
def create_spec_file(config_file, spec_output=None):
"""Create and save the generate spec file."""
config = ConfigFile(config_file)
return save_spec_file(config, spec_output)
@click.command()
@click.argument("config")
@click.option(
"--spec-output", "-s",
help="Provide custom output where spec file will be saved",
)
def main(config, spec_output):
create_spec_file(config, spec_output)
if __name__ == "__main__":
main()