prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  hmtx code should round values
  Currently, float values result in exception:
  
  ```
      self._writeTable(masterTable, writer, done)
    File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 648, in _writeTable
      tabledata = self.getTableData(tag)
    File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 659, in getTableData
      return self.tables[tag].compile(self)
    File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/tables/_h_m_t_x.py", line 68, in compile
      allMetrics = array.array("h", allMetrics)
  TypeError: integer argument expected, got float
  ```
  
  Possibly warn?  Though it will become annoying if we do.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `Lib/fontTools/ttLib/tables/_h_m_t_x.py`
  Content:
  ```
  1 from __future__ import print_function, division, absolute_import
  2 from fontTools.misc.py23 import *
  3 from fontTools import ttLib
  4 from fontTools.misc.textTools import safeEval
  5 from . import DefaultTable
  6 import sys
  7 import struct
  8 import array
  9 import logging
  10 
  11 
  12 log = logging.getLogger(__name__)
  13 
  14 
  15 class table__h_m_t_x(DefaultTable.DefaultTable):
  16 
  17 	headerTag = 'hhea'
  18 	advanceName = 'width'
  19 	sideBearingName = 'lsb'
  20 	numberOfMetricsName = 'numberOfHMetrics'
  21 	longMetricFormat = 'Hh'
  22 
  23 	def decompile(self, data, ttFont):
  24 		numGlyphs = ttFont['maxp'].numGlyphs
  25 		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
  26 		if numberOfMetrics > numGlyphs:
  27 			log.warning("The %s.%s exceeds the maxp.numGlyphs" % (
  28 				self.headerTag, self.numberOfMetricsName))
  29 			numberOfMetrics = numGlyphs
  30 		if len(data) < 4 * numberOfMetrics:
  31 			raise ttLib.TTLibError("not enough '%s' table data" % self.tableTag)
  32 		# Note: advanceWidth is unsigned, but some font editors might
  33 		# read/write as signed. We can't be sure whether it was a mistake
  34 		# or not, so we read as unsigned but also issue a warning...
  35 		metricsFmt = ">" + self.longMetricFormat * numberOfMetrics
  36 		metrics = struct.unpack(metricsFmt, data[:4 * numberOfMetrics])
  37 		data = data[4 * numberOfMetrics:]
  38 		numberOfSideBearings = numGlyphs - numberOfMetrics
  39 		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
  40 		data = data[2 * numberOfSideBearings:]
  41 
  42 		if sys.byteorder != "big":
  43 			sideBearings.byteswap()
  44 		if data:
  45 			log.warning("too much '%s' table data" % self.tableTag)
  46 		self.metrics = {}
  47 		glyphOrder = ttFont.getGlyphOrder()
  48 		for i in range(numberOfMetrics):
  49 			glyphName = glyphOrder[i]
  50 			advanceWidth, lsb = metrics[i*2:i*2+2]
  51 			if advanceWidth > 32767:
  52 				log.warning(
  53 					"Glyph %r has a huge advance %s (%d); is it intentional or "
  54 					"an (invalid) negative value?", glyphName, self.advanceName,
  55 					advanceWidth)
  56 			self.metrics[glyphName] = (advanceWidth, lsb)
  57 		lastAdvance = metrics[-2]
  58 		for i in range(numberOfSideBearings):
  59 			glyphName = glyphOrder[i + numberOfMetrics]
  60 			self.metrics[glyphName] = (lastAdvance, sideBearings[i])
  61 
  62 	def compile(self, ttFont):
  63 		metrics = []
  64 		hasNegativeAdvances = False
  65 		for glyphName in ttFont.getGlyphOrder():
  66 			advanceWidth, sideBearing = self.metrics[glyphName]
  67 			if advanceWidth < 0:
  68 				log.error("Glyph %r has negative advance %s" % (
  69 					glyphName, self.advanceName))
  70 				hasNegativeAdvances = True
  71 			metrics.append([advanceWidth, sideBearing])
  72 		lastAdvance = metrics[-1][0]
  73 		lastIndex = len(metrics)
  74 		while metrics[lastIndex-2][0] == lastAdvance:
  75 			lastIndex -= 1
  76 			if lastIndex <= 1:
  77 				# all advances are equal
  78 				lastIndex = 1
  79 				break
  80 		additionalMetrics = metrics[lastIndex:]
  81 		additionalMetrics = [sb for advance, sb in additionalMetrics]
  82 		metrics = metrics[:lastIndex]
  83 		numberOfMetrics = len(metrics)
  84 		setattr(ttFont[self.headerTag], self.numberOfMetricsName, numberOfMetrics)
  85 
  86 		allMetrics = []
  87 		for item in metrics:
  88 			allMetrics.extend(item)
  89 		metricsFmt = ">" + self.longMetricFormat * numberOfMetrics
  90 		try:
  91 			data = struct.pack(metricsFmt, *allMetrics)
  92 		except struct.error as e:
  93 			if "out of range" in str(e) and hasNegativeAdvances:
  94 				raise ttLib.TTLibError(
  95 					"'%s' table can't contain negative advance %ss"
  96 					% (self.tableTag, self.advanceName))
  97 			else:
  98 				raise
  99 		additionalMetrics = array.array("h", additionalMetrics)
  100 		if sys.byteorder != "big":
  101 			additionalMetrics.byteswap()
  102 		data = data + additionalMetrics.tostring()
  103 		return data
  104 
  105 	def toXML(self, writer, ttFont):
  106 		names = sorted(self.metrics.keys())
  107 		for glyphName in names:
  108 			advance, sb = self.metrics[glyphName]
  109 			writer.simpletag("mtx", [
  110 					("name", glyphName),
  111 					(self.advanceName, advance),
  112 					(self.sideBearingName, sb),
  113 					])
  114 			writer.newline()
  115 
  116 	def fromXML(self, name, attrs, content, ttFont):
  117 		if not hasattr(self, "metrics"):
  118 			self.metrics = {}
  119 		if name == "mtx":
  120 			self.metrics[attrs["name"]] = (safeEval(attrs[self.advanceName]),
  121 					safeEval(attrs[self.sideBearingName]))
  122 
  123 	def __delitem__(self, glyphName):
  124 		del self.metrics[glyphName]
  125 
  126 	def __getitem__(self, glyphName):
  127 		return self.metrics[glyphName]
  128 
  129 	def __setitem__(self, glyphName, advance_sb_pair):
  130 		self.metrics[glyphName] = tuple(advance_sb_pair)
  131
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
  --- a/Lib/fontTools/ttLib/tables/_h_m_t_x.py
  +++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py
  @@ -78,14 +78,14 @@
   				lastIndex = 1
   				break
   		additionalMetrics = metrics[lastIndex:]
  -		additionalMetrics = [sb for advance, sb in additionalMetrics]
  +		additionalMetrics = [int(round(sb)) for _, sb in additionalMetrics]
   		metrics = metrics[:lastIndex]
   		numberOfMetrics = len(metrics)
   		setattr(ttFont[self.headerTag], self.numberOfMetricsName, numberOfMetrics)
   
   		allMetrics = []
  -		for item in metrics:
  -			allMetrics.extend(item)
  +		for advance, sb in metrics:
  +			allMetrics.extend([int(round(advance)), int(round(sb))])
   		metricsFmt = ">" + self.longMetricFormat * numberOfMetrics
   		try:
   			data = struct.pack(metricsFmt, *allMetrics)
  
verification_info: {"golden_diff": "diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py\n--- a/Lib/fontTools/ttLib/tables/_h_m_t_x.py\n+++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py\n@@ -78,14 +78,14 @@\n \t\t\t\tlastIndex = 1\n \t\t\t\tbreak\n \t\tadditionalMetrics = metrics[lastIndex:]\n-\t\tadditionalMetrics = [sb for advance, sb in additionalMetrics]\n+\t\tadditionalMetrics = [int(round(sb)) for _, sb in additionalMetrics]\n \t\tmetrics = metrics[:lastIndex]\n \t\tnumberOfMetrics = len(metrics)\n \t\tsetattr(ttFont[self.headerTag], self.numberOfMetricsName, numberOfMetrics)\n \n \t\tallMetrics = []\n-\t\tfor item in metrics:\n-\t\t\tallMetrics.extend(item)\n+\t\tfor advance, sb in metrics:\n+\t\t\tallMetrics.extend([int(round(advance)), int(round(sb))])\n \t\tmetricsFmt = \">\" + self.longMetricFormat * numberOfMetrics\n \t\ttry:\n \t\t\tdata = struct.pack(metricsFmt, *allMetrics)\n", "issue": "hmtx code should round values\nCurrently, float values result in exception:\n\n```\n    self._writeTable(masterTable, writer, done)\n  File \"/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py\", line 648, in _writeTable\n    tabledata = self.getTableData(tag)\n  File \"/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py\", line 659, in getTableData\n    return self.tables[tag].compile(self)\n  File \"/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/tables/_h_m_t_x.py\", line 68, in compile\n    allMetrics = array.array(\"h\", allMetrics)\nTypeError: integer argument expected, got float\n```\n\nPossibly warn?  Though it will become annoying if we do.\n\n", "before_files": [{"content": "from __future__ import print_function, division, absolute_import\nfrom fontTools.misc.py23 import *\nfrom fontTools import ttLib\nfrom fontTools.misc.textTools import safeEval\nfrom . import DefaultTable\nimport sys\nimport struct\nimport array\nimport logging\n\n\nlog = logging.getLogger(__name__)\n\n\nclass table__h_m_t_x(DefaultTable.DefaultTable):\n\n\theaderTag = 'hhea'\n\tadvanceName = 'width'\n\tsideBearingName = 'lsb'\n\tnumberOfMetricsName = 'numberOfHMetrics'\n\tlongMetricFormat = 'Hh'\n\n\tdef decompile(self, data, ttFont):\n\t\tnumGlyphs = ttFont['maxp'].numGlyphs\n\t\tnumberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))\n\t\tif numberOfMetrics > numGlyphs:\n\t\t\tlog.warning(\"The %s.%s exceeds the maxp.numGlyphs\" % (\n\t\t\t\tself.headerTag, self.numberOfMetricsName))\n\t\t\tnumberOfMetrics = numGlyphs\n\t\tif len(data) < 4 * numberOfMetrics:\n\t\t\traise ttLib.TTLibError(\"not enough '%s' table data\" % self.tableTag)\n\t\t# Note: advanceWidth is unsigned, but some font editors might\n\t\t# read/write as signed. We can't be sure whether it was a mistake\n\t\t# or not, so we read as unsigned but also issue a warning...\n\t\tmetricsFmt = \">\" + self.longMetricFormat * numberOfMetrics\n\t\tmetrics = struct.unpack(metricsFmt, data[:4 * numberOfMetrics])\n\t\tdata = data[4 * numberOfMetrics:]\n\t\tnumberOfSideBearings = numGlyphs - numberOfMetrics\n\t\tsideBearings = array.array(\"h\", data[:2 * numberOfSideBearings])\n\t\tdata = data[2 * numberOfSideBearings:]\n\n\t\tif sys.byteorder != \"big\":\n\t\t\tsideBearings.byteswap()\n\t\tif data:\n\t\t\tlog.warning(\"too much '%s' table data\" % self.tableTag)\n\t\tself.metrics = {}\n\t\tglyphOrder = ttFont.getGlyphOrder()\n\t\tfor i in range(numberOfMetrics):\n\t\t\tglyphName = glyphOrder[i]\n\t\t\tadvanceWidth, lsb = metrics[i*2:i*2+2]\n\t\t\tif advanceWidth > 32767:\n\t\t\t\tlog.warning(\n\t\t\t\t\t\"Glyph %r has a huge advance %s (%d); is it intentional or \"\n\t\t\t\t\t\"an (invalid) negative value?\", glyphName, self.advanceName,\n\t\t\t\t\tadvanceWidth)\n\t\t\tself.metrics[glyphName] = (advanceWidth, lsb)\n\t\tlastAdvance = metrics[-2]\n\t\tfor i in range(numberOfSideBearings):\n\t\t\tglyphName = glyphOrder[i + numberOfMetrics]\n\t\t\tself.metrics[glyphName] = (lastAdvance, sideBearings[i])\n\n\tdef compile(self, ttFont):\n\t\tmetrics = []\n\t\thasNegativeAdvances = False\n\t\tfor glyphName in ttFont.getGlyphOrder():\n\t\t\tadvanceWidth, sideBearing = self.metrics[glyphName]\n\t\t\tif advanceWidth < 0:\n\t\t\t\tlog.error(\"Glyph %r has negative advance %s\" % (\n\t\t\t\t\tglyphName, self.advanceName))\n\t\t\t\thasNegativeAdvances = True\n\t\t\tmetrics.append([advanceWidth, sideBearing])\n\t\tlastAdvance = metrics[-1][0]\n\t\tlastIndex = len(metrics)\n\t\twhile metrics[lastIndex-2][0] == lastAdvance:\n\t\t\tlastIndex -= 1\n\t\t\tif lastIndex <= 1:\n\t\t\t\t# all advances are equal\n\t\t\t\tlastIndex = 1\n\t\t\t\tbreak\n\t\tadditionalMetrics = metrics[lastIndex:]\n\t\tadditionalMetrics = [sb for advance, sb in additionalMetrics]\n\t\tmetrics = metrics[:lastIndex]\n\t\tnumberOfMetrics = len(metrics)\n\t\tsetattr(ttFont[self.headerTag], self.numberOfMetricsName, numberOfMetrics)\n\n\t\tallMetrics = []\n\t\tfor item in metrics:\n\t\t\tallMetrics.extend(item)\n\t\tmetricsFmt = \">\" + self.longMetricFormat * numberOfMetrics\n\t\ttry:\n\t\t\tdata = struct.pack(metricsFmt, *allMetrics)\n\t\texcept struct.error as e:\n\t\t\tif \"out of range\" in str(e) and hasNegativeAdvances:\n\t\t\t\traise ttLib.TTLibError(\n\t\t\t\t\t\"'%s' table can't contain negative advance %ss\"\n\t\t\t\t\t% (self.tableTag, self.advanceName))\n\t\t\telse:\n\t\t\t\traise\n\t\tadditionalMetrics = array.array(\"h\", additionalMetrics)\n\t\tif sys.byteorder != \"big\":\n\t\t\tadditionalMetrics.byteswap()\n\t\tdata = data + additionalMetrics.tostring()\n\t\treturn data\n\n\tdef toXML(self, writer, ttFont):\n\t\tnames = sorted(self.metrics.keys())\n\t\tfor glyphName in names:\n\t\t\tadvance, sb = self.metrics[glyphName]\n\t\t\twriter.simpletag(\"mtx\", [\n\t\t\t\t\t(\"name\", glyphName),\n\t\t\t\t\t(self.advanceName, advance),\n\t\t\t\t\t(self.sideBearingName, sb),\n\t\t\t\t\t])\n\t\t\twriter.newline()\n\n\tdef fromXML(self, name, attrs, content, ttFont):\n\t\tif not hasattr(self, \"metrics\"):\n\t\t\tself.metrics = {}\n\t\tif name == \"mtx\":\n\t\t\tself.metrics[attrs[\"name\"]] = (safeEval(attrs[self.advanceName]),\n\t\t\t\t\tsafeEval(attrs[self.sideBearingName]))\n\n\tdef __delitem__(self, glyphName):\n\t\tdel self.metrics[glyphName]\n\n\tdef __getitem__(self, glyphName):\n\t\treturn self.metrics[glyphName]\n\n\tdef __setitem__(self, glyphName, advance_sb_pair):\n\t\tself.metrics[glyphName] = tuple(advance_sb_pair)\n", "path": "Lib/fontTools/ttLib/tables/_h_m_t_x.py"}], "after_files": [{"content": "from __future__ import print_function, division, absolute_import\nfrom fontTools.misc.py23 import *\nfrom fontTools import ttLib\nfrom fontTools.misc.textTools import safeEval\nfrom . import DefaultTable\nimport sys\nimport struct\nimport array\nimport logging\n\n\nlog = logging.getLogger(__name__)\n\n\nclass table__h_m_t_x(DefaultTable.DefaultTable):\n\n\theaderTag = 'hhea'\n\tadvanceName = 'width'\n\tsideBearingName = 'lsb'\n\tnumberOfMetricsName = 'numberOfHMetrics'\n\tlongMetricFormat = 'Hh'\n\n\tdef decompile(self, data, ttFont):\n\t\tnumGlyphs = ttFont['maxp'].numGlyphs\n\t\tnumberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))\n\t\tif numberOfMetrics > numGlyphs:\n\t\t\tlog.warning(\"The %s.%s exceeds the maxp.numGlyphs\" % (\n\t\t\t\tself.headerTag, self.numberOfMetricsName))\n\t\t\tnumberOfMetrics = numGlyphs\n\t\tif len(data) < 4 * numberOfMetrics:\n\t\t\traise ttLib.TTLibError(\"not enough '%s' table data\" % self.tableTag)\n\t\t# Note: advanceWidth is unsigned, but some font editors might\n\t\t# read/write as signed. We can't be sure whether it was a mistake\n\t\t# or not, so we read as unsigned but also issue a warning...\n\t\tmetricsFmt = \">\" + self.longMetricFormat * numberOfMetrics\n\t\tmetrics = struct.unpack(metricsFmt, data[:4 * numberOfMetrics])\n\t\tdata = data[4 * numberOfMetrics:]\n\t\tnumberOfSideBearings = numGlyphs - numberOfMetrics\n\t\tsideBearings = array.array(\"h\", data[:2 * numberOfSideBearings])\n\t\tdata = data[2 * numberOfSideBearings:]\n\n\t\tif sys.byteorder != \"big\":\n\t\t\tsideBearings.byteswap()\n\t\tif data:\n\t\t\tlog.warning(\"too much '%s' table data\" % self.tableTag)\n\t\tself.metrics = {}\n\t\tglyphOrder = ttFont.getGlyphOrder()\n\t\tfor i in range(numberOfMetrics):\n\t\t\tglyphName = glyphOrder[i]\n\t\t\tadvanceWidth, lsb = metrics[i*2:i*2+2]\n\t\t\tif advanceWidth > 32767:\n\t\t\t\tlog.warning(\n\t\t\t\t\t\"Glyph %r has a huge advance %s (%d); is it intentional or \"\n\t\t\t\t\t\"an (invalid) negative value?\", glyphName, self.advanceName,\n\t\t\t\t\tadvanceWidth)\n\t\t\tself.metrics[glyphName] = (advanceWidth, lsb)\n\t\tlastAdvance = metrics[-2]\n\t\tfor i in range(numberOfSideBearings):\n\t\t\tglyphName = glyphOrder[i + numberOfMetrics]\n\t\t\tself.metrics[glyphName] = (lastAdvance, sideBearings[i])\n\n\tdef compile(self, ttFont):\n\t\tmetrics = []\n\t\thasNegativeAdvances = False\n\t\tfor glyphName in ttFont.getGlyphOrder():\n\t\t\tadvanceWidth, sideBearing = self.metrics[glyphName]\n\t\t\tif advanceWidth < 0:\n\t\t\t\tlog.error(\"Glyph %r has negative advance %s\" % (\n\t\t\t\t\tglyphName, self.advanceName))\n\t\t\t\thasNegativeAdvances = True\n\t\t\tmetrics.append([advanceWidth, sideBearing])\n\t\tlastAdvance = metrics[-1][0]\n\t\tlastIndex = len(metrics)\n\t\twhile metrics[lastIndex-2][0] == lastAdvance:\n\t\t\tlastIndex -= 1\n\t\t\tif lastIndex <= 1:\n\t\t\t\t# all advances are equal\n\t\t\t\tlastIndex = 1\n\t\t\t\tbreak\n\t\tadditionalMetrics = metrics[lastIndex:]\n\t\tadditionalMetrics = [int(round(sb)) for _, sb in additionalMetrics]\n\t\tmetrics = metrics[:lastIndex]\n\t\tnumberOfMetrics = len(metrics)\n\t\tsetattr(ttFont[self.headerTag], self.numberOfMetricsName, numberOfMetrics)\n\n\t\tallMetrics = []\n\t\tfor advance, sb in metrics:\n\t\t\tallMetrics.extend([int(round(advance)), int(round(sb))])\n\t\tmetricsFmt = \">\" + self.longMetricFormat * numberOfMetrics\n\t\ttry:\n\t\t\tdata = struct.pack(metricsFmt, *allMetrics)\n\t\texcept struct.error as e:\n\t\t\tif \"out of range\" in str(e) and hasNegativeAdvances:\n\t\t\t\traise ttLib.TTLibError(\n\t\t\t\t\t\"'%s' table can't contain negative advance %ss\"\n\t\t\t\t\t% (self.tableTag, self.advanceName))\n\t\t\telse:\n\t\t\t\traise\n\t\tadditionalMetrics = array.array(\"h\", additionalMetrics)\n\t\tif sys.byteorder != \"big\":\n\t\t\tadditionalMetrics.byteswap()\n\t\tdata = data + additionalMetrics.tostring()\n\t\treturn data\n\n\tdef toXML(self, writer, ttFont):\n\t\tnames = sorted(self.metrics.keys())\n\t\tfor glyphName in names:\n\t\t\tadvance, sb = self.metrics[glyphName]\n\t\t\twriter.simpletag(\"mtx\", [\n\t\t\t\t\t(\"name\", glyphName),\n\t\t\t\t\t(self.advanceName, advance),\n\t\t\t\t\t(self.sideBearingName, sb),\n\t\t\t\t\t])\n\t\t\twriter.newline()\n\n\tdef fromXML(self, name, attrs, content, ttFont):\n\t\tif not hasattr(self, \"metrics\"):\n\t\t\tself.metrics = {}\n\t\tif name == \"mtx\":\n\t\t\tself.metrics[attrs[\"name\"]] = (safeEval(attrs[self.advanceName]),\n\t\t\t\t\tsafeEval(attrs[self.sideBearingName]))\n\n\tdef __delitem__(self, glyphName):\n\t\tdel self.metrics[glyphName]\n\n\tdef __getitem__(self, glyphName):\n\t\treturn self.metrics[glyphName]\n\n\tdef __setitem__(self, glyphName, advance_sb_pair):\n\t\tself.metrics[glyphName] = tuple(advance_sb_pair)\n", "path": "Lib/fontTools/ttLib/tables/_h_m_t_x.py"}]}