Yesterday I used fstringify <https://pypi.org/project/fstringify/>to 
convert all % strings to f-strings in Leo's core.  The results are in the 
fstring 
branch <https://github.com/leo-editor/leo-editor/tree/fstring>.

*Status*

The code is probably safe to merge into devel.  All unit tests pass and 
pylint is happy with all the changes.

However, I am dithering about what, if anything, to do with all the 
changes, for reasons that I'll now discuss.

*Procedure*

Using fstringify was a snap:  "fstringify leo\core" took under 3 seconds.

*Small glitches*

In some cases, fstringify converted if trace: g.trace(...) to if 
trace:g.trace(...).  That is, it removed the space after "if trace:".

fstringify did not convert strings containing the "f" format, such as 
"%5.2f". I converted them by hand.

fstringify did not convert string formats containing the minus sign.

fstringify sometimes added an unnecessary set of parentheses inside the 
curly braces.

fstringify sometimes created quite long lines.  I typically broke them into 
separate f-strings by hand.


*Regex problems*

fstringify does not handle regex strings well.  It drops the "r" prefix and 
doubles backspaces.  I backed out of all such changes.

*Second thoughts*

I spent several hours looking at diffs, and tweaking the results.  At 
first, I was happy with what I saw.  Gradually, however, I realized that I 
wasn't always pleased.

For simple messages, f-strings seem fine:

at.error(f"can not open {fileName}")
at.error(f"Exception reading {fileName}")
at.error(f"@all not valid in: {p.h}")
g.es(f"{timestamp}created: {fileName}")

etc.  This covers a great deal of Leo's strings

Key-value pairs work particularly well with f-strings:

def print_stats(self):
    print(f"changed nodes  {self.n_changed_nodes}")
    print(f"tokens         {self.n_input_tokens}")
    print(f"len(code_list) {self.n_output_tokens}")
    print(f"len(s)         {self.n_strings}")
    print(f"parse          {self.parse_time:4.2f}")
    print(f"tokenize       {self.tokenize_time:4.2f}")
    print(f"format         {self.beautify_time:4.2f}")
    print(f"check          {self.check_time:4.2f}")
    print(f"total          {self.total_time:4.2f}")

Messages involving counts seem a tad less clear, imo.  Compare:

g.es(f"finished. {at.sameFiles} unchanged files")
g.es("finished. %s unchanged files" % (at.sameFiles))

Messages involving g.plural are significantly less clear. Compare:

g.es_print(f"beautified {n} node{g.plural(n)}")
g.es_print(f"beautified %s node%s" % (n, g.plural(n))

The second %s stands for either "s" or "", which is like a pun.

Finally, f-strings can sometimes be *much* less clear than % strings. This 
happens when:

1. the % string represents a pattern, and
2. we *don't much care* what the actual values are.

Much of the code in leoAst.py is like this.  Some examples:

if node.bases:
    bases = [self.format(z, self.level) for z in node.bases]
    s = 'class %s(%s):' % (node.name, ','.join(bases))
else:
    s = 'class %s:' % node.name
s = 'def %s(%s):' % (node.name, args)
s = '%s=%s' % (target, value)

Patterns appear in various other places in Leo's core:

attr = ' %s="%s"' % (key, xml.sax.saxutils.escape(val))
pane = '%s:' % (bi.pane)
return '<ModeInfo %s>' % self.name
key = '%s:%s' % (self.language, id(self))

Asserts are a common example:

assert aCondition, "Fail %s, expected %s, got %s" (
    why, expected, result)

I quite like this pattern.  It works well  regardless of the length of the 
three expressions. With f-strings it becomes:

assert aCondition, f"Fail {why}, expected {expected}, got {got}"

This is clumsy when the actual expressions are lengthy.  Understand?

*Summary*

f-strings are excellent in the following situations:

1. Simple messages.
2. Lists of key-value pairs.

f-strings are less clear in several other situations.

I don't recommend f-strings when the % string represents an important 
pattern.

I'll continue to review diffs to see if any clear preference emerges.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/947e6901-dacc-4d5b-af5b-2cd6b0a59a8d%40googlegroups.com.

Reply via email to