Coding 2021-12-11

By Max Woerner Chase

Okay, I failed at getting more rest last night, so, we'll see what happens tonight. I'm not feeling super confident, but I'd like to try to get a bit done. So, let's see what I think about one thing I'd noticed, which is the heavy amount of boilerplate for the base command stuff. What I want to see is, how much variety is there in the definitions of the base commands?

So, I'm going to try to sketch out what I want from the helper functions for cutting down on the boilerplate.

# pytest:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "pytest",
        installer_key=PYTEST_KEY,
        requirements=["pytest"],
        path_segments=["pytest"],
    ),
    allowed_codes=frozenset([1]),
)

# flake8:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "flake8",
        installer_key=FLAKE8_KEY,
        requirements=["flake8"],
        path_segments=["check"],
    ),
    allowed_codes=frozenset([1]),
)

# Now let's try some I haven't attempted.

# junit2html:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "junit2hml",
        installer_key=JUNIT2HTML_KEY,
        requirements=["junit2html"],
        path_segments=["junit2html"],
    ),
)

# limit_coverage:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "limit-coverage",
        installer_key=LIMIT_COVERAGE_KEY,
        requirements=["limit-coverage"],
        path_segments=["limit-coverage"],
    ),
)

# mypy:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "mypy",
        installer_key=MYPY_KEY,
        requirements=["mypy"],
        path_segments=["mypy"],
    ),
    allowed_codes=frozenset([1]),
)

# pyinstrument:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "pyinstrument",
        installer_key=PYINSTRUMENT_KEY,
        requirements=["pyinstrument"],
        path_segments=["profile"],
    ),
)

# junitparser merge:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "junitparser",
        "merge",
        installer_key=JUNITPARSER_KEY,
        requirements=["junitparser"],
        path_segments=["junitparser"],
    ),
)

# coverage:
BASE: Fragment = _types.Fragment(
    my_helper_func(
        "coverage",
        "erase",
        installer_key=COVERAGE_KEY,
        requirements=["coverage"],
        path_segments=["coverage", "base"],
    ),
)

# ...

BASE: Fragment = _types.Fragment(
    my_helper_func(
        "coverage",
        "html",
        installer_key=COVERAGE_KEY,
        requirements=["coverage"],
        path_segments=["coverage", "base"],
    ),
    allowed_codes=frozenset([2])
)

def base(
    installer_key: Key[Installer],
    module_fragment: Fragment[Module, TProgram],
    # Probably something about MetaBuilders?
) -> Fragment[Script, TProgram]:
    return _types.Fragment(
        my_helper_func(
            "coverage",
            "run",
            installer_key=installer_key,
            requirements=["coverage"],
            path_segments=["coverage"],
        ),
    ).with_module(module_fragment)

So, there are a few observations here. One is that the command, the requirement, and the path segment for the environment are usually the same, and most of the remainder of the cases could have them all be the same if I were so inclined. This all implies to me that I could make the helper just fill in those values and change the arguments to "iterables of additional values". I'm not confident that I'm using it right for coverage run, but that's the weirdest command out of these, and if I need to do something differently, the underlying code is, like, right there.

So, maybe the helper looks like:

def my_helper_func(
    name: str,
    *subcommands: str,
    installer_key: Key[Installer],
    requirements: Iterable[str] = (),
    path_segments: Iterable[str] = (),
) -> CmdMeta:
    return base_cmd(
        Command(installer_key, name),
        *subcommands,
        installer_registry=INSTALLER_REGISTRY.set(
            installer_key,
            Pip(
                frozenset([
                    package(name),
                    *(
                        package(requirement)
                        for requirement
                        in requirements
                    ),
                ]),
                (name, *path_segments),
            ),
        ),
    )

I'll have to sleep on this and see what I think. Maybe have my original version of the idea, and then this version as a wrapper that just replicates the argument around.

But, I'm pretty tired right now, so I don't want to try to evaluate it at the moment.

Good night.