googlefonts / ufo2ft

A bridge from UFOs to FontTools objects (and therefore, OTFs and TTFs).
MIT License
151 stars 43 forks source link

"AttributeError: 'tuple' object has no attribute 'defaultLayer'" error after adding flattenComponents filter & upgrading to ufo2ft==2.19.1 #443

Closed arrowtype closed 3 years ago

arrowtype commented 3 years ago

I’ve catalogued my efforts to figure out an issue blocking my static build of Recursive when adding filters to its sources, https://github.com/arrowtype/recursive/issues/427.

The branch I am on is one in which I am trying to use the flattenComponents filter to avoid nested components: https://github.com/arrowtype/recursive/tree/c2590cc287639c94aabb4c0cd42609ccc55b9d62

It seems to be getting hung up when trying to get the default layer of a UFO, while trying to set the skipExportGlyphs lib data. But, I am pretty unsure of this diagnosis. Here’s where I think the problem is started; full traceback in the issue linked to above.

Traceback (most recent call last):--------------------| 0.0% Complete
  File "build.py", line 78, in <module>
    files = buildFiles(version=version, variable=False)
  File "/Users/stephennixon/type-repos/recursive/mastering/build_files.py", line 107, in buildFiles
    buildInstances(paths["designspace"], paths["cff"], name_map)
  File "/Users/stephennixon/type-repos/recursive/mastering/build_static.py", line 515, in buildInstances
    writeKerning(font, path)
  File "/Users/stephennixon/type-repos/recursive/mastering/build_static.py", line 210, in writeKerning
    w.write(font, feaFile)
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/featureWriters/baseFeatureWriter.py", line 109, in write
    self.setContext(font, feaFile, compiler=compiler)
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/featureWriters/kernFeatureWriter.py", line 207, in setContext
    ctx.kerning = self.getKerningData(font, feaFile, self.getOrderedGlyphSet())
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/featureWriters/baseFeatureWriter.py", line 155, in getOrderedGlyphSet
    skipExportGlyphs=set(font.lib.get("public.skipExportGlyphs", [])),
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/util.py", line 46, in from_layer
    layer = font.layers.defaultLayer

In summary:

I feel odd filing this issue, because I’m having trouble even being 100% sure that the problem is in ufo2ft itself. But, I feel pretty stuck.

Do these tracebacks suggest anything specific to folks more familiar with ufo2ft? Is there anything you might suggest I try to get unstuck? Really, any thoughts or tips are appreciated. Thank you!

madig commented 3 years ago

The tuple is weird. Can you track down where it originates? Reminds me of glyph stand-ins.

PS: Install a debugger like pdbpp to make backtrace sifting nicer.

anthrotype commented 3 years ago

could it be a fontparts font instead of ufoLib2?

arrowtype commented 3 years ago

Okay, yes, it’s probably a good time to dive into a proper debugger to follow what is happening. Thanks, @madig!

@anthrotype – maybe! It seems likely it could be an interaction between libraries. Will update once I know more.

anthrotype commented 3 years ago

We don't test against the fontparts API so it may well be the case that ufo2ft doesn't work with fontParts. I suggest you pass down the naked defcon or ufoLib2 Font object

arrowtype commented 3 years ago

Hmm, so, an interesting result...

I used ipdb to step through this, and realized that a potential issue might be that ufo2ft/util.py, on line 47, calls for font.layers.defaultLayer when it perhaps should call for font.defaultLayer as specced in FontParts. In debugging mode, the existing ufo2ft line gives the AttributeError, while the latter returns an RLayer object as I would expect.

(Pdb) print(font.layers.defaultLayer)
*** AttributeError: 'tuple' object has no attribute 'defaultLayer'

(Pdb) print(font.defaultLayer)
<RLayer 'public.default' at 140519045115856>

However, when I run the full process on this ... it still breaks on the same line, with a very similar error message:

🏗  Making TTF sources
Traceback (most recent call last):--------------------| 0.0% Complete
  File "build.py", line 93, in <module>
    build_static(files["cff"], files["ttf"], out)
  File "/Users/stephennixon/type-repos/recursive/mastering/build_static.py", line 771, in build_static
    buildTTFfiles(cff_root, ttf_root)
  File "/Users/stephennixon/type-repos/recursive/mastering/build_static.py", line 167, in buildTTFfiles
    ttf = compileTTF(ufo, useProductionNames=False)
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/__init__.py", line 215, in compileTTF
    skipExportGlyphs=skipExportGlyphs,
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/preProcessor.py", line 40, in __init__
    ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs
  File "/Users/stephennixon/type-repos/recursive/venv/lib/python3.7/site-packages/ufo2ft/util.py", line 47, in from_layer
    layer = font.defaultLayer # DEBUGGING EXPERIMENT
AttributeError: 'Font' object has no attribute 'defaultLayer'

@anthrotype I am guessing this might be where your suggestion comes in:

I suggest you pass down the naked defcon or ufoLib2 Font object

I will try to figure out how to do this ... hopefully it doesn’t require too major of an overhaul of the scripts. Thank you for pointing out that there might be some meaningful differences there!

arrowtype commented 3 years ago

Just to update this: we ended up solving the problem in another way, adding a decomposition step to the Recursive build-prep script instead of using ufo2ft filters. I’m sure they’ll be useful on another project, but as is probably pretty obvious, Recursive is a fairly complex project to change a lot at this stage (e.g. changing the build from FontParts to ufoLib2).

Thanks for the thoughts here, though! I really do appreciate it. I’ll close this issue, as it is probably too specific to take action on within ufo2ft.