예제 #1
0
def check_pyproject_toml():
    """Check pyproject.toml."""
    check_path("pyproject.toml")
    errors = 0
    try:
        last_release = semantic_version.Version(CONFIG["last_release"])
    except ValueError:
        errors += err(
            f"last_release is not a valid semantic version: {CONFIG['last_release']}"
        )
        return errors

    # Get list of all semantic version tags
    repo = git.Repo()
    tags = sorted(
        semantic_version.Version(t.name) for t in repo.tags
        if semantic_version.validate(t.name))
    if not tags:  # not present in GitHub actions
        return errors

    if not last_release == tags[-1]:
        errors += err(
            f"last_release does not match last git tag: {last_release} vs. {tags[-1]}"
        )

    return errors
예제 #2
0
def check_tox():
    """Check tox.ini."""
    errors = 0
    check_path("tox.ini")
    tox_config = configparser.ConfigParser()
    tox_config.read(os.path.join(ROOT_DIR, "tox.ini"))

    # Mapping of additional testenv specific requirements
    tox_deps = tox_config["testenv"]["deps"].splitlines()
    tox_env_reqs = dict(
        [line.split(": ", 1) for line in tox_deps if ": " in line])

    # Check that there is a testenv listing all versions
    # pylint: disable=consider-using-f-string  # this line is just ugly otherwise
    # expected_envlist = "py{%s}-django{%s}-cryptography{%s}-acme{%s}-idna{%s}" % (
    #    ",".join([pyver.replace(".", "") for pyver in CONFIG["python-map"]]),
    #    ",".join(CONFIG["django-map"]),
    #    ",".join(CONFIG["cryptography-map"]),
    #    ",".join(CONFIG["acme-map"]),
    #    ",".join(CONFIG["idna-map"]),
    # )

    # pylint: enable=consider-using-f-string
    # Check disabled as long as different Django versions support different Python versions
    # if expected_envlist not in tox_config["tox"]["envlist"].splitlines():
    #    errors += err(f"Expected envlist item not found: {expected_envlist}")

    # Check that conditional dependencies are up to date
    for component in ["django", "cryptography", "acme", "idna"]:
        # First, check if there are any left over conditional settings for this component
        errors += simple_diff(
            f"{component} conditional dependencies present",
            [e for e in tox_env_reqs if e.startswith(component)],
            [f"{component}{major}" for major in CONFIG[f"{component}-map"]],
        )

        for major, minor in CONFIG[f"{component}-map"].items():
            name = f"{component}{major}"
            try:
                actual = tox_env_reqs[name]
            except KeyError:
                errors += err(f"{name}: Conditional dependency not found.")
                continue

            expected = f"{CANONICAL_PYPI_NAMES[component]}=={minor}"
            if name not in tox_env_reqs:
                continue  # handled in simple-diff above

            if actual != expected:
                errors += err(
                    f"conditional dependency for {name}: Have {actual}, expected {expected}."
                )

    return errors
예제 #3
0
def check_readme():
    """Check contents of README.md."""
    errors = 0
    check_path("README.md")
    readme_fullpath = os.path.join(ROOT_DIR, "README.md")
    with open(readme_fullpath, encoding="utf-8") as stream:
        readme = stream.read()
    if f"{exp_version_line}" not in readme:
        errors += err('Does not contain correct version line ("Written in ...").')

    return errors
예제 #4
0
def check_intro():
    """Check intro.rst (reused in a couple of places)."""
    errors = 0
    intro_path = os.path.join("docs", "source", "intro.rst")
    intro_fullpath = os.path.join(ROOT_DIR, intro_path)
    check_path(intro_path)
    with open(intro_fullpath, encoding="utf-8") as stream:
        intro = stream.read()

    if f"#. {exp_version_line}" not in intro.splitlines():
        errors += err('Does not contain correct version line ("Written in ...").')
    return errors
예제 #5
0
def check_setup_cfg():
    """Check setup.cfg"""
    check_path("setup.cfg")
    errors = 0

    setup_config = read_configuration(os.path.join(ROOT_DIR, "setup.cfg"))

    # parse data from setup.cfg
    classifiers = setup_config["metadata"]["classifiers"]
    install_requires = setup_config["options"]["install_requires"]

    # validate that we have the proper language/django classifiers
    pyver_cfs = [
        m.groups(0)[0] for m in filter(
            None,
            [re.search(r"Python :: (3\.[0-9]+)$", cf) for cf in classifiers])
    ]
    if pyver_cfs != CONFIG["python-major"]:
        errors += err(
            f'Wrong python classifiers: Have {pyver_cfs}, wanted {CONFIG["python-major"]}'
        )

    djver_cfs = [
        m.groups(0)[0] for m in filter(None, [
            re.search(r"Django :: ([0-9]\.[0-9]+)$", cf) for cf in classifiers
        ])
    ]
    if djver_cfs != CONFIG["django-major"]:
        errors += err(
            f'Wrong python classifiers: Have {djver_cfs}, wanted {CONFIG["django-major"]}'
        )

    for djver in CONFIG["django-map"]:
        if f"Framework :: Django :: {djver}" not in classifiers:
            errors += err(f"Django {djver} classifier not found.")

    expected_py_req = f">={CONFIG['python-major'][0]}"
    actual_py_req = setup_config["options"]["python_requires"]
    if actual_py_req != expected_py_req:
        errors += err(
            f"python_requires: Have {actual_py_req}, expected {expected_py_req}"
        )

    expected_django_req = f"Django>={CONFIG['django-major'][0]}"
    if expected_django_req not in install_requires:
        errors += err(
            f"{expected_django_req}: Expected Django requirement not found.")

    expected_cg_req = f"cryptography>={CONFIG['cryptography-major'][0]}"
    if expected_cg_req not in install_requires:
        errors += err(
            f"{expected_cg_req}: Expected cryptography requirement not found.")

    # Do not check setup.cfg minimum dependency, as actually any version works fine right now
    # expected_idna_req = f"idna>={CONFIG['idna-major'][0]}"
    # if expected_idna_req not in install_requires:
    #    errors += err(f"{expected_idna_req}: Expected idna requirement not found.")

    return errors
예제 #6
0
def check_test_settings():
    """Check test_settings.py"""
    relpath = os.path.join("ca", "ca", "test_settings.py")
    fullpath = os.path.join(ROOT_DIR, relpath)
    check_path(relpath)
    errors = 0

    test_settings = import_mod("test_settings", fullpath)
    for component in ["python", "django", "cryptography"]:
        config_key = f"{component}-map"
        setting = f"NEWEST_{component.upper()}_VERSION"
        value = getattr(test_settings, setting)
        expected = tuple(int(e) for e in list(CONFIG[config_key])[-1].split("."))
        if value == expected:
            ok(f"{setting} = {value}")
        else:
            errors += err(f"{setting}: Have {value}, expected {expected}")

    return errors
예제 #7
0
def simple_diff(what, actual, expected) -> int:
    """Simply compare two values and output any difference."""
    if expected == actual:
        return ok(what)
    return err(f"{what}: Have {actual}, expected {expected}.")