Desarrollo basado en pruebas para FontLab Studio 5 Python MacRos and Modules.
Fakelab es un reemplazo de FontLab Studio 5 para probar el código Python.
Todo se implementa solo para hacer que los objetos FONTLAB sean importables fuera de FontLab Studio 5, y ejecute pruebas.
Se sugiere instalar Fakelab en un entorno virtual, por lo que FontLab no importará accidentalmente el módulo falso al ejecutar los scripts en FontLab Studio 5 real. Si puede vivir con las incompatibilitas entre Python 2.7 y 3, también puede ejecutar Fakelab en Python 3.
Guardar VFBS no es compatible, ya que el formato VFB no es público, pero puede guardar objetos Font como JSON.
La implementación de Fakelab se basa en la invaluable referencia de API de FontLab/Python no oficial, y de ejecutar scripts en FontLab Studio y verificar lo que hacen, aparte de bloquear la aplicación.
Cuando haya activado su entorno virtual:
$ pip install -e .FL entonces es importable fuera de FontLab Studio:
from FL import fl , Font
# Make an empty font
f = Font ()
# Add the font to the mock app
fl . Add ( f )
# Close the font
fl . Close () Si se está ejecutando en un entorno virtual y necesita hacer que sus módulos FontLab sean importables, agregue un archivo .pth en el directorio de paquetes de sitios de su entorno virtual:
# fl5modules.pth
/Users/<yourname>/Code/FLMacros/System/Modules
Fakelab es un trabajo en progreso, y solo se implementa hasta donde lo necesitaba en mis propios scripts. Tengo que admitir que la mayor parte de ellos todavía no tiene pruebas.
Si se encuentra con un NotImplementedError mientras escribe pruebas, aquí es donde puede sobresalir para ayudar a mejorar este proyecto;) Estaré encantado de aceptar sus solicitudes de extracción. Alternativamente, abre un problema, cómprame un café y espero que mis hijos me dejen en paz para que pueda encontrar algo de tiempo para trabajar en su problema.
El desarrollo de scripts sin pruebas automatizadas es realmente solo para proyectos muy pequeños. Para estar seguro de los resultados de un módulo o script, siempre debe escribir pruebas. Esto generalmente se hace usando pytest.
Supongamos que tiene un script FontLab para seleccionar glifos que contengan componentes. Si tiene su propia colección de herramientas para FONTLAB, este script puede consistir en dos partes: un script que se enumera en la barra de herramientas macro de FontLab y un módulo Python que implementa la lógica, que se llama el script de la barra de herramientas.
Studio 5
+- Macros
+- Selection
+- Select Composites.py
+- System
+- Modules
+- fakeLabDemo
+- selection
+- __init__.py
+- composites.py
El script Select Composites.py se ve así:
#FLM: Select composites
# Studio 5/Macros/Selection/Select Composites.py
from fakeLabDemo . selection . composites import selectComposites
selectComposites ( fl . font )Y el módulo:
# Studio 5/Macros/System/Modules/fakeLabDemo/selection/composites.py
from __future__ import absolute_import , division , print_function
from FL import fl
def getFontIndex ( font ):
"""
Get the index of the supplied font.
We must iterate through the open fonts and compare file names,
because the == operator can not compare the font objects directly.
(FL font objects get a different id() each time they are called)
:param font: A title for the dialog.
:type font: :py:class:`FL.Font`
"""
for i in range ( len ( fl )):
cf = fl [ i ]
if cf . file_name == font . file_name :
if font . file_name is None :
if (
cf . family_name == font . family_name
and cf . style_name == font . style_name
):
return ( cf , i )
else :
return ( cf , i )
# Font was not found, probably there are no open fonts
return ( None , - 1 )
def setSelection ( font , glyph_names ):
"""
Set glyphs from the glyph_names list as selected in the font window.
"""
f , i = getFontIndex ( font )
if i > - 1 :
fl . ifont = i
fl . Unselect ()
for n in glyph_names :
fl . Select ( n )
def selectComposites ( font ):
"""
Select composites in font.
"""
setSelection (
font ,
[
glyph . name
for glyph in font . glyphs
if glyph . components
]
)¿Cómo podemos estar seguros de que este script hace lo que se supone que debe hacer? Para Pytest, agregamos otra estructura de carpeta paralela a la estructura existente:
Studio 5
+- Macros
+- Selection
+- Select Composites.py
+- System
+- Modules
+- fakeLabDemo
+- selection
+- __init__.py
+- composites.py
+- tests
+- fakeLabDemo
+- selection
+- composites_test.py
El archivo composites_test.py , que se llama análoga al archivo del módulo con el que se relaciona, es donde implementaremos nuestras pruebas:
# Studio 5/Macros/System/Modules/tests/fakeLabDemo/selection/composites_test.py
import pytest
from FL import fl , Component , Font , Glyph , Point
from fakeLabDemo . selection . composites import selectComposites
def test_selectComposites ():
# Construct a fake FontLab font object
font = Font ()
g = Glyph ( 1 )
g . name = "A"
g . width = 500
g . unicode = 0x41
font . glyphs . append ( g )
g = Glyph ( 1 )
g . name = "dieresis"
g . width = 500
g . unicode = 0xA8
font . glyphs . append ( g )
g = Glyph ( 1 )
g . name = "Adieresis"
g . width = 500
g . unicode = 0xC4
g . components . append ( Component ( 0 ))
g . components . append ( Component ( 1 , Point ( 0 , 300 )))
font . glyphs . append ( g )
# Add the font to the FL object
fl . Add ( font )
fl . UpdateFont ()
# Run our script to be tested on the font
selectComposites ( fl . font )
# You could save the fake font to JSON instead of VFB.
# fl.font.Save("test_composites.vfb.json")
# Test if the correct glyphs have been selected
assert fl . Selected ( 0 ) == 0
assert fl . Selected ( 1 ) == 0
assert fl . Selected ( 2 ) == 1
# Close the fake font
fl . Close ()Como puede ver, puede usar los objetos tal como lo haría dentro de FontLab. Simplemente no puede abrir una fuente de un VFB existente, lo que sería mucho más fácil. Pero el formato de archivo VFB no es público.
En cambio, debe construir una fuente de prueba utilizando la API FL Python.
Invoca el script de prueba en una ventana de terminal mientras su entorno virtual está activo:
cd " Studio 5/Macros/System/Modules "
python -m pytest tests/fakeLabDemo/selection/composites_test.pySi todo funciona, verá alguna salida como esta:
============================ test session starts ===============================
platform darwin -- Python 3.8.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /Users/jens/Code/fakelab
collected 1 item
tests/fakeLabDemo/selection/composites_test.py . [100%]
============================= 1 passed in 0.02s ================================