|
|
|
|
|
|
|
|
|
from fontTools.ttLib.tables.DefaultTable import DefaultTable |
|
import logging |
|
|
|
|
|
log = logging.getLogger("fontTools.merge") |
|
|
|
|
|
def add_method(*clazzes, **kwargs): |
|
"""Returns a decorator function that adds a new method to one or |
|
more classes.""" |
|
allowDefault = kwargs.get("allowDefaultTable", False) |
|
|
|
def wrapper(method): |
|
done = [] |
|
for clazz in clazzes: |
|
if clazz in done: |
|
continue |
|
done.append(clazz) |
|
assert allowDefault or clazz != DefaultTable, "Oops, table class not found." |
|
assert ( |
|
method.__name__ not in clazz.__dict__ |
|
), "Oops, class '%s' has method '%s'." % (clazz.__name__, method.__name__) |
|
setattr(clazz, method.__name__, method) |
|
return None |
|
|
|
return wrapper |
|
|
|
|
|
def mergeObjects(lst): |
|
lst = [item for item in lst if item is not NotImplemented] |
|
if not lst: |
|
return NotImplemented |
|
lst = [item for item in lst if item is not None] |
|
if not lst: |
|
return None |
|
|
|
clazz = lst[0].__class__ |
|
assert all(type(item) == clazz for item in lst), lst |
|
|
|
logic = clazz.mergeMap |
|
returnTable = clazz() |
|
returnDict = {} |
|
|
|
allKeys = set.union(set(), *(vars(table).keys() for table in lst)) |
|
for key in allKeys: |
|
try: |
|
mergeLogic = logic[key] |
|
except KeyError: |
|
try: |
|
mergeLogic = logic["*"] |
|
except KeyError: |
|
raise Exception( |
|
"Don't know how to merge key %s of class %s" % (key, clazz.__name__) |
|
) |
|
if mergeLogic is NotImplemented: |
|
continue |
|
value = mergeLogic(getattr(table, key, NotImplemented) for table in lst) |
|
if value is not NotImplemented: |
|
returnDict[key] = value |
|
|
|
returnTable.__dict__ = returnDict |
|
|
|
return returnTable |
|
|
|
|
|
@add_method(DefaultTable, allowDefaultTable=True) |
|
def merge(self, m, tables): |
|
if not hasattr(self, "mergeMap"): |
|
log.info("Don't know how to merge '%s'.", self.tableTag) |
|
return NotImplemented |
|
|
|
logic = self.mergeMap |
|
|
|
if isinstance(logic, dict): |
|
return m.mergeObjects(self, self.mergeMap, tables) |
|
else: |
|
return logic(tables) |
|
|