METADATA.pb: Designer exists in Google Fonts profiles.csv?
337966
def com_google_fonts_check_metadata_profiles_csv(family_metadata):
  """"""
  PROFILES_GIT_URL = ("https://github.com/google/"
                      "fonts/blob/master/designers/profiles.csv")
  PROFILES_RAW_URL = ("https://raw.githubusercontent.com/google/"
                      "fonts/master/designers/profiles.csv")
  if family_metadata.designer == "":
    yield FAIL, ("METADATA.pb field \"designer\" MUST NOT be empty!")
  elif family_metadata.designer == "Multiple Designers":
    yield SKIP, ("Found \"Multiple Designers\" at METADATA.pb, which"
                 " is OK, so we won't look for it at profiles.csv")
  else:
    from urllib import request
    import csv
    try:
      handle = request.urlopen(PROFILES_RAW_URL)
      designers = []
      for row in csv.reader(handle):
        if not row:
          continue
        designers.append(row[0].decode("utf-8"))
      if family_metadata.designer not in designers:
        yield WARN, ("METADATA.pb: Designer \"{}\" is not listed"
                     " in profiles.csv"
                     " (at \"{}\")").format(family_metadata.designer,
                                            PROFILES_GIT_URL)
      else:
        yield PASS, ("Found designer \"{}\""
                     " at profiles.csv").format(family_metadata.designer)
    except:
      yield WARN, f"Failed to fetch \"{PROFILES_RAW_URL}\""
1320128
def get_font(self, font):
        
        font = {'a': 0, 'b': 1}.get(font, font)
        if not six.text_type(font) in self.fonts:
            raise NotSupported(
                '"{}" is not a valid font in the current profile'.format(font))
        return font
1182407
def com_google_fonts_check_metadata_match_weight_postscript(font_metadata):
  """"""
  WEIGHTS = {
    "Thin": 100,
    "ThinItalic": 100,
    "ExtraLight": 200,
    "ExtraLightItalic": 200,
    "Light": 300,
    "LightItalic": 300,
    "Regular": 400,
    "Italic": 400,
    "Medium": 500,
    "MediumItalic": 500,
    "SemiBold": 600,
    "SemiBoldItalic": 600,
    "Bold": 700,
    "BoldItalic": 700,
    "ExtraBold": 800,
    "ExtraBoldItalic": 800,
    "Black": 900,
    "BlackItalic": 900
  }
  pair = []
  for k, weight in WEIGHTS.items():
    if weight == font_metadata.weight:
      pair.append((k, weight))

  if not pair:
    yield FAIL, ("METADATA.pb: Font weight value ({})"
                 " is invalid.").format(font_metadata.weight)
  elif not (font_metadata.post_script_name.endswith('-' + pair[0][0]) or
            font_metadata.post_script_name.endswith('-' + pair[1][0])):
    yield FAIL, ("METADATA.pb: Mismatch between postScriptName (\"{}\")"
                 " and weight value ({}). The name must be"
                 " ended with \"{}\" or \"{}\"."
                 "").format(font_metadata.post_script_name,
                            pair[0][1],
                            pair[0][0],
                            pair[1][0])
  else:
    yield PASS, "Weight value matches postScriptName."
782845
def com_google_fonts_check_vendor_id(ttFont, registered_vendor_ids):
  """"""

  SUGGEST_MICROSOFT_VENDORLIST_WEBSITE = (
    " You should set it to your own 4 character code,"
    " and register that code with Microsoft at"
    " https://www.microsoft.com"
  "/typography/links/vendorlist.aspx")

  vid = ttFont['OS/2'].achVendID
  bad_vids = ['UKWN', 'ukwn', 'PfEd']
  if vid is None:
    yield WARN, Message("not set", "OS/2 VendorID is not set." +
                                   SUGGEST_MICROSOFT_VENDORLIST_WEBSITE)
  elif vid in bad_vids:
    yield WARN, Message("bad", ("OS/2 VendorID is '{}',"
                                " a font editor default.").format(vid) +
                                SUGGEST_MICROSOFT_VENDORLIST_WEBSITE)
  elif vid not in registered_vendor_ids.keys():
    yield WARN, Message("unknown", ("OS/2 VendorID value '{}' is not"
                                    " a known registered id.").format(vid) +
                                    SUGGEST_MICROSOFT_VENDORLIST_WEBSITE)
  else:
    yield PASS, f"OS/2 VendorID '{vid}' looks good!"
1196926
def com_google_fonts_check_name_mandatory_entries(ttFont, style):
  """"""
  from fontbakery.utils import get_name_entry_strings
  from fontbakery.constants import RIBBI_STYLE_NAMES

  required_nameIDs = [NameID.FONT_FAMILY_NAME,
                      NameID.FONT_SUBFAMILY_NAME,
                      NameID.FULL_FONT_NAME,
                      NameID.POSTSCRIPT_NAME]
  if style not in RIBBI_STYLE_NAMES:
    required_nameIDs += [NameID.TYPOGRAPHIC_FAMILY_NAME,
                         NameID.TYPOGRAPHIC_SUBFAMILY_NAME]
  failed = False
  # The font must have at least these name IDs:
  for nameId in required_nameIDs:
    if len(get_name_entry_strings(ttFont, nameId)) == 0:
      failed = True
      yield FAIL, (f"Font lacks entry with nameId={nameId}"
                   f" ({NameID(nameId).name})")
  if not failed:
    yield PASS, "Font contains values for all mandatory name table entries."
855860
def import_fonts(style_less, fontname, font_subdir):
    

    ftype_dict = {'woff2': 'woff2',
                  'woff': 'woff',
                  'ttf': 'truetype',
                  'otf': 'opentype',
                  'svg': 'svg'}

    define_font = (
        "@font-face {{font-family: {fontname};\n\tfont-weight:"
        "{weight};\n\tfont-style: {style};\n\tsrc: local('{fontname}'),"
        "\n\turl('fonts{sepp}{fontfile}') format('{ftype}');}}\n")
    fontname = fontname.split(',')[0]
    fontpath = os.path.join(fonts_dir, font_subdir)
    for fontfile in os.listdir(fontpath):
        if '.txt' in fontfile or 'DS_' in fontfile:
            continue
        weight = 'normal'
        style = 'normal'
        if 'medium' in fontfile:
            weight = 'medium'
        elif 'ital' in fontfile:
            style = 'italic'
        ft = ftype_dict[fontfile.split('.')[-1]]
        style_less += define_font.format(
            fontname=fontname,
            weight=weight,
            style=style,
            sepp='/',
            fontfile=fontfile,
            ftype=ft)
        send_fonts_to_jupyter(os.path.join(fontpath, fontfile))

    return style_less
577131
def com_google_fonts_check_varfont_generate_static(ttFont):
  
  import tempfile
  from fontTools.varLib import mutator

  try:
    loc = {k.axisTag: float((k.maxValue + k.minValue) / 2)
           for k in ttFont['fvar'].axes}
    with tempfile.TemporaryFile() as instance:
      font = mutator.instantiateVariableFont(ttFont, loc)
      font.save(instance)
      yield PASS, ("fontTools.varLib.mutator generated a static font "
                   "instance")
  except Exception as e:
    yield FAIL, ("fontTools.varLib.mutator failed to generated a static font "
                 "instance\n{}".format(repr(e)))
1271129
def _valid_designspace(self, designspace):
        
        # TODO: (jany) really make a copy to avoid modifying the original object
        copy = designspace
        # Load only full UFO masters, sparse or "brace" layer sources are assumed
        # to point to existing layers within one of the full masters.
        for source in (s for s in copy.sources if not s.layerName):
            if not hasattr(source, "font") or source.font is None:
                if source.path:
                    # FIXME: (jany) consider not changing the caller's objects
                    source.font = defcon.Font(source.path)
                else:
                    dirname = os.path.dirname(designspace.path)
                    ufo_path = os.path.join(dirname, source.filename)
                    source.font = defcon.Font(ufo_path)
            if source.location is None:
                source.location = {}
            for name in ("familyName", "styleName"):
                if getattr(source, name) != getattr(source.font.info, name):
                    self.logger.warning(
                        dedent(
                            """\
                    The {name} is different between the UFO and the designspace source:
                        source filename: {filename}
                        source {name}: {source_name}
                        ufo {name}: {ufo_name}

                    The UFO name will be used.
                    """
                        ).format(
                            name=name,
                            filename=source.filename,
                            source_name=getattr(source, name),
                            ufo_name=getattr(source.font.info, name),
                        )
                    )
                    setattr(source, name, getattr(source.font.info, name))
        return copy
612405
def com_google_fonts_check_metadata_copyright(family_metadata):
  """"""
  copyright = None
  fail = False
  for f in family_metadata.fonts:
    if copyright and f.copyright != copyright:
      fail = True
    copyright = f.copyright
  if fail:
    yield FAIL, ("METADATA.pb: Copyright field value"
                 " is inconsistent across family")
  else:
    yield PASS, "Copyright is consistent across family"
1247629
def com_google_fonts_check_fvar_name_entries(ttFont):
  """"""

  failed = False
  for instance in ttFont["fvar"].instances:

    entries = [entry for entry in ttFont["name"].names if entry.nameID == instance.subfamilyNameID]
    if len(entries) == 0:
      failed = True
      yield FAIL, (f"Named instance with coordinates {instance.coordinates}"
                   f" lacks an entry on the name table (nameID={instance.subfamilyNameID}).")

  if not failed:
    yield PASS, "OK"
581185
def com_google_fonts_check_family_has_license(licenses):
  """"""
  if len(licenses) > 1:
    yield FAIL, Message("multiple",
                        ("More than a single license file found."
                         " Please review."))
  elif not licenses:
    yield FAIL, Message("no-license",
                        ("No license file was found."
                         " Please add an OFL.txt or a LICENSE.txt file."
                         " If you are running fontbakery on a Google Fonts"
                         " upstream repo, which is fine, just make sure"
                         " there is a temporary license file in"
                         " the same folder."))
  else:
    yield PASS, "Found license at '{}'".format(licenses[0])
1303594
def find_font(font_name):
    """"""
    if font_name in STANDARD_FONT_NAMES:
        return font_name, True
    elif font_name in _registered_fonts:
        return font_name, _registered_fonts[font_name]

    NOT_FOUND = (None, False)
    try:
        # Try first to register the font if it exists as ttf,
        # based on ReportLab font search.
        registerFont(TTFont(font_name, '%s.ttf' % font_name))
        _registered_fonts[font_name] = True
        return font_name, True
    except TTFError:
        # Try searching with Fontconfig
        try:
            pipe = subprocess.Popen(
                ['fc-match', '-s', '--format=%{file}\\n', font_name],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            output = pipe.communicate()[0].decode(sys.getfilesystemencoding())
            font_path = output.split('\n')[0]
        except OSError:
            return NOT_FOUND
        try:
            registerFont(TTFont(font_name, font_path))
        except TTFError:
            return NOT_FOUND
        # Fontconfig may return a default font totally unrelated with font_name
        exact = font_name.lower() in os.path.basename(font_path).lower()
        _registered_fonts[font_name] = exact
        return font_name, exact
519991
def ufo2glyphs(options):
    """"""
    import fontTools.designspaceLib
    import defcon

    sources = options.designspace_file_or_UFOs
    designspace_file = None
    if (
        len(sources) == 1
        and sources[0].endswith(".designspace")
        and os.path.isfile(sources[0])
    ):
        designspace_file = sources[0]
        designspace = fontTools.designspaceLib.DesignSpaceDocument()
        designspace.read(designspace_file)
        object_to_read = designspace
    elif all(source.endswith(".ufo") and os.path.isdir(source) for source in sources):
        ufos = [defcon.Font(source) for source in sources]
        ufos.sort(
            key=lambda ufo: [  # Order the masters by weight and width
                ufo.info.openTypeOS2WeightClass or 400,
                ufo.info.openTypeOS2WidthClass or 5,
            ]
        )
        object_to_read = ufos
    else:
        print(
            "Please specify just one designspace file *or* one or more "
            "UFOs. They must end in '.designspace' or '.ufo', respectively.",
            file=sys.stderr,
        )
        return 1

    font = glyphsLib.to_glyphs(
        object_to_read, minimize_ufo_diffs=options.no_preserve_glyphsapp_metadata
    )

    # Make the Glyphs file more suitable for roundtrip:
    font.customParameters["Disable Last Change"] = options.enable_last_change
    font.disablesAutomaticAlignment = options.enable_automatic_alignment

    if options.output_path:
        font.save(options.output_path)
    else:
        if designspace_file:
            filename_to_write = os.path.splitext(designspace_file)[0] + ".glyphs"
        else:
            filename_to_write = os.path.join(
                os.path.dirname(sources[0]),
                font.familyName.replace(" ", "") + ".glyphs",
            )
        font.save(filename_to_write)
901892
def com_google_fonts_check_metadata_nameid_font_name(ttFont, style, font_metadata):
  
  from fontbakery.utils import get_name_entry_strings
  from fontbakery.constants import RIBBI_STYLE_NAMES

  if style in RIBBI_STYLE_NAMES:
    font_familynames = get_name_entry_strings(ttFont, NameID.FONT_FAMILY_NAME)
    nameid = NameID.FONT_FAMILY_NAME
  else:
    font_familynames = get_name_entry_strings(ttFont, NameID.TYPOGRAPHIC_FAMILY_NAME)
    nameid = NameID.TYPOGRAPHIC_FAMILY_NAME

  if len(font_familynames) == 0:
    yield FAIL, Message("lacks-entry",
                        (f"This font lacks a {NameID(nameid).name} entry"
                         f" (nameID={nameid}) in the name table."))
  else:
    for font_familyname in font_familynames:
      if font_familyname != font_metadata.name:
        yield FAIL, Message("mismatch",
                            ("Unmatched familyname in font:"
                             " TTF has \"{}\" while METADATA.pb has"
                             " name=\"{}\".").format(font_familyname,
                                                     font_metadata.name))
      else:
        yield PASS, ("OK: Family name \"{}\" is identical"
                     " in METADATA.pb and on the"
                     " TTF file.").format(font_metadata.name)
1013860
def _installed_fonts(cls):
        
        fonts = {}
        for d in cls._font_directories():
            for key, path in cls._iter_font_files_in(d):
                fonts[key] = path
        return fonts
505712
def com_google_fonts_check_name_license_url(ttFont, familyname):
  """""""
  from fontbakery.constants import PLACEHOLDER_LICENSING_TEXT
  LEGACY_UFL_FAMILIES = ["Ubuntu", "UbuntuCondensed", "UbuntuMono"]
  LICENSE_URL = {
    'OFL.txt': 'http://scripts.sil.org/OFL',
    'LICENSE.txt': 'http://www.apache.org/licenses/LICENSE-2.0',
    'UFL.txt': 'https://www.ubuntu.com/legal/terms-and-policies/font-licence'
  }
  LICENSE_NAME = {
    'OFL.txt': 'Open Font',
    'LICENSE.txt': 'Apache',
    'UFL.txt': 'Ubuntu Font License'
  }
  detected_license = False
  for license in ['OFL.txt', 'LICENSE.txt', 'UFL.txt']:
    placeholder = PLACEHOLDER_LICENSING_TEXT[license]
    for nameRecord in ttFont['name'].names:
      string = nameRecord.string.decode(nameRecord.getEncoding())
      if nameRecord.nameID == NameID.LICENSE_DESCRIPTION and\
         string == placeholder:
        detected_license = license
        break

  if detected_license == "UFL.txt" and familyname not in LEGACY_UFL_FAMILIES:
    yield FAIL, Message("ufl",
                        ("The Ubuntu Font License is only acceptable on"
                         " the Google Fonts collection for legacy font"
                         " families that already adopted such license."
                         " New Families should use eigther Apache or"
                         " Open Font License."))
  else:
    found_good_entry = False
    if detected_license:
      failed = False
      expected = LICENSE_URL[detected_license]
      for nameRecord in ttFont['name'].names:
        if nameRecord.nameID == NameID.LICENSE_INFO_URL:
          string = nameRecord.string.decode(nameRecord.getEncoding())
          if string == expected:
            found_good_entry = True
          else:
            failed = True
            yield FAIL, Message("licensing-inconsistency",
                                ("Licensing inconsistency in name table"
                                 " entries! NameID={} (LICENSE DESCRIPTION)"
                                 " indicates {} licensing, but NameID={}"
                                 " (LICENSE URL) has '{}'. Expected: '{}'"
                                 "").format(NameID.LICENSE_DESCRIPTION,
                                            LICENSE_NAME[detected_license],
                                            NameID.LICENSE_INFO_URL,
                                            string, expected))
    if not found_good_entry:
      yield FAIL, Message("no-license-found",
                          ("A known license URL must be provided in the"
                           " NameID {} (LICENSE INFO URL) entry."
                           " Currently accepted licenses are Apache or"
                           " Open Font License. For a small set of legacy"
                           " families the Ubuntu Font License may be"
                           " acceptable as well."
                           "").format(NameID.LICENSE_INFO_URL))
    else:
      if failed:
        yield FAIL, Message("bad-entries",
                            ("Even though a valid license URL was seen in"
                             " NAME table, there were also bad entries."
                             " Please review NameIDs {} (LICENSE DESCRIPTION)"
                             " and {} (LICENSE INFO URL)."
                             "").format(NameID.LICENSE_DESCRIPTION,
                                        NameID.LICENSE_INFO_URL))
      else:
        yield PASS, "Font has a valid license URL in NAME table."
467413
def com_google_fonts_check_metatada_canonical_style_names(ttFont, font_metadata):
  """"""
  from fontbakery.constants import MacStyle

  def find_italic_in_name_table():
    for entry in ttFont["name"].names:
      if entry.nameID < 256 and "italic" in entry.string.decode(entry.getEncoding()).lower():
        return True
    return False

  def is_italic():
    return (ttFont["head"].macStyle & MacStyle.ITALIC or
            ttFont["post"].italicAngle or
            find_italic_in_name_table())

  if font_metadata.style not in ["italic", "normal"]:
    yield SKIP, ("This check only applies to font styles declared"
                 " as \"italic\" or \"regular\" on METADATA.pb.")
  else:
    if is_italic() and font_metadata.style != "italic":
      yield FAIL, ("The font style is {}"
                   " but it should be italic").format(font_metadata.style)
    elif not is_italic() and font_metadata.style != "normal":
      yield FAIL, ("The font style is {}"
                   " but it should be normal").format(font_metadata.style)
    else:
      yield PASS, "Font styles are named canonically."