thought-machine / please

High-performance extensible build system for reproducible multi-language builds.
https://please.build
Apache License 2.0
2.45k stars 205 forks source link

f-strings produce inconsistent output for some object types #3181

Open chrisnovakovic opened 3 months ago

chrisnovakovic commented 3 months ago

MWE, which can be observed in a more substantial setting in #3176:

s = "a string"
i = 1
d = {"s": s, "i": i}

log.fatal(f"s={s}, i={i}, d={d}")
15:40:42.350 CRITICAL: //ftest/BUILD: s=a string, i=1, d={"i": 1, "s": a string}

There seems to be an overloading of the purpose of the String function for different object types in the build language - e.g. for pyDicts it tries to produce a somewhat ASP-compliant representation of the current state of the object, but for pyStrings it seems to explicitly produce something suitable for output into an f-string (which makes complete sense given the context where this function is typically called - you don't want to see the surrounding double-quotes in the f-string output).

I wonder whether it'd make more sense to have a second function on the pyObject interface to sit alongside the String() function imposed by fmt.Stringer - something similar in spirit to encoding.TextMarshaler - and then we can choose which one to use given the circumstances for requiring a textual representation of the object. This would also allow us to accurately stringify pyDicts (and other non-primitive types like pyList), so f"this is {s}" can return this is a string, while f"{d}" can return {"i": 1, "s": "a string"}.

Tatskaari commented 3 months ago

What does Python do in this situation? I think your suggestion makes sense though.

chrisnovakovic commented 3 months ago
$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "a string"
>>> i = 1
>>> d = {"s": s, "i": i}
>>> f"s={s}, i={i}, d={d}"
"s=a string, i=1, d={'s': 'a string', 'i': 1}"

So pretty much what I'm proposing.

peterebden commented 3 months ago

Makes sense, although there's a limit to how far I want to get into us guaranteeing nuances of how we stringify dicts - that feels like it should only be a thing to help with debugging really.