Right, it’s just not overly intuitive to iterate over, nor does the type <objective-c class NSKVONotifying_GSFont at 0x600001158d80> reveal how to iterate it. (key in dir(Font) works, but will have all sort of attributes, not just the API paramaters).
Just used for explicitness in the sample code.
Particularly the fact that trying to access it with "designer" in Font will send Glyphs into limbo is… not ideal
Just my feedback, since I’ve ran into this quite a few times.
I added a some code that at least print an error instead of crashing.
And I thought about it a bit more. If I would allow dict like access on the font, it would make more sense to return the glyph with that name (at least RoboFab is behaving like this).
Well, it’s a matter of taste and custom, but I find it odd the indices on a font should be the glyphs, not the font’s own properties. I rather like how the Glyphs API is logical about this with Font.glyphs[…]
Why and how would you iterate over an object’s (very diverse) properties? I have never encountered that pattern (also other programming languages, and independent of fonts).
You asked, so e.g. a QA script to make sure what should, should not or may be set by a designer.
required_fields = ["upm", "familyName"]
recommended_fields = ["designer", "designerUrl"]
ignored_fields = ["manufacturer", "manufacturerURL",
"versionMajor", "versionMinor", "copyright"]
for field in [r for r in required_fields
if r in dir(Glyphs.font) and getattr(Glyphs.font, r) is None]:
logging.error("Font attribute '%s' must not be empty." % (field))
for field in [r for r in recommended_fields
if r in dir(Glyphs.font) and getattr(Glyphs.font, r) is None]:
logging.warning("Font attribute '%s' should ideally not be empty." %
(field))
for field in [r for r in ignored_fields
if r in dir(Glyphs.font) and getattr(Glyphs.font, r) is None]:
logging.warning("Font attribute '%s' should be empty and will be "
"overwritten in the production." % (field))
Instead of r in dir(Glyphs.font) and getattr(Glyphs.font, r) is None I’d expect to check r in Glyphs.font or without having to avoid crashing on non-existance, simply Glyphs.font[r] is None.
In contrast to this, GSMaster.customParameters behaves pythonic and like I’d expect it to, e.g. "underlinePosition" in mymaster.customParameters
It seems you want to iterate over only a subset of the GSFont object’s properties. Practically all plain string properties. I wouldn’t say that r in Glyphs.font is an intuitive way of iterating over a particular subset of the object’s properties.
Instead, it could be useful if Glyphs provided a property, maybe called fontInfo of metadata, that provides that subset of properties (plain strings) as, say, a Python dict.
Yea, sounds about right. I suppose the documented properties of GSFont are of interest, implicitly getting any other properties is a result of the objective C bridge, I suppose?
So you want to check if a certain property is set?
Why not like this. The list comprehension is not helping with the readability of the code.
required_fields = ["upm", "familyName"]
recommended_fields = ["designer", "designerUrl"]
ignored_fields = ["manufacturer", "manufacturerURL",
"versionMajor", "versionMinor", "copyright"]
font = Glyphs.font
for field in required_fields:
value = getattr(font, field)
if value is None or len(value) == 0:
logging.error("Font attribute '%s' must not be empty." % (field))
...