bazelbuild / starlark

Starlark Language
Apache License 2.0
2.38k stars 158 forks source link

Add fail.format() to make it easier to use formatted strings with fail() #256

Open rickeylev opened 1 year ago

rickeylev commented 1 year ago

Description of the feature request:

Make it easier to produce nice looking error messages with fail().

So we can write this:

fail.format(
    "Unable to find interpreter '{name}' for hub '{hub}' for version '{version}': " +
    "make sure a toolchain for version {version} was registered in module {module}",
    name = name, hub = hub, version=version, module=module
)

I'm not sure if java-backed starlark objects can have attribute lookup; a subattribute is appealing because it avoids introducing another global name and reads nicely.

Instead of this:

fail.format(
    (
        "Unable to find interpreter '{name}' for hub '{hub}' for version '{version}': " +
        "make sure a toolchain for version {version} was registered in module {module}"
    ).format(
        name=name, hub=hub, version=version, module=module
    )
)

You can play tricks with the location of newlines and parentheses to make the above look nicer, but it's tiring to fight the auto formatter for every fail() call.

There's several alternatives, but they are somewhat annoying:

What underlying problem are you trying to solve with this feature?

Making it easier to write useful informative error messages.

Which operating system are you running Bazel on?

linux

What is the output of bazel info release?

No response

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse master; git rev-parse HEAD ?

No response

Have you found anything relevant by searching the web?

Didn't see anything

Any other information, logs, or outputs that you want to share?

No response

martis42 commented 1 year ago

It is not directly related to fail. But if https://github.com/bazelbuild/starlark/issues/91 would be accepted and implemented we could write significantly leaner code whenever strings are involved.

brandjon commented 1 year ago

Transferred to bazelbuild/starlark since fail() is a language-level construct.

My view is that the inconvenient syntax in Richard's post isn't worth a new builtin symbol.

Does a triple quoted string literal help? E.g.

fail(
    """Unable to find interpreter '{name}' for hub '{hub}' for version '{version}': \
make sure a toolchain for version {version} was registered in module {module}""",
    name = name, hub = hub, version=version, module=module
)

This requires care to suppress newlines and avoid spurious inline spaces.

ndmitchell commented 1 year ago

This would be much more concise with f-strings #91, and in fact with that it probably is even better than the initial proposal.

fail(
    f"Unable to find interpreter {name} for hub {hub} for version {version}: " +
    f"make sure a toolchain for version {version} was registered in module {module}"
)
rickeylev commented 1 year ago

A triple quoted string introduces extra leading white space. If it's pulled all the way to the left, then after a couple level of indentions, the flow of code is pretty awkward. Having to escape newlines to prevent them from becoming newlines is also awkward.

If there was a text.dedent function that took care of reflowing the text, that'd help.

A variation of fail.format would be to have fail accept varargs of message strings, and kwargs of format names, then internally concat and call format.