Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for checking UFOs #1736

Merged
merged 21 commits into from Mar 22, 2018
Merged

Initial support for checking UFOs #1736

merged 21 commits into from Mar 22, 2018

Conversation

madig
Copy link
Contributor

@madig madig commented Mar 19, 2018

First test runs ufolint on *.ufo.

First test runs ufolint on *ufo.
@googlebot
Copy link

So there's good news and bad news.

👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there.

😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request.

Note to project maintainer: This is a terminal state, meaning the cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

Eh... I'm submitting this PR from work, that's probably why googlebot mixes something up.

@anthrotype
Copy link
Member

you need to add your dama email address to your @madig github profile

yield FAIL, ("ufolint failed the UFO source. Output follows :"
"\n\n{}\n").format(e.output)
except OSError:
yield ERROR, "ufolint is not available!"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this ufolint be added as a dependency?
by the way, what does it actually do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counting lints in a UFO? Haven't read the source closely, but it will e.g. complain if the XML is malformed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I was wondering about that as well.

@felipesanches
Copy link
Collaborator

felipesanches commented Mar 19, 2018

In the past we had some ufo source checks but they were removed in order to refocus our development efforts. If you're willing to add more ufo checks, then I'm not in principle against doing so.

Having said that, I see that your first check simply hooks up an external tool (an UFO linter). I would like to postpone merging this PR until when we get at least a couple more checks here.

What do you think, @davelab6 ?

Maybe @graphicore and @m4rc1e have thoughts to share here as well? I think this kind of thing can be very useful for Marc, for instance.

@felipesanches
Copy link
Collaborator

@madig would you be OK with working for a while (a few days? a week? a month?) on this branch keeping this PR open until we decide it is good enough to justify merging into master?

Or would you rather commit early to a set of new checks to be added (and debugged) in the near future?

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

I'm fine with postponing, this is as much a proof of concept as it is a PR :) I want to do some company-internal checks here and work out what's useful and what isn't.

@felipesanches
Copy link
Collaborator

Great! Feel free to make them public in this PR (by pushing more commits to the same branch) and we'll likely have them in FB soon. If it is truly useful internally, then there's a good chance it may also be useful here and we'd love to gather such checks.

I looked at Travis and noticed that this initial commit breaks a few things. As it seems you're warming up for collaboration, I would be happy to help you figure out these things we deal with on a daily-basis while developing FontBakery.

For instance, any time one opens a pull request, a corresponding automated test-suite runs on Travis. You can see it at: https://travis-ci.org/googlefonts/fontbakery In particular, the latest commit resulted in a build-fail with the logs available here: https://travis-ci.org/googlefonts/fontbakery/builds/355351088

It would also be good to always add code-tests to ensure all code-paths in a font-check are behaving as expected. You can see several examples of this approach at https://github.com/googlefonts/fontbakery/blob/master/Lib/fontbakery/specifications/googlefonts_test.py

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

I know Travis, but why isn't it hooked up as a check here in the PR next to "cla/google"?

Will unbreak the tests :D I also added my work email to my account, can you trigger googlebot?



@register_check
@check(id='com.google.ufos/check/001', priority=CRITICAL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A check id does not really need to end in a number. We've been doing it that way, but perhaps we could use this as an opportunity to experimenting with doing it differently. Maybe this should end in /ufolint instead.

Also, you may prefer to identify the original contribution by using a different choice of reverse domain instead of com.google.

I also don't see a point in .ufoshere. If @davelab6 brings up some ufo-checking need from the Google Fonts project, for detecting some "foo" problem, I would then create a new check in this spec called something like com.google.fonts/check/foo and the resulting command line invocation to run this single check would then be:

fontbakery check-ufo-sources -c com.google.fonts/check/foo --verbose

For Dalton Maag contributions for checking some hypothetical "example" issue on UFO sources, then I'd suggest adopting an id such as: com.daltonmaag/check/example

Maybe it could be com.domain/check/ufo/something to make the fact we're dealing with UFOs explicit on the id. But I am not sure about that, yet.

@graphicore do you agree with my considerations here? Or would have other suggestions? This is definitely a work in progress.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe at some point we could consider adding a command-line attribute like -d domain to run only checks from a given domain. In that case, running only the Dalton Maag contributed UFO checks could work like this:

fontbakery check-ufo-sources -d com.daltonmaag --verbose

(possibly allowing multiple -d and -c flags in a single command to cherry-pick what a user wants...)

But I'm just speculating here. Not sure yet what we'll actually do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(How about pytest's -k switch:

  -k EXPRESSION         only run tests which match the given substring
                        expression. An expression is a python evaluatable
                        expression where all names are substring-matched
                        against test names and their parent classes. Example:
                        -k 'test_method or test_other' matches all test
                        functions and classes whose name contains
                        'test_method' or 'test_other', while -k 'not
                        test_method' matches those that don't contain
                        'test_method' in their names. Additionally keywords
                        are matched to classes and functions containing extra
                        names in their 'extra_keyword_matches' set, as well as
                        functions which have names assigned directly to them.

)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks powerful, but also a bit of over-engineering. I'd probably avoid that complexity.

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

Can't replicate the test failure locally...

@davelab6
Copy link
Contributor

I tend to think that UFO (and .glyphs) checking belongs in an editor extension rather than fontbakery, which has recently been scoped to checking TTFs.

However, if the fontbakery architecture is appealing to DaMa for running source checks, then having a profile as Felipe said for UFO would be great!

Almost all Google Fonts contributors are supplying .glyphs source files now, so we would benefit from a GlyphsLib based source checker too, and Marc has made one as a Glyphs in-app script (with a small UI)

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

I think it is okay with us if you decide that the UFO checking I do (still drafting!) is of no interest to the official fontbakery scope -- we can just as well make it an internally distributed module that gets loaded by check-spec and contribute just the parts to make that use-case work.

I suppose an editor extension makes sense, but only if the editor uses UFO as a native format. We round-trip from Fontlab to UFO with an internal script, which sometimes does unnecessary things -- hence the external checks we want to do on commits.

@davelab6
Copy link
Contributor

davelab6 commented Mar 19, 2018 via email

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

Oh, okay, no need to try, I'm motivated already ;)

@graphicore
Copy link
Collaborator

I tend to think that UFO (and .glyphs) checking belongs in an editor extension rather than fontbakery …

A font bakery editor extension could be an option. The font bakery check runner is rather light weight and an editor specific reporter could be created.

… fontbakery, which has recently been scoped to checking TTFs.

Another repo then for none-TTF specs?

Maybe I should spent some time to figure out and write down how third parties can best write their own specs, how checks can be shared and so on. Would also be a good thing to point to at TypoLabs.

@felipesanches
Copy link
Collaborator

I agree with Lasse on his comments. But if you'll write fontbakery-based checks I'd prefer to host them all in a single repo (here) to reduce potential segmentation. I pretty much would prefer to keep it all together in a "single universal font testing system" ;-)

@felipesanches
Copy link
Collaborator

@madig please add "check-ufo-sources" to the expected list of subcommands at test_list_subcommands_has_all_scripts

@felipesanches
Copy link
Collaborator

Please, also consider creating a new Lib/fontbakery/commands/check_ufo_sources_tests.py file where we could implement code tests for each of the ufo checks.

@madig
Copy link
Contributor Author

madig commented Mar 19, 2018

Okay, I was just surprised I can't reproduce the failure on my work machine...

Will do.

@felipesanches
Copy link
Collaborator

Once we get that minimal setup I'll be happy to merge soon (and often), as long as the code looks good and travis is kept green ;-)

@felipesanches
Copy link
Collaborator

Okay, I was just surprised I can't reproduce the failure on my work machine...

You may be running pytest on just the specifications subfolder and because of that the rest of the checks are not run on your machine. (I am guessing)

@graphicore
Copy link
Collaborator

But if you'll write fontbakery-based checks I'd prefer to host them all in a single repo (here) to reduce potential segmentation.

I see your point here and I agree that consequently contributing to this should be straight forward. I have some remarks though.

  1. We'll have more and more dependencies. I.e. someone who's interested in only checking UFOs will be forced to also install fonttools etc. when just ufoLib + ufoLint may be sufficient. Also vice versa, ufoLint will be a dependency also if you just want to check TTFs and it seems like glyphsLib will become a dependency rather sooner than later. I wonder if we could host submodules in the same repo, so that a cherry picking style installations become possible e.g. like pip install fontbakery-ufo (also installs fontbakery-core) and pip install fontbakery-ttf stuff like that. Just a thought.

  2. To allow people to implement their own foundry/project internal checks, such a guide is needed anyways. Ideally we can then backport useful third party checks into fontbakery as much as third parties will import fontbakery hosted checks into their specifiations.

@davelab6
Copy link
Contributor

davelab6 commented Mar 19, 2018 via email

@moyogo
Copy link
Contributor

moyogo commented Mar 20, 2018

Not all dependencies have to be installed, some parts can be unavailable unless their dependencies are installed.

@madig
Copy link
Contributor Author

madig commented Mar 20, 2018

@felipesanches when I run pytest Lib everything checks out?!

And please hook up Travis to the check-list thing below so Travis status displays there without me having to open a separate tab :)

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please rename this file so that its name is identical to the name of the script it tests, except for the _test suffix?

I mean to call it ufo_sources_test.pyinstead of ufo_source_test.py in order to match Lib/fontbakery/specifications/ufo_sources.py

except OSError:
yield ERROR, "ufolint is not available!"

yield PASS, "ufolint passed the UFO source."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need a boolean initialized as failed=False then make it True in the exception handlers above and then do "if not failed yield pass" here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a general pattern used throughout our codebase, actually

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, why not use else: appended to the try block?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the else branch runs when there is no exception, before the finally clause. That is its primary purpose. Here there is no finally so it doesn't make any difference

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another use of else is to do something only when no exception occurs and to not do that when exceptions are handled. In this case there is a yield in the except: branches, not a return, so technically Nikolaus is correct: if one where to call next() on the iterator returned by this function after a FAIL or an ERROR, it will surprisingly continue execution and meet a yield PASS. So yes, it would make sense to protect it with an else

import defcon

unnecessary_fields = []
ufo = defcon.Font(font)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is repeated in more than a single check. Make it a condition so that it can be reused (and probably save CPU time and memory)

You can look at specifications/googlefonts.py for examples such as this:
https://github.com/googlefonts/fontbakery/blob/fc9a4e68e5f002fe5df805b5fc6696b6bd1732cd/Lib/fontbakery/specifications/googlefonts.py#L78-L82

To use it, you simply pass the condition name as an argument to the check implementation.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use conditions=['ufo'] in this case (just like in the ttFont, it is also a special case). But in general, for other conditions you may want to do this:

https://github.com/googlefonts/fontbakery/blob/fc9a4e68e5f002fe5df805b5fc6696b6bd1732cd/Lib/fontbakery/specifications/googlefonts.py#L591-L597

The result of doing so is that if registered_vendor_ids is not available ("if not True"), then the check will be automatically skipped and this will be logged in the fontbakery summary report.

com_daltonmaag_check_recommended_fields as check)
ufo, ufo_path = empty_ufo_font

print('Test FAIL with empty UFO.')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARN

import defcon
import pytest

from fontbakery.checkrunner import (DEBUG, ENDCHECK, ERROR, FAIL, INFO, PASS,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove ENDCHECK here. Travis complains because this was not used at all.

At https://travis-ci.org/googlefonts/fontbakery/builds/355967025 you see:

************* Module fontbakery.specifications.ufo_sources_test
W:  8, 0: Unused ENDCHECK imported from fontbakery.checkrunner (unused-import)

@felipesanches
Copy link
Collaborator

According to https://travis-ci.org/googlefonts/fontbakery/builds/355967025 you are missing a "check-ufo-sources" subcommand. I think what this actually means is that in order to fix the TestSubcommands.test_list_subcommands_has_all_scripts test on Travis you'll have to add a '''bin/fontbakery-check-ufo-sources.py''' script similar to this one:

https://github.com/googlefonts/fontbakery/blob/7aec375b7f174934fdeb6aac754b7ed4d5c35b60/bin/fontbakery-check-googlefonts.py#L1-L7

@madig
Copy link
Contributor Author

madig commented Mar 21, 2018

But bin/fontbakery-check-ufo-sources.py already exists and is commited 😕

@moyogo
Copy link
Contributor

moyogo commented Mar 22, 2018

You can define optional dependencies with extras_require like in: robotools/defcon#177

@felipesanches
Copy link
Collaborator

felipesanches commented Mar 22, 2018

But bin/fontbakery-check-ufo-sources.py already exists and is commited

did you make it an executablescript with chmod a+x ? If I recall correctly that's necessary for the script to be detected by fontbakery as a valid subcommand.

@felipesanches
Copy link
Collaborator

I want to merge this PR, but there are 2 code-tests failing right now:

  • test_check_ufolint (the check resulted in ERROR instead of PASS)
  • TestSubcommands::test_list_subcommands_has_all_scripts (you probably just need to chmod a+x bin/fontbakery-check-ufo-sources.py)

@madig Could you quickly fix these so that I can merge this PR?

Detailed Travis log listing these two problems at:
https://travis-ci.org/googlefonts/fontbakery/builds/356340681

Copy link
Collaborator

@felipesanches felipesanches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chmod worked, but the ufolint check still fails on Travis. Here are my thoughts on what could possibly fix this.

.travis.yml Outdated
@@ -19,6 +19,7 @@ install:
- pip install pytest
- pip install flake8
- pip install pylint
- pip install ufodiff
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we get an ERROR on the com_daltonmaag_check_ufolint test on Travis, it probably means we need to install ufolint here as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print('Test PASS with empty UFO.')
c = list(check(ufo_path))
status, _ = c[-1]
assert status == PASS
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does ufolint really PASS with an empty UFO? Shouldn't it complain about it being empty? And also all other problems that such a degenerated case would likely trigger?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I installed the wrong package because the cross-activity on GH distracted me :D

I think ufolint only does a bare minimum checking of technicalities. That's why there are more checks to be made ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

greeeeeeeeeeeeeeeeeeeeeeen

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright !!! :-D

@felipesanches felipesanches merged commit d0ffa1f into fonttools:master Mar 22, 2018
@felipesanches
Copy link
Collaborator

Thanks a lot, @madig ! We appreciate the work you're doing ;-)

Feel free to open another PR if you have further contribs to submit and we'll review those as well.
Beware that I'm catching a long international flight tonight and I'll only be back tomorrow afternoon.

cheers!

@madig
Copy link
Contributor Author

madig commented Mar 22, 2018

Damn. I forgot to pull Unicode ranges from unnecessary. Those actually have to be set by hand, ufo2ft won't do that, on purpose.

@madig madig deleted the check-ufo-sources branch March 22, 2018 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants