diff --git a/CHANGELOG.md b/CHANGELOG.md index d811b45cc5..c231f551af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,11 @@ A more detailed list of changes is available in the corresponding milestones for - Axis Registry has been updated to commit https://github.com/google/fonts/tree/6418bd97834330f245cce4131ec3b8b98cb333be which includes changes to the `opsz` axis. - Format status output to improve readability. (issue #2052) - Move reporter-specific write logic to reporters, simplify argparse (PR #3206) + - Profile-specific `fontbakery.commands.check_...` removed and replaced with a call to `check_profile` with the appropriate profile. (PR #3218) - HTML reporter parses and renders markdown. (PR #3212) ### New Profile - - new Type Network profile for checking some of their new axis proposals (issue #3130) - - **[com.google.fonts/check/kern_table]:** add FAIL when non-character glyph present, WARN when no format-0 subtable present. + - Created a Type Network profile for checking some of their new axis proposals (issue #3130) ### Bugfixes - **license** condition now assumes that all license files in a given project repo are identical if more than one is found. With that some checks wont be skipped. We should have a fontbakery check to ensuring that assumption is valid, though. (issue #3172) @@ -24,6 +24,7 @@ A more detailed list of changes is available in the corresponding milestones for - **[com.google.fonts/check/missing_small_caps_glyphs]:** Check small caps glyphs are available (issue #3154) ### Changes to existing checks + - **[com.google.fonts/check/kern_table]:** add FAIL when non-character glyph present, WARN when no format-0 subtable present. - **[com.google.fonts/check/gf-axisregistry/fvar_axis_defaults]:** Only check axes which are in the GF Axis Registry (PR #3217) - **[com.google.fonts/check/mandatory_avar_table]:** Update rationale to mention that this check may be ignored if axis progressions are linear. - **[com.google.fonts/check/integer_ppem_if_hinted]:** Format message with newlines. diff --git a/Lib/fontbakery/cli.py b/Lib/fontbakery/cli.py index c35cc7c4f0..67124b675f 100644 --- a/Lib/fontbakery/cli.py +++ b/Lib/fontbakery/cli.py @@ -2,15 +2,34 @@ import pkgutil import runpy import sys +from importlib import import_module import fontbakery.commands +from fontbakery.commands.check_profile import main as check_profile_main + +CLI_PROFILES = [ + "adobefonts", + "fontval", + "googlefonts", + "notofonts", + "opentype", + "typenetwork", + "ufo_sources", + "universal", +] + + +def run_profile_check(profilename): + module = import_module("fontbakery.profiles.%s" % profilename) + sys.exit(check_profile_main(module.profile)) def main(): subcommands = [ - pkg[1].replace("_", "-") - for pkg in pkgutil.walk_packages(fontbakery.commands.__path__) - ] + pkg[1] for pkg in pkgutil.walk_packages(fontbakery.commands.__path__) + ] + ["check_" + prof for prof in CLI_PROFILES] + + subcommands = [command.replace("_", "-") for command in sorted(subcommands)] if len(sys.argv) >= 2 and sys.argv[1] in subcommands: # Relay to subcommand. @@ -18,8 +37,15 @@ def main(): subcommand_module = subcommand.replace("-", "_") sys.argv[0] += " " + subcommand del sys.argv[1] # Make this indirection less visible for subcommands. - runpy.run_module( - "fontbakery.commands." + subcommand_module, run_name='__main__') + if ( + subcommand_module.startswith("check_") + and subcommand_module[6:] in CLI_PROFILES + ): + run_profile_check(subcommand_module[6:]) + else: + runpy.run_module( + "fontbakery.commands." + subcommand_module, run_name="__main__" + ) else: description = ( "Run fontbakery subcommands. Subcommands have their own help " diff --git a/Lib/fontbakery/commands/check_adobefonts.py b/Lib/fontbakery/commands/check_adobefonts.py deleted file mode 100644 index f8b1a1218a..0000000000 --- a/Lib/fontbakery/commands/check_adobefonts.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.adobefonts import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - - -main = partial(super_main, profile, values=BLOCKLISTS) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_fontval.py b/Lib/fontbakery/commands/check_fontval.py deleted file mode 100644 index 2948c8ee73..0000000000 --- a/Lib/fontbakery/commands/check_fontval.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.fontval import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - -main = partial(super_main, profile) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_googlefonts.py b/Lib/fontbakery/commands/check_googlefonts.py deleted file mode 100644 index 9751aacc44..0000000000 --- a/Lib/fontbakery/commands/check_googlefonts.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.googlefonts import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - -main = partial(super_main, profile, values=BLOCKLISTS) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_notofonts.py b/Lib/fontbakery/commands/check_notofonts.py deleted file mode 100644 index f1eb2ab337..0000000000 --- a/Lib/fontbakery/commands/check_notofonts.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.notofonts import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - -main = partial(super_main, profile) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_opentype.py b/Lib/fontbakery/commands/check_opentype.py deleted file mode 100644 index 11495b686c..0000000000 --- a/Lib/fontbakery/commands/check_opentype.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -import sys -from functools import partial - -import fontbakery.profiles.opentype -from fontbakery.commands.check_profile import (main as super_main, - get_module_profile) - -main = partial(super_main, - get_module_profile(fontbakery.profiles.opentype)) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_profile.py b/Lib/fontbakery/commands/check_profile.py index de6538528c..49fdc00bdb 100644 --- a/Lib/fontbakery/commands/check_profile.py +++ b/Lib/fontbakery/commands/check_profile.py @@ -243,11 +243,6 @@ def error(message): raise ArgumentParserError(message) raise Exception(f"Can't get a profile from {imported}.") return profile -# This stub or alias is kept for compatibility (e.g. check-commands, FontBakery -# Dashboard). The function of the same name previously only passed on all parameters to -# CheckRunner. -runner_factory = CheckRunner - def main(profile=None, values=None): # profile can be injected by e.g. check-googlefonts injects it's own profile add_profile_arg = False diff --git a/Lib/fontbakery/commands/check_typenetwork.py b/Lib/fontbakery/commands/check_typenetwork.py deleted file mode 100644 index 34fd1c4acb..0000000000 --- a/Lib/fontbakery/commands/check_typenetwork.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.typenetwork import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - - -main = partial(super_main, profile, values=BLOCKLISTS) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_ufo_sources.py b/Lib/fontbakery/commands/check_ufo_sources.py deleted file mode 100644 index 19e8d94d5a..0000000000 --- a/Lib/fontbakery/commands/check_ufo_sources.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -import sys -from functools import partial - -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) -from fontbakery.profiles.ufo_sources import profile, BLOCKLISTS - - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - - -main = partial(super_main, profile, values=BLOCKLISTS) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/commands/check_universal.py b/Lib/fontbakery/commands/check_universal.py deleted file mode 100644 index bbf978cc56..0000000000 --- a/Lib/fontbakery/commands/check_universal.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import sys - -from functools import partial -from fontbakery.profiles.universal import profile, BLOCKLISTS -from fontbakery.commands.check_profile import ( - runner_factory as super_runner_factory, main as super_main) - -# runner_factory is used by the fontbakery dashboard. -# It is here in order to have a single place from which -# the profile is configured for the CLI and the worker. -def runner_factory(fonts): - values = {} - values.update(BLOCKLISTS) - values['fonts'] = fonts - return super_runner_factory(profile, values=values) - -main = partial(super_main, profile) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Lib/fontbakery/profiles/adobefonts.py b/Lib/fontbakery/profiles/adobefonts.py index e262af6ecb..d694728f98 100644 --- a/Lib/fontbakery/profiles/adobefonts.py +++ b/Lib/fontbakery/profiles/adobefonts.py @@ -12,8 +12,6 @@ profile_imports = ('fontbakery.profiles.universal',) profile = profile_factory(default_section=Section("Adobe Fonts")) -BLOCKLISTS = {} - ADOBEFONTS_PROFILE_CHECKS = \ UNIVERSAL_PROFILE_CHECKS + [ 'com.adobe.fonts/check/family/consistent_upm', diff --git a/Lib/fontbakery/profiles/fontval.py b/Lib/fontbakery/profiles/fontval.py index 5c8bd75b84..8ba3d4f51f 100644 --- a/Lib/fontbakery/profiles/fontval.py +++ b/Lib/fontbakery/profiles/fontval.py @@ -9,8 +9,6 @@ profile_imports = ['.shared_conditions'] profile = profile_factory(default_section=Section("Checks inherited from Microsoft Font Validator")) -BLOCKLISTS = {} - @check( id = 'com.google.fonts/check/fontvalidator' ) diff --git a/Lib/fontbakery/profiles/googlefonts.py b/Lib/fontbakery/profiles/googlefonts.py index 75bc0ba6b6..93245ddb25 100644 --- a/Lib/fontbakery/profiles/googlefonts.py +++ b/Lib/fontbakery/profiles/googlefonts.py @@ -18,8 +18,6 @@ profile_imports = ('fontbakery.profiles.universal',) profile = profile_factory(default_section=Section("Google Fonts")) -BLOCKLISTS = {} - METADATA_CHECKS = [ 'com.google.fonts/check/metadata/parses', 'com.google.fonts/check/metadata/unknown_designer', diff --git a/Lib/fontbakery/profiles/notofonts.py b/Lib/fontbakery/profiles/notofonts.py index fa5f6a5c05..8020e058c6 100644 --- a/Lib/fontbakery/profiles/notofonts.py +++ b/Lib/fontbakery/profiles/notofonts.py @@ -28,8 +28,6 @@ CMAP_TABLE_CHECKS + \ OS2_TABLE_CHECKS -BLOCKLISTS = {} - @check( id = 'com.google.fonts/check/cmap/unexpected_subtables', rationale = """ diff --git a/Lib/fontbakery/profiles/typenetwork.py b/Lib/fontbakery/profiles/typenetwork.py index fd3c4659fd..8e885a5c54 100644 --- a/Lib/fontbakery/profiles/typenetwork.py +++ b/Lib/fontbakery/profiles/typenetwork.py @@ -17,8 +17,6 @@ 'io.github.abysstypeco/check/ytlc_sanity' ] -BLOCKLISTS = {} - @check( id='io.github.abysstypeco/check/ytlc_sanity', rationale=""" diff --git a/Lib/fontbakery/profiles/ufo_sources.py b/Lib/fontbakery/profiles/ufo_sources.py index 46e106dbea..a0a20bc84f 100644 --- a/Lib/fontbakery/profiles/ufo_sources.py +++ b/Lib/fontbakery/profiles/ufo_sources.py @@ -6,8 +6,6 @@ from fontbakery.section import Section from fontbakery.profile import Profile -BLOCKLISTS = {} - class UFOProfile(Profile): def setup_argparse(self, argument_parser): diff --git a/Lib/fontbakery/profiles/universal.py b/Lib/fontbakery/profiles/universal.py index fefa8e5df9..9e3779a0e1 100644 --- a/Lib/fontbakery/profiles/universal.py +++ b/Lib/fontbakery/profiles/universal.py @@ -49,8 +49,6 @@ 'com.google.fonts/check/rupee' ] -BLOCKLISTS = {} - @check( id = 'com.google.fonts/check/name/trailing_spaces', ) diff --git a/tests/commands/test_usage.py b/tests/commands/test_usage.py index 53e048c12a..5c1947a911 100644 --- a/tests/commands/test_usage.py +++ b/tests/commands/test_usage.py @@ -7,8 +7,9 @@ def test_list_subcommands_has_all_scripts(): """Tests if the output from running `fontbakery --list-subcommands` matches - the fontbakery scripts within the bin folder.""" + the fontbakery scripts within the bin folder and the promoted profiles.""" import fontbakery.commands + from fontbakery.cli import CLI_PROFILES commands_dir = os.path.dirname(fontbakery.commands.__file__) scripts = [ @@ -16,6 +17,7 @@ def test_list_subcommands_has_all_scripts(): for f in os.listdir(commands_dir) if (f.endswith(".py") and not f.startswith('_')) ] + scripts = scripts + [ ("check-"+i).replace("_", "-") for i in CLI_PROFILES ] subcommands = subprocess.check_output( ['fontbakery', '--list-subcommands']).decode().split() assert sorted(scripts) == sorted(subcommands)