docs: def masters(self):
          """Get an iterator over master UFOs that match the given family_name.
          """
          if self._sources:
              for source in self._sources.values():
                  yield source.font
              return
  
          # Store set of actually existing master (layer) ids. This helps with
          # catching dangling layer data that Glyphs may ignore, e.g. when
          # copying glyphs from other fonts with, naturally, different master
          # ids. Note: Masters have unique ids according to the Glyphs
          # documentation and can therefore be stored in a set.
          master_layer_ids = {m.id for m in self.font.masters}
  
          # stores background data from "associated layers"
          supplementary_layer_data = []
  
          # TODO(jamesgk) maybe create one font at a time to reduce memory usage
          # TODO: (jany) in the future, return a lazy iterator that builds UFOs
          #     on demand.
          self.to_ufo_font_attributes(self.family_name)
  
          # Generate the main (master) layers first.
          for glyph in self.font.glyphs:
              for layer in glyph.layers.values():
                  if layer.associatedMasterId != layer.layerId:
                      # The layer is not the main layer of a master
                      # Store all layers, even the invalid ones, and just skip
                      # them and print a warning below.
                      supplementary_layer_data.append((glyph, layer))
                      continue
  
                  ufo_layer = self.to_ufo_layer(glyph, layer)
                  ufo_glyph = ufo_layer.newGlyph(glyph.name)
                  self.to_ufo_glyph(ufo_glyph, layer, glyph)
  
          # And sublayers (brace, bracket, ...) second.
          for glyph, layer in supplementary_layer_data:
              if (
                  layer.layerId not in master_layer_ids
                  and layer.associatedMasterId not in master_layer_ids
              ):
                  if self.minimize_glyphs_diffs:
                      self.logger.warning(
                          '{}, glyph "{}": Layer "{}" is dangling and will be '
                          "skipped. Did you copy a glyph from a different font?"
                          " If so, you should clean up any phantom layers not "
                          "associated with an actual master.".format(
                              self.font.familyName, glyph.name, layer.layerId
                          )
                      )
                  continue
  
              if not layer.name:
                  # Empty layer names are invalid according to the UFO spec.
                  if self.minimize_glyphs_diffs:
                      self.logger.warning(
                          '{}, glyph "{}": Contains layer without a name which '
                          "will be skipped.".format(self.font.familyName, glyph.name)
                      )
                  continue
  
              # Save processing bracket layers for when designspace() is called, as we
              # have to extract them to free-standing glyphs.
              if (
                  "[" in layer.name
                  and "]" in layer.name
                  and ".background" not in layer.name
              ):
                  self.bracket_layers.append(layer)
              else:
                  ufo_layer = self.to_ufo_layer(glyph, layer)
                  ufo_glyph = ufo_layer.newGlyph(glyph.name)
                  self.to_ufo_glyph(ufo_glyph, layer, layer.parent)
  
          for source in self._sources.values():
              ufo = source.font
              if self.propagate_anchors:
                  self.to_ufo_propagate_font_anchors(ufo)
              for layer in ufo.layers:
                  self.to_ufo_layer_lib(layer)
  
          # Sanitize skip list and write it to both Designspace- and UFO-level lib keys.
          # The latter is unnecessary when using e.g. the `ufo2ft.compile*FromDS`
          # functions, but the data may take a different path. Writing it everywhere can
          # save on surprises/logic in other software.
          skip_export_glyphs = self._designspace.lib.get("public.skipExportGlyphs")
          if skip_export_glyphs is not None:
              skip_export_glyphs = sorted(set(skip_export_glyphs))
              self._designspace.lib["public.skipExportGlyphs"] = skip_export_glyphs
              for source in self._sources.values():
                  source.font.lib["public.skipExportGlyphs"] = skip_export_glyphs
  
          self.to_ufo_features()  # This depends on the glyphOrder key
          self.to_ufo_groups()
          self.to_ufo_kerning()
  
          for source in self._sources.values():
              yield source.font