Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def com_google_fonts_check_003(description):
"""Does DESCRIPTION file contain broken links?"""
from lxml.html import HTMLParser
import defusedxml.lxml
import requests
doc = defusedxml.lxml.fromstring(description, parser=HTMLParser())
broken_links = []
for link in doc.xpath('//a/@href'):
if link.startswith("mailto:") and \
"@" in link and \
"." in link.split("@")[1]:
yield INFO, (f"Found an email address: {link}")
continue
try:
response = requests.head(link, allow_redirects=True, timeout=10)
code = response.status_code
if code != requests.codes.ok:
broken_links.append(("url: '{}' "
"status code: '{}'").format(link, code))
except requests.exceptions.Timeout:
yield WARN, ("Timedout while attempting to access: '{}'."
" Please verify if that's a broken link.").format(link)
except requests.exceptions.RequestException:
broken_links.append(link)
if len(broken_links) > 0:
yield FAIL, ("The following links are broken"
, ERROR
, STARTSECTION
, STARTCHECK
, SKIP
, PASS
, FAIL
, ENDCHECK
, ENDSECTION
, START
, END
, DEBUG
, Status
)
statuses = (
INFO
, WARN
, ERROR
, STARTSECTION
, STARTCHECK
, SKIP
, PASS
, FAIL
, ENDCHECK
, ENDSECTION
, START
, END
, DEBUG
)
# these are displayed in the result counters
check_statuses = [ERROR, FAIL, SKIP, PASS, WARN, INFO]
check_statuses.sort(key=lambda s:s.weight, reverse=True)
, FAIL
, STARTSECTION
, ENDSECTION
)
log_levels = OrderedDict((s.name,s) for s in sorted((
DEBUG
, INFO
, WARN
, ERROR
, SKIP
, PASS
, FAIL
)))
DEFAULT_LOG_LEVEL = INFO
from fontbakery.reporters.terminal import TerminalReporter
from fontbakery.reporters.serialize import SerializeReporter
from fontbakery.reporters.ghmarkdown import GHMarkdownReporter
from fontbakery.reporters.html import HTMLReporter
def ArgumentParser(profile, profile_arg=True):
argument_parser = argparse.ArgumentParser(description="Check TTF files"
" against a profile.",
formatter_class=argparse.RawTextHelpFormatter)
if profile_arg:
argument_parser.add_argument('profile',
help='File/Module name, must define a fontbakery "profile".')
def com_google_fonts_check_kern_table(ttFont):
"""Is there a "kern" table declared in the font?"""
if "kern" in ttFont:
yield INFO,\
Message("kern-found",
'Only a few programs may require the kerning'
' info that this font provides on its "kern" table.')
# TODO: perhaps we should add code here to detect and emit a FAIL
# if the kern table and subtable version and format are not zero,
# as mentioned in the rationale above.
else:
yield PASS, 'Font does not declare an optional "kern" table.'
return
width_sum = 0
for glyph_id in weightFactors:
width = ttFont['hmtx'].metrics[glyph_id][0]
width_sum += (width * weightFactors[glyph_id])
expected_value = int(width_sum / 1000.0 + 0.5) # round to closest int
difference = abs(current_value - expected_value)
# We accept matches and off-by-ones due to rounding as correct.
if current_value == expected_value or difference == 1:
yield PASS, "OS/2 xAvgCharWidth value is correct."
elif difference < ACCEPTABLE_ERROR:
yield INFO, (f"OS/2 xAvgCharWidth is {current_value} but it should be"
f" {expected_value} which corresponds to {calculation_rule}."
f" These are similar values, which"
f" may be a symptom of the slightly different"
f" calculation of the xAvgCharWidth value in"
f" font editors. There's further discussion on"
f" this at https://github.com/googlefonts/fontbakery"
f"/issues/1622")
else:
yield WARN, (f"OS/2 xAvgCharWidth is {current_value} but it should be"
f" {expected_value} which corresponds to {calculation_rule}.")
# And, finally, the log messages are emitted:
if data["errortype"] == "P":
yield PASS, report_message(msg, data["details"])
elif data["errortype"] == "E":
status = FAIL
for substring in downgrade_to_warn:
if substring in msg:
status = WARN
yield status, report_message(msg, data["details"])
elif data["errortype"] == "W":
yield WARN, report_message(msg, data["details"])
else:
yield INFO, report_message(msg, data["details"])
, Profile
, get_module_profile
, DEBUG
, INFO
, WARN
, ERROR
, SKIP
, PASS
, FAIL
, STARTSECTION
, ENDSECTION
)
log_levels = OrderedDict((s.name,s) for s in sorted((
DEBUG
, INFO
, WARN
, ERROR
, SKIP
, PASS
, FAIL
)))
DEFAULT_LOG_LEVEL = INFO
from fontbakery.reporters.terminal import TerminalReporter
from fontbakery.reporters.serialize import SerializeReporter
from fontbakery.reporters.ghmarkdown import GHMarkdownReporter
from fontbakery.reporters.html import HTMLReporter
def ArgumentParser(profile, profile_arg=True):
argument_parser = argparse.ArgumentParser(description="Check TTF files"
self.msgs.append(data)
def restore(self):
sys.stderr = self.original_stderr
sys.stdout = self.original_stdout
from xml.parsers.expat import ExpatError
try:
logger = TTXLogger()
xml_file = font + ".xml"
ttFont.saveXML(xml_file)
export_error_msgs = logger.msgs
if len(export_error_msgs):
failed = True
yield INFO, ("While converting TTF into an XML file,"
" ttx emited the messages listed below.")
for msg in export_error_msgs:
yield FAIL, msg.strip()
f = ttx.TTFont()
f.importXML(font + ".xml")
import_error_msgs = [msg for msg in logger.msgs if msg not in export_error_msgs]
if len(import_error_msgs):
failed = True
yield INFO, ("While importing an XML file and converting"
" it back to TTF, ttx emited the messages"
" listed below.")
for msg in import_error_msgs:
yield FAIL, msg.strip()
logger.restore()
NameID.TYPOGRAPHIC_SUBFAMILY_NAME):
if len(string) >= 32:
bad_entries.append({
'field': 'OT Style Name',
'value': string,
'rec': 'exceeds max length (31)'
})
if len(bad_entries) > 0:
table = "| Field | Value | Recommendation |\n"
table += "|:----- |:----- |:-------------- |\n"
for bad in bad_entries:
table += "| {} | {} | {} |\n".format(bad["field"],
bad["value"],
bad["rec"])
yield INFO,\
Message("bad-entries",
f"Font does not follow "
f"some family naming recommendations:\n"
f"\n"
f"{table}")
else:
yield PASS, "Font follows the family naming recommendations."