[merge] Use NotImplemented as a singleton meaning "doesn't have"

And cleanup recalculate, so we don't accidentally mess something
that is NOT recalculated.
diff --git a/Lib/fontTools/merge.py b/Lib/fontTools/merge.py
index 21c49ad..5e4da52 100644
--- a/Lib/fontTools/merge.py
+++ b/Lib/fontTools/merge.py
@@ -31,6 +31,7 @@
 	return wrapper
 
 # General utility functions for merging values from different fonts
+
 def equal(lst):
 	t = iter(lst)
 	first = next(t)
@@ -41,8 +42,7 @@
 	return next(iter(lst))
 
 def recalculate(lst):
-	# Just return the first value, assume will be recalculated when saved
-	return first(lst)
+	return NotImplemented
 
 def current_time(lst):
 	return int(time.time() - _h_e_a_d.mac_epoch_diff)
@@ -50,14 +50,15 @@
 def bitwise_or(lst):
 	return reduce(operator.or_, lst)
 
-def ignore(lst):
-	assert False, "This function should not be called."
+def avg_int(lst):
+	lst = list(lst)
+	return sum(lst) // len(lst)
 
-def maybenone(func):
+def nonnone(func):
 	"""Returns a filter func that when called with a list,
 	only calls func on the non-None items of the list, and
 	only so if there's at least one non-None item in the
-	list."""
+	list.  Otherwise returns None."""
 
 	def wrapper(lst):
 		items = [item for item in lst if item is not None]
@@ -65,6 +66,18 @@
 
 	return wrapper
 
+def implemented(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:
@@ -82,10 +95,9 @@
 def merge(self, m, tables):
 	if not hasattr(self, 'mergeMap'):
 		m.log("Don't know how to merge '%s'." % self.tableTag)
-		return False
+		return NotImplemented
 
-	m.mergeObjects(self, self.mergeMap, tables)
-	return True
+	return m.mergeObjects(self, self.mergeMap, tables)
 
 ttLib.getTableClass('maxp').mergeMap = {
 	'*': max,
@@ -103,7 +115,7 @@
 	'tableTag': equal,
 	'tableVersion': max,
 	'fontRevision': max,
-	'checkSumAdjustment': recalculate,
+	'checkSumAdjustment': lambda lst: 0, # We need *something* here
 	'magicNumber': equal,
 	'flags': first, # FIXME: replace with bit-sensitive code
 	'unitsPerEm': equal,
@@ -141,7 +153,7 @@
 	'*': first,
 	'tableTag': equal,
 	'version': max,
-	'xAvgCharWidth': recalculate,
+	'xAvgCharWidth': avg_int, # Apparently fontTools doesn't recalc this
 	'fsType': first, # FIXME
 	'panose': first, # FIXME?
 	'ulUnicodeRange1': bitwise_or,
@@ -170,18 +182,9 @@
 	'maxMemType42': lambda lst: 0,
 	'minMemType1': max,
 	'maxMemType1': lambda lst: 0,
-	'mapping': ignore,
-	'extraNames': ignore,
+	'mapping': implemented(sumDicts),
+	'extraNames': lambda lst: [][:],
 }
-@_add_method(ttLib.getTableClass('post'))
-def merge(self, m, tables):
-	DefaultTable.merge(self, m, tables)
-	self.mapping = {}
-	for table in tables:
-		if hasattr(table, 'mapping'):
-			self.mapping.update(table.mapping)
-	self.extraNames = []
-	return True
 
 ttLib.getTableClass('vmtx').mergeMap = ttLib.getTableClass('hmtx').mergeMap = {
 	'tableTag': equal,
@@ -189,7 +192,7 @@
 }
 
 ttLib.getTableClass('loca').mergeMap = {
-	'*': ignore,
+	'*': recalculate,
 	'tableTag': equal,
 }
 
@@ -210,14 +213,11 @@
 			# composite glyph names.
 			if g.isComposite():
 				g.expand(table)
-	DefaultTable.merge(self, m, tables)
-	return True
+	return DefaultTable.merge(self, m, tables)
 
-@_add_method(ttLib.getTableClass('prep'),
-	     ttLib.getTableClass('fpgm'),
-	     ttLib.getTableClass('cvt '))
-def merge(self, m):
-	return False # TODO We don't merge hinting data currently.
+ttLib.getTableClass('prep').mergeMap = NotImplemented
+ttLib.getTableClass('fpgm').mergeMap = NotImplemented
+ttLib.getTableClass('cvt ').mergeMap = NotImplemented
 
 @_add_method(ttLib.getTableClass('cmap'))
 def merge(self, m, tables):
@@ -240,7 +240,7 @@
 	self.tableVersion = 0
 	self.tables = [cmapTable]
 	self.numSubTables = len(self.tables)
-	return True
+	return self
 
 @_add_method(ttLib.getTableClass('GDEF'))
 def merge(self, m, tables):
@@ -301,7 +301,7 @@
 	else:
 		self.table.AttachList = None
 
-	return True
+	return self
 
 
 class Options(object):
@@ -309,9 +309,6 @@
   class UnknownOptionError(Exception):
     pass
 
-  _drop_tables_default = ['fpgm', 'prep', 'cvt ', 'gasp']
-  drop_tables = _drop_tables_default
-
   def __init__(self, **kwargs):
 
     self.set(**kwargs)
@@ -417,16 +414,11 @@
 		allTags.remove('GlyphOrder')
 		for tag in allTags:
 
-			if tag in self.options.drop_tables:
-				self.log("Dropping '%s'." % tag)
-				continue
-
 			clazz = ttLib.getTableClass(tag)
 
-			# TODO For now assume all fonts have the same tables.
-			tables = [font[tag] for font in fonts]
-			table = clazz(tag)
-			if table.merge (self, tables):
+			tables = [font[tag] if font.has_key(tag) else NotImplemented for font in fonts]
+			table = clazz(tag).merge(self, tables)
+			if table is not NotImplemented and table is not False:
 				mega[tag] = table
 				self.log("Merged '%s'." % tag)
 			else:
@@ -450,7 +442,13 @@
 		return mega
 
 	def mergeObjects(self, returnTable, logic, tables):
-		allKeys = set.union(set(), *(vars(table).keys() for table in tables))
+		# Right now we don't use self at all.  Will use in the future
+		# for options and logging.
+
+		if logic is NotImplemented:
+			return NotImplemented
+
+		allKeys = set.union(set(), *(vars(table).keys() for table in tables if table is not NotImplemented))
 		for key in allKeys:
 			try:
 				mergeLogic = logic[key]
@@ -460,10 +458,13 @@
 				except KeyError:
 					raise Exception("Don't know how to merge key %s of class %s" % 
 							(key, returnTable.__class__.__name__))
-			if mergeLogic == ignore:
+			if mergeLogic is NotImplemented:
 				continue
-			key_value = mergeLogic(getattr(table, key) for table in tables)
-			setattr(returnTable, key, key_value)
+			value = mergeLogic(getattr(table, key, NotImplemented) for table in tables)
+			if value is not NotImplemented:
+				setattr(returnTable, key, value)
+
+		return returnTable
 
 
 class Logger(object):