|
|
|
|
|
|
|
|
|
from fontTools.misc.timeTools import timestampNow |
|
from fontTools.ttLib.tables.DefaultTable import DefaultTable |
|
from functools import reduce |
|
import operator |
|
import logging |
|
|
|
|
|
log = logging.getLogger("fontTools.merge") |
|
|
|
|
|
|
|
|
|
|
|
def equal(lst): |
|
lst = list(lst) |
|
t = iter(lst) |
|
first = next(t) |
|
assert all(item == first for item in t), "Expected all items to be equal: %s" % lst |
|
return first |
|
|
|
|
|
def first(lst): |
|
return next(iter(lst)) |
|
|
|
|
|
def recalculate(lst): |
|
return NotImplemented |
|
|
|
|
|
def current_time(lst): |
|
return timestampNow() |
|
|
|
|
|
def bitwise_and(lst): |
|
return reduce(operator.and_, lst) |
|
|
|
|
|
def bitwise_or(lst): |
|
return reduce(operator.or_, lst) |
|
|
|
|
|
def avg_int(lst): |
|
lst = list(lst) |
|
return sum(lst) // len(lst) |
|
|
|
|
|
def onlyExisting(func): |
|
"""Returns a filter func that when called with a list, |
|
only calls func on the non-NotImplemented items of the list, |
|
and only so if there's at least one item remaining. |
|
Otherwise returns NotImplemented.""" |
|
|
|
def wrapper(lst): |
|
items = [item for item in lst if item is not NotImplemented] |
|
return func(items) if items else NotImplemented |
|
|
|
return wrapper |
|
|
|
|
|
def sumLists(lst): |
|
l = [] |
|
for item in lst: |
|
l.extend(item) |
|
return l |
|
|
|
|
|
def sumDicts(lst): |
|
d = {} |
|
for item in lst: |
|
d.update(item) |
|
return d |
|
|
|
|
|
def mergeBits(bitmap): |
|
def wrapper(lst): |
|
lst = list(lst) |
|
returnValue = 0 |
|
for bitNumber in range(bitmap["size"]): |
|
try: |
|
mergeLogic = bitmap[bitNumber] |
|
except KeyError: |
|
try: |
|
mergeLogic = bitmap["*"] |
|
except KeyError: |
|
raise Exception("Don't know how to merge bit %s" % bitNumber) |
|
shiftedBit = 1 << bitNumber |
|
mergedValue = mergeLogic(bool(item & shiftedBit) for item in lst) |
|
returnValue |= mergedValue << bitNumber |
|
return returnValue |
|
|
|
return wrapper |
|
|
|
|
|
class AttendanceRecordingIdentityDict(object): |
|
"""A dictionary-like object that records indices of items actually accessed |
|
from a list.""" |
|
|
|
def __init__(self, lst): |
|
self.l = lst |
|
self.d = {id(v): i for i, v in enumerate(lst)} |
|
self.s = set() |
|
|
|
def __getitem__(self, v): |
|
self.s.add(self.d[id(v)]) |
|
return v |
|
|
|
|
|
class GregariousIdentityDict(object): |
|
"""A dictionary-like object that welcomes guests without reservations and |
|
adds them to the end of the guest list.""" |
|
|
|
def __init__(self, lst): |
|
self.l = lst |
|
self.s = set(id(v) for v in lst) |
|
|
|
def __getitem__(self, v): |
|
if id(v) not in self.s: |
|
self.s.add(id(v)) |
|
self.l.append(v) |
|
return v |
|
|
|
|
|
class NonhashableDict(object): |
|
"""A dictionary-like object mapping objects to values.""" |
|
|
|
def __init__(self, keys, values=None): |
|
if values is None: |
|
self.d = {id(v): i for i, v in enumerate(keys)} |
|
else: |
|
self.d = {id(k): v for k, v in zip(keys, values)} |
|
|
|
def __getitem__(self, k): |
|
return self.d[id(k)] |
|
|
|
def __setitem__(self, k, v): |
|
self.d[id(k)] = v |
|
|
|
def __delitem__(self, k): |
|
del self.d[id(k)] |
|
|