Smed crashes with python extension

Issue #34 resolved
Georg Mayr-Duffner created an issue

I’m loading my glyphbuilder script as a menu entry in smed. It should build composed glyphs from components listed in a dictionary. It’s here: https://github.com/georgd/EB-Garamond/blob/master/tools/glyphbuilder.py

Whenever I try to apply it to a glyph, smed crashes.

Comments (37)

  1. Barry Schwartz

    This is good for me to have a script handy. I can get it working in Python, but also I can make the support for doing it easily in Scheme. :) (Though that could take a while, because I am doing major rework of how glyphs are represented internally, to better support extension languages.)

  2. Georg Mayr-Duffner reporter

    Great. I need that extension often, because the builtin "build composites" tool is way too limited and gives buggy output when more than two components have to be combined.

  3. Barry Schwartz

    I use my own composite-building code, too, though I haven’t tried compiling my fonts with SM Tools. I think every person serious about automating this ends up writing their own code.

    The problem seems to involve the return values from ‘action’ (as opposed to ‘enabled’) functions. These return values are not used for anything but for simplification I assume they exist. (Or, to put it more succinctly, I’m investigating the bug right now.)

  4. Barry Schwartz

    This is inadequate to get things working but I would make the following change anyway, for stylistic reasons--not just because activeFont() currently isn’t working in this case :)

    #  font_file = os.path.normpath(fontforge.activeFont().path)
    font_file = os.path.normpath(object.font.path)
    
  5. Barry Schwartz

    Try moving the

    from glyphcomponents import glyphComponents

    to the top of the glyphbuilder.py module and see if that works, at least with the other change I suggest above. I do not think importing glyphcomponents like that within a function is something I’ll go to the trouble of making work. Is there a particular reason for it? You can still put it in a try-except block, just at the global level.

  6. Barry Schwartz

    The reason for the original crash seems simply failure to check whether the ‘action’ function succeeded, and so wasn’t the root problem. I think the things mentioned above were.

  7. Georg Mayr-Duffner reporter

    Please understand that I don’t really know how to write such code. The original glyphbuilder script was put together from snippets which I modelled after what I saw in different scripts (among which your script figures too) while simultaneously jumping through the first few chapters of a python tutorial. The problem here is that I want the glyphcomponents script to stay at the font’s directory so I can use different components def’s for different fonts. I got help there because the chapters of the tutorial that I went through didn’t talk about try-except and I had no idea how to do the path trickery.

    If I move

    try:
        sys.path.append(tool_path)
        from glyphcomponents import glyphComponents
    except ImportError:
        fontforge.postError("Cannot import Python module glyphcomponents",
                "This script is made to work with the SFDs residing in top_level/SFD and the module in top_level/tools.")
    

    to the top of the script it complains that tool_path isn’t defined. If I then move the path definitions block before the try-except one (this time again with fontforge.activeFont because object wouldn’t make sense here I think), I still get an error.

    I’m clueless.

  8. Barry Schwartz

    Now I see what the code is supposed to do.

    Python is very difficult to work with on stuff like that. More reason I hate it. I’ll try modifying the script myself.

  9. Barry Schwartz

    Try this patch, if you don’t mind.

    This version works for me. Also it should let you modify the glyphcomponents.py file without restarting smed (though I haven’t tested it for that).

    The way the module is loaded here is similar to how I load per-font stuff in the Python code at sortsmill.googlecode.com, where I have to edit stuff while working and have it reloaded without restarting the editor.

  10. Georg Mayr-Duffner reporter

    Thank you! Sadly, it still crashes. When selecting the menu point "tools" the terminal tells me

    _xgeWireToEvent: Unknown extension 131, this should never happen.
    _xgeWireToEvent: Unknown extension 131, this should never happen.
    _xgeWireToEvent: Unknown extension 131, this should never happen.
    

    When clicking on "glyphbuilder" in a glyph without entry in the dictionary, it issues the expected error notice and continues, when within a glyph to be composed, it crashes.

    Reloading without having to restart the editor is really great! Is it the try block after if import_successful?

  11. Barry Schwartz

    It’s the reload() function.

    It works for me but then I have made a few changes to my working version of smed. Perhaps I’ll have to finish and check that in.

    Using try blocks is good because I would not count on smed to catch Python exceptions nicely. Try blocks do no harm when using the original FontForge, either. (The syntax is clumsy, though.)

  12. Georg Mayr-Duffner reporter

    Ok, no crashing any longer. Now, when trying to compose a glyph, i get this message in the terminal: 'NoneType' object has no attribute 'path'

  13. Barry Schwartz

    Hmm. I’m actually going to guess that ‘NoneType’ is the value of the variable ‘os’. In other words ‘os.path’ is not imported. Try adding ‘import os’ to the top of user_init.py and if that works it will be a clue.

  14. Georg Mayr-Duffner reporter

    import os is already the first line because I copy the glyphbuilder script to user_init.py Not needing any other script at that place I decided it’s safe to be so lazy to not investigate how to load it otherways, even if probably quite easy. If, however, you tell me that it does matter, I’ll change that.

  15. Barry Schwartz

    I’ll try that copying method. I’ve been using PYTHONPATH to locate glyphbuilder and then an import statement in user_init.py.

    It’s quite possible that I’m getting a different set of imports. We’ve run into that problem with Guile code.

  16. Barry Schwartz

    I would say the preferred way to install a module like that is to install it as an ordinary Python module, for instance using setuptools, and then use import. But, if you want something that loads scripts from a special subdirectory the way FontForge does, I can easily write a Python module that will let you do that. Would you prefer that?

    (The ease of doing such things and more once you have startup scripts is why I was astonished that the idea was rejected for FontForge, and contributed significantly to the decision to do the fork.)

  17. Barry Schwartz

    I get the same error you do if I load glyphbuilder that way you are doing, which is very good. :))))

  18. Barry Schwartz

    Make this workaround change and it should work:

    #    font = object if type(object).__name__ == "font" else object.font
    font = fontforge.activeFont()
    

    In other words, put that back to how you were doing that before, now that it is supported in smed. (It used to be activeFont wasn’t getting set if you were in glyph view.)

  19. Barry Schwartz

    I need to fix the problem, and I appreciate your encounter with it. The Python support is messy at best (but that’s true for FF, as well).

  20. Barry Schwartz

    The problem was something I suspected was a problem yesterday but for some reason I couldn’t remember the better way of writing it. I changed the type tests to ‘isinstance (variablename, fontforge.font)’ in the attached script.

    I think one nearly always wants to use isinstance(), although writing ‘type(variablename) == type(some_object_known_to_be_of_the_type)’ also works.

  21. Barry Schwartz

    I know why I thought it worked. It’s because it works if you first run glyphbuild from the font menu and then later from the glyph menu, but not if you run it from the glyph menu first. I can fix that.

    (This is a very clumsy part of the FF code BTW, so it isn’t surprising that what little change I’ve made has cascading effects where things that are supposed to happen don’t.)

  22. Georg Mayr-Duffner reporter

    Ok. I randomly try from font view and glyph view. From now on I’ll try both before replying-

  23. Barry Schwartz

    BTW (off topic) have you had any problems with editing being slow? And are you on a 32-bit or 64-bit platform? There seem to be problems at least on Ubuntu 32-bit.

  24. Georg Mayr-Duffner reporter

    No, I din’t have such problems. I’m on a 64-bit platform (mostly Arch, but also Mint/Debian and Fedora, I don’t know if I want to give Ubuntu another chance)

  25. Barry Schwartz

    Installing on a 32-bit Ubuntu should be ‘easy’ now; you might not even need anything but standard packages, with the latest release (13.04). But I haven’t tried it on a 64-bit Ubuntu.

    With the LTS version of Ubuntu you may need a GNU PPA and may need to use pip or easy_install to install Cython. I do not remember if you still need to install PCRE on your own. With the later 12.x (12.10?) release you don’t.

    Of course it’s still a chore to find all the ‘dev’ packages, which is a type of problem I prefer to entirely avoid by using Gentoo. :) Though for VirtualBoxes I really do appreciate Ubuntu.

  26. Georg Mayr-Duffner reporter

    It’s not a question of installing smed (I managed on LMDE so it shouldn’t be a problem) but rather of liking Ubuntu.

    And I like that I don't have to think about 'dev' packages on Arch :)

  27. Barry Schwartz

    I just remembered that I made Sorts Mill Tools compatible with older versions of PCRE and so, yes, you can just use the one that comes with Ubuntu LTS.

    We solved the slowdown problem and you might notice that editing splines is faster. The difference on x86 is much greater, though.

  28. Log in to comment