from __future__ import absolute_import, unicode_literals
import sys
import os
from copy import deepcopy
import logging
import zipfile
import enum
from collections import OrderedDict
import fs
import fs.base
import fs.subfs
import fs.errors
import fs.copy
import fs.osfs
import fs.zipfs
import fs.tempfs
import fs.tools
from fontTools.misc.py23 import basestring, unicode, tounicode
from fontTools.misc import plistlib
from fontTools.ufoLib.validators import *
from fontTools.ufoLib.filenames import userNameToFileName
from fontTools.ufoLib.converters import convertUFO1OrUFO2KerningToUFO3Kerning
from fontTools.ufoLib.errors import UFOLibError
from fontTools.ufoLib.utils import datetimeAsTimestamp, fsdecode, numberTypes

"""
A library for importing .ufo files and their descendants.
Refer to http://unifiedfontobject.com for the UFO specification.

The UFOReader and UFOWriter classes support versions 1, 2 and 3
of the specification.

Sets that list the font info attribute names for the fontinfo.plist
formats are available for external use. These are:
	fontInfoAttributesVersion1
	fontInfoAttributesVersion2
	fontInfoAttributesVersion3

A set listing the fontinfo.plist attributes that were deprecated
in version 2 is available for external use:
	deprecatedFontInfoAttributesVersion2

Functions that do basic validation on values for fontinfo.plist
are available for external use. These are
	validateFontInfoVersion2ValueForAttribute
	validateFontInfoVersion3ValueForAttribute

Value conversion functions are available for converting
fontinfo.plist values between the possible format versions.
	convertFontInfoValueForAttributeFromVersion1ToVersion2
	convertFontInfoValueForAttributeFromVersion2ToVersion1
	convertFontInfoValueForAttributeFromVersion2ToVersion3
	convertFontInfoValueForAttributeFromVersion3ToVersion2
"""

__all__ = [
	"makeUFOPath",
	"UFOLibError",
	"UFOReader",
	"UFOWriter",
	"UFOReaderWriter",
	"UFOFileStructure",
	"fontInfoAttributesVersion1",
	"fontInfoAttributesVersion2",
	"fontInfoAttributesVersion3",
	"deprecatedFontInfoAttributesVersion2",
	"validateFontInfoVersion2ValueForAttribute",
	"validateFontInfoVersion3ValueForAttribute",
	"convertFontInfoValueForAttributeFromVersion1ToVersion2",
	"convertFontInfoValueForAttributeFromVersion2ToVersion1"
]

__version__ = "3.0.0"


logger = logging.getLogger(__name__)


# ---------
# Constants
# ---------

DEFAULT_GLYPHS_DIRNAME = "glyphs"
DATA_DIRNAME = "data"
IMAGES_DIRNAME = "images"
METAINFO_FILENAME = "metainfo.plist"
FONTINFO_FILENAME = "fontinfo.plist"
LIB_FILENAME = "lib.plist"
GROUPS_FILENAME = "groups.plist"
KERNING_FILENAME = "kerning.plist"
FEATURES_FILENAME = "features.fea"
LAYERCONTENTS_FILENAME = "layercontents.plist"
LAYERINFO_FILENAME = "layerinfo.plist"

DEFAULT_LAYER_NAME = "public.default"

supportedUFOFormatVersions = [1, 2, 3]


class UFOFileStructure(enum.Enum):
	ZIP = "zip"
	PACKAGE = "package"


# --------------
# Shared Methods
# --------------


class _UFOBaseIO(object):

	def getFileModificationTime(self, path):
		"""
		Returns the modification time for the file at the given path, as a
		floating point number giving the number of seconds since the epoch.
		The path must be relative to the UFO path.
		Returns None if the file does not exist.
		"""
		try:
			dt = self.fs.getinfo(fsdecode(path), namespaces=["details"]).modified
		except (fs.errors.MissingInfoNamespace, fs.errors.ResourceNotFound):
			return None
		else:
			return datetimeAsTimestamp(dt)

	def _getPlist(self, fileName, default=None):
		"""
		Read a property list relative to the UFO filesystem's root.
		Raises UFOLibError if the file is missing and default is None,
		otherwise default is returned.

		The errors that could be raised during the reading of a plist are
		unpredictable and/or too large to list, so, a blind try: except:
		is done. If an exception occurs, a UFOLibError will be raised.
		"""
		try:
			with self.fs.open(fileName, "rb") as f:
				return plistlib.load(f)
		except fs.errors.ResourceNotFound:
			if default is None:
				raise UFOLibError(
					"'%s' is missing on %s. This file is required"
					% (fileName, self.fs)
				)
			else:
				return default
		except Exception as e:
			# TODO(anthrotype): try to narrow this down a little
			raise UFOLibError(
				"'%s' could not be read on %s: %s" % (fileName, self.fs, e)
			)

	def _writePlist(self, fileName, obj):
		"""
		Write a property list to a file relative to the UFO filesystem's root.

		Do this sort of atomically, making it harder to corrupt existing files,
		for example when plistlib encounters an error halfway during write.
		This also checks to see if text matches the text that is already in the
		file at path. If so, the file is not rewritten so that the modification
		date is preserved.

		The errors that could be raised during the writing of a plist are
		unpredictable and/or too large to list, so, a blind try: except: is done.
		If an exception occurs, a UFOLibError will be raised.
		"""
		if self._havePreviousFile:
			try:
				data = plistlib.dumps(obj)
			except Exception as e:
				raise UFOLibError(
					"'%s' could not be written on %s because "
					"the data is not properly formatted: %s"
					% (fileName, self.fs, e)
				)
			if self.fs.exists(fileName) and data == self.fs.readbytes(fileName):
				return
			self.fs.writebytes(fileName, data)
		else:
			with self.fs.openbin(fileName, mode="w") as fp:
				try:
					plistlib.dump(obj, fp)
				except Exception as e:
					raise UFOLibError(
						"'%s' could not be written on %s because "
						"the data is not properly formatted: %s"
						% (fileName, self.fs, e)
					)


# ----------
# UFO Reader
# ----------

class UFOReader(_UFOBaseIO):

	"""
	Read the various components of the .ufo.

	By default read data is validated. Set ``validate`` to
	``False`` to not validate the data.
	"""

	def __init__(self, path, validate=True):
		if hasattr(path, "__fspath__"):  # support os.PathLike objects
			path = path.__fspath__()

		if isinstance(path, basestring):
			structure = _sniffFileStructure(path)
			try:
				if structure is UFOFileStructure.ZIP:
					parentFS = fs.zipfs.ZipFS(path, write=False, encoding="utf-8")
				else:
					parentFS = fs.osfs.OSFS(path)
			except fs.errors.CreateFailed as e:
				raise UFOLibError("unable to open '%s': %s" % (path, e))

			if structure is UFOFileStructure.ZIP:
				# .ufoz zip files must contain a single root directory, with arbitrary
				# name, containing all the UFO files
				rootDirs = [
					p.name for p in parentFS.scandir("/")
					# exclude macOS metadata contained in zip file
					if p.is_dir and p.name != "__MACOSX"
				]
				if len(rootDirs) == 1:
					# 'ClosingSubFS' ensures that the parent zip file is closed when
					# its root subdirectory is closed
					self.fs = parentFS.opendir(
						rootDirs[0], factory=fs.subfs.ClosingSubFS
					)
				else:
					raise UFOLibError(
						"Expected exactly 1 root directory, found %d" % len(rootDirs)
					)
			else:
				# normal UFO 'packages' are just a single folder
				self.fs = parentFS
			# when passed a path string, we make sure we close the newly opened fs
			# upon calling UFOReader.close method or context manager's __exit__
			self._shouldClose = True
			self._fileStructure = structure
		elif isinstance(path, fs.base.FS):
			filesystem = path
			try:
				filesystem.check()
			except fs.errors.FilesystemClosed:
				raise UFOLibError("the filesystem '%s' is closed" % path)
			else:
				self.fs = filesystem
			try:
				path = filesystem.getsyspath("/")
			except fs.errors.NoSysPath:
				# network or in-memory FS may not map to the local one
				path = unicode(filesystem)
			# when user passed an already initialized fs instance, it is her
			# responsibility to close it, thus UFOReader.close/__exit__ are no-op
			self._shouldClose = False
			# default to a 'package' structure
			self._fileStructure = UFOFileStructure.PACKAGE
		else:
			raise TypeError(
				"Expected a path string or fs.base.FS object, found '%s'"
				% type(path).__name__
			)
		self._path = fsdecode(path)
		self._validate = validate
		self.readMetaInfo(validate=validate)
		self._upConvertedKerningData = None

	# properties

	def _get_path(self):
		import warnings

		warnings.warn(
			"The 'path' attribute is deprecated; use the 'fs' attribute instead",
			DeprecationWarning,
			stacklevel=2,
		)
		return self._path

	path = property(_get_path, doc="The path of the UFO (DEPRECATED).")

	def _get_formatVersion(self):
		return self._formatVersion

	formatVersion = property(_get_formatVersion, doc="The format version of the UFO. This is determined by reading metainfo.plist during __init__.")

	def _get_fileStructure(self):
		return self._fileStructure

	fileStructure = property(
		_get_fileStructure,
		doc=(
			"The file structure of the UFO: "
			"either UFOFileStructure.ZIP or UFOFileStructure.PACKAGE"
		)
	)

	# up conversion

	def _upConvertKerning(self, validate):
		"""
		Up convert kerning and groups in UFO 1 and 2.
		The data will be held internally until each bit of data
		has been retrieved. The conversion of both must be done
		at once, so the raw data is cached and an error is raised
		if one bit of data becomes obsolete before it is called.

		``validate`` will validate the data.
		"""
		if self._upConvertedKerningData:
			testKerning = self._readKerning()
			if testKerning != self._upConvertedKerningData["originalKerning"]:
				raise UFOLibError("The data in kerning.plist has been modified since it was converted to UFO 3 format.")
			testGroups = self._readGroups()
			if testGroups != self._upConvertedKerningData["originalGroups"]:
				raise UFOLibError("The data in groups.plist has been modified since it was converted to UFO 3 format.")
		else:
			groups = self._readGroups()
			if validate:
				invalidFormatMessage = "groups.plist is not properly formatted."
				if not isinstance(groups, dict):
					raise UFOLibError(invalidFormatMessage)
				for groupName, glyphList in groups.items():
					if not isinstance(groupName, basestring):
						raise UFOLibError(invalidFormatMessage)
					elif not isinstance(glyphList, list):
						raise UFOLibError(invalidFormatMessage)
					for glyphName in glyphList:
						if not isinstance(glyphName, basestring):
							raise UFOLibError(invalidFormatMessage)
			self._upConvertedKerningData = dict(
				kerning={},
				originalKerning=self._readKerning(),
				groups={},
				originalGroups=groups
			)
			# convert kerning and groups
			kerning, groups, conversionMaps = convertUFO1OrUFO2KerningToUFO3Kerning(
				self._upConvertedKerningData["originalKerning"],
				deepcopy(self._upConvertedKerningData["originalGroups"])
			)
			# store
			self._upConvertedKerningData["kerning"] = kerning
			self._upConvertedKerningData["groups"] = groups
			self._upConvertedKerningData["groupRenameMaps"] = conversionMaps

	# support methods

	def readBytesFromPath(self, path):
		"""
		Returns the bytes in the file at the given path.
		The path must be relative to the UFO's filesystem root.
		Returns None if the file does not exist.
		"""
		try:
			return self.fs.readbytes(fsdecode(path))
		except fs.errors.ResourceNotFound:
			return None

	def getReadFileForPath(self, path, encoding=None):
		"""
		Returns a file (or file-like) object for the file at the given path.
		The path must be relative to the UFO path.
		Returns None if the file does not exist.
		By default the file is opened in binary mode (reads bytes).
		If encoding is passed, the file is opened in text mode (reads unicode).

		Note: The caller is responsible for closing the open file.
		"""
		path = fsdecode(path)
		try:
			if encoding is None:
				return self.fs.openbin(path)
			else:
				return self.fs.open(path, mode="r", encoding=encoding)
		except fs.errors.ResourceNotFound:
			return None
	# metainfo.plist

	def readMetaInfo(self, validate=None):
		"""
		Read metainfo.plist. Only used for internal operations.

		``validate`` will validate the read data, by default it is set
		to the class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		data = self._getPlist(METAINFO_FILENAME)
		if validate and not isinstance(data, dict):
			raise UFOLibError("metainfo.plist is not properly formatted.")
		formatVersion = data["formatVersion"]
		if validate:
			if not isinstance(formatVersion, int):
				raise UFOLibError(
					"formatVersion must be specified as an integer in '%s' on %s"
					% (METAINFO_FILENAME, self.fs)
				)
			if formatVersion not in supportedUFOFormatVersions:
				raise UFOLibError(
					"Unsupported UFO format (%d) in '%s' on %s"
					% (formatVersion, METAINFO_FILENAME, self.fs)
				)
		self._formatVersion = formatVersion

	# groups.plist

	def _readGroups(self):
		return self._getPlist(GROUPS_FILENAME, {})

	def readGroups(self, validate=None):
		"""
		Read groups.plist. Returns a dict.
		``validate`` will validate the read data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		# handle up conversion
		if self._formatVersion < 3:
			self._upConvertKerning(validate)
			groups = self._upConvertedKerningData["groups"]
		# normal
		else:
			groups = self._readGroups()
		if validate:
			valid, message = groupsValidator(groups)
			if not valid:
				raise UFOLibError(message)
		return groups

	def getKerningGroupConversionRenameMaps(self, validate=None):
		"""
		Get maps defining the renaming that was done during any
		needed kerning group conversion. This method returns a
		dictionary of this form:

			{
				"side1" : {"old group name" : "new group name"},
				"side2" : {"old group name" : "new group name"}
			}

		When no conversion has been performed, the side1 and side2
		dictionaries will be empty.

		``validate`` will validate the groups, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		if self._formatVersion >= 3:
			return dict(side1={}, side2={})
		# use the public group reader to force the load and
		# conversion of the data if it hasn't happened yet.
		self.readGroups(validate=validate)
		return self._upConvertedKerningData["groupRenameMaps"]

	# fontinfo.plist

	def _readInfo(self, validate):
		data = self._getPlist(FONTINFO_FILENAME, {})
		if validate and not isinstance(data, dict):
			raise UFOLibError("fontinfo.plist is not properly formatted.")
		return data

	def readInfo(self, info, validate=None):
		"""
		Read fontinfo.plist. It requires an object that allows
		setting attributes with names that follow the fontinfo.plist
		version 3 specification. This will write the attributes
		defined in the file into the object.

		``validate`` will validate the read data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		infoDict = self._readInfo(validate)
		infoDataToSet = {}
		# version 1
		if self._formatVersion == 1:
			for attr in fontInfoAttributesVersion1:
				value = infoDict.get(attr)
				if value is not None:
					infoDataToSet[attr] = value
			infoDataToSet = _convertFontInfoDataVersion1ToVersion2(infoDataToSet)
			infoDataToSet = _convertFontInfoDataVersion2ToVersion3(infoDataToSet)
		# version 2
		elif self._formatVersion == 2:
			for attr, dataValidationDict in list(fontInfoAttributesVersion2ValueData.items()):
				value = infoDict.get(attr)
				if value is None:
					continue
				infoDataToSet[attr] = value
			infoDataToSet = _convertFontInfoDataVersion2ToVersion3(infoDataToSet)
		# version 3
		elif self._formatVersion == 3:
			for attr, dataValidationDict in list(fontInfoAttributesVersion3ValueData.items()):
				value = infoDict.get(attr)
				if value is None:
					continue
				infoDataToSet[attr] = value
		# unsupported version
		else:
			raise NotImplementedError
		# validate data
		if validate:
			infoDataToSet = validateInfoVersion3Data(infoDataToSet)
		# populate the object
		for attr, value in list(infoDataToSet.items()):
			try:
				setattr(info, attr, value)
			except AttributeError:
				raise UFOLibError("The supplied info object does not support setting a necessary attribute (%s)." % attr)

	# kerning.plist

	def _readKerning(self):
		data = self._getPlist(KERNING_FILENAME, {})
		return data

	def readKerning(self, validate=None):
		"""
		Read kerning.plist. Returns a dict.

		``validate`` will validate the kerning data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		# handle up conversion
		if self._formatVersion < 3:
			self._upConvertKerning(validate)
			kerningNested = self._upConvertedKerningData["kerning"]
		# normal
		else:
			kerningNested = self._readKerning()
		if validate:
			valid, message = kerningValidator(kerningNested)
			if not valid:
				raise UFOLibError(message)
		# flatten
		kerning = {}
		for left in kerningNested:
			for right in kerningNested[left]:
				value = kerningNested[left][right]
				kerning[left, right] = value
		return kerning

	# lib.plist

	def readLib(self, validate=None):
		"""
		Read lib.plist. Returns a dict.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		data = self._getPlist(LIB_FILENAME, {})
		if validate:
			valid, message = fontLibValidator(data)
			if not valid:
				raise UFOLibError(message)
		return data

	# features.fea

	def readFeatures(self):
		"""
		Read features.fea. Return a unicode string.
		The returned string is empty if the file is missing.
		"""
		try:
			with self.fs.open(FEATURES_FILENAME, "r", encoding="utf-8") as f:
				return f.read()
		except fs.errors.ResourceNotFound:
			return ""

	# glyph sets & layers

	def _readLayerContents(self, validate):
		"""
		Rebuild the layer contents list by checking what glyphsets
		are available on disk.

		``validate`` will validate the layer contents.
		"""
		if self._formatVersion < 3:
			return [(DEFAULT_LAYER_NAME, DEFAULT_GLYPHS_DIRNAME)]
		contents = self._getPlist(LAYERCONTENTS_FILENAME)
		if validate:
			valid, error = layerContentsValidator(contents, self.fs)
			if not valid:
				raise UFOLibError(error)
		return contents

	def getLayerNames(self, validate=None):
		"""
		Get the ordered layer names from layercontents.plist.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		layerContents = self._readLayerContents(validate)
		layerNames = [layerName for layerName, directoryName in layerContents]
		return layerNames

	def getDefaultLayerName(self, validate=None):
		"""
		Get the default layer name from layercontents.plist.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		layerContents = self._readLayerContents(validate)
		for layerName, layerDirectory in layerContents:
			if layerDirectory == DEFAULT_GLYPHS_DIRNAME:
				return layerName
		# this will already have been raised during __init__
		raise UFOLibError("The default layer is not defined in layercontents.plist.")

	def getGlyphSet(self, layerName=None, validateRead=None, validateWrite=None):
		"""
		Return the GlyphSet associated with the
		glyphs directory mapped to layerName
		in the UFO. If layerName is not provided,
		the name retrieved with getDefaultLayerName
		will be used.

		``validateRead`` will validate the read data, by default it is set to the
		class's validate value, can be overridden.
		``validateWrte`` will validate the written data, by default it is set to the
		class's validate value, can be overridden.
		"""
		from fontTools.ufoLib.glifLib import GlyphSet

		if validateRead is None:
			validateRead = self._validate
		if validateWrite is None:
			validateWrite = self._validate
		if layerName is None:
			layerName = self.getDefaultLayerName(validate=validateRead)
		directory = None
		layerContents = self._readLayerContents(validateRead)
		for storedLayerName, storedLayerDirectory in layerContents:
			if layerName == storedLayerName:
				directory = storedLayerDirectory
				break
		if directory is None:
			raise UFOLibError("No glyphs directory is mapped to \"%s\"." % layerName)
		try:
			glyphSubFS = self.fs.opendir(directory)
		except fs.errors.ResourceNotFound:
			raise UFOLibError(
				"No '%s' directory for layer '%s'" % (directory, layerName)
			)
		return GlyphSet(
			glyphSubFS,
			ufoFormatVersion=self._formatVersion,
			validateRead=validateRead,
			validateWrite=validateWrite,
		)

	def getCharacterMapping(self, layerName=None, validate=None):
		"""
		Return a dictionary that maps unicode values (ints) to
		lists of glyph names.
		"""
		if validate is None:
			validate = self._validate
		glyphSet = self.getGlyphSet(layerName, validateRead=validate, validateWrite=True)
		allUnicodes = glyphSet.getUnicodes()
		cmap = {}
		for glyphName, unicodes in allUnicodes.items():
			for code in unicodes:
				if code in cmap:
					cmap[code].append(glyphName)
				else:
					cmap[code] = [glyphName]
		return cmap

	# /data

	def getDataDirectoryListing(self):
		"""
		Returns a list of all files in the data directory.
		The returned paths will be relative to the UFO.
		This will not list directory names, only file names.
		Thus, empty directories will be skipped.
		"""
		try:
			self._dataFS = self.fs.opendir(DATA_DIRNAME)
		except fs.errors.ResourceNotFound:
			return []
		except fs.errors.DirectoryExpected:
			raise UFOLibError("The UFO contains a \"data\" file instead of a directory.")
		try:
			# fs Walker.files method returns "absolute" paths (in terms of the
			# root of the 'data' SubFS), so we strip the leading '/' to make
			# them relative
			return [
				p.lstrip("/") for p in self._dataFS.walk.files()
			]
		except fs.errors.ResourceError:
			return []

	def getImageDirectoryListing(self, validate=None):
		"""
		Returns a list of all image file names in
		the images directory. Each of the images will
		have been verified to have the PNG signature.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if self._formatVersion < 3:
			return []
		if validate is None:
			validate = self._validate
		try:
			self._imagesFS = imagesFS = self.fs.opendir(IMAGES_DIRNAME)
		except fs.errors.ResourceNotFound:
			return []
		except fs.errors.DirectoryExpected:
			raise UFOLibError("The UFO contains an \"images\" file instead of a directory.")
		result = []
		for path in imagesFS.scandir("/"):
			if path.is_dir:
				# silently skip this as version control
				# systems often have hidden directories
				continue
			if validate:
				with imagesFS.openbin(path.name) as fp:
					valid, error = pngValidator(fileObj=fp)
				if valid:
					result.append(path.name)
			else:
				result.append(path.name)
		return result

	def readData(self, fileName):
		"""
		Return bytes for the file named 'fileName' inside the 'data/' directory.
		"""
		fileName = fsdecode(fileName)
		try:
			try:
				dataFS = self._dataFS
			except AttributeError:
				# in case readData is called before getDataDirectoryListing
				dataFS = self.fs.opendir(DATA_DIRNAME)
			data = dataFS.readbytes(fileName)
		except fs.errors.ResourceNotFound:
			raise UFOLibError("No data file named '%s' on %s" % (fileName, self.fs))
		return data

	def readImage(self, fileName, validate=None):
		"""
		Return image data for the file named fileName.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		if self._formatVersion < 3:
			raise UFOLibError("Reading images is not allowed in UFO %d." % self._formatVersion)
		fileName = fsdecode(fileName)
		try:
			try:
				imagesFS = self._imagesFS
			except AttributeError:
				# in case readImage is called before getImageDirectoryListing
				imagesFS = self.fs.opendir(IMAGES_DIRNAME)
			data = imagesFS.readbytes(fileName)
		except fs.errors.ResourceNotFound:
			raise UFOLibError("No image file named '%s' on %s" % (fileName, self.fs))
		if validate:
			valid, error = pngValidator(data=data)
			if not valid:
				raise UFOLibError(error)
		return data

	def close(self):
		if self._shouldClose:
			self.fs.close()

	def __enter__(self):
		return self

	def __exit__(self, exc_type, exc_value, exc_tb):
		self.close()


# ----------
# UFO Writer
# ----------

class UFOWriter(UFOReader):

	"""
	Write the various components of the .ufo.

	By default, the written data will be validated before writing. Set ``validate`` to
	``False`` if you do not want to validate the data. Validation can also be overriden
	on a per method level if desired.
	"""

	def __init__(
		self,
		path,
		formatVersion=3,
		fileCreator="com.github.fonttools.ufoLib",
		structure=None,
		validate=True,
	):
		if formatVersion not in supportedUFOFormatVersions:
			raise UFOLibError("Unsupported UFO format (%d)." % formatVersion)

		if hasattr(path, "__fspath__"):  # support os.PathLike objects
			path = path.__fspath__()

		if isinstance(path, basestring):
			# normalize path by removing trailing or double slashes
			path = os.path.normpath(path)
			havePreviousFile = os.path.exists(path)
			if havePreviousFile:
				# ensure we use the same structure as the destination
				existingStructure = _sniffFileStructure(path)
				if structure is not None:
					try:
						structure = UFOFileStructure(structure)
					except ValueError:
						raise UFOLibError(
							"Invalid or unsupported structure: '%s'" % structure
						)
					if structure is not existingStructure:
						raise UFOLibError(
							"A UFO with a different structure (%s) already exists "
							"at the given path: '%s'" % (existingStructure, path)
						)
				else:
					structure = existingStructure
			else:
				# if not exists, default to 'package' structure
				if structure is None:
					structure = UFOFileStructure.PACKAGE
				dirName = os.path.dirname(path)
				if dirName and not os.path.isdir(dirName):
					raise UFOLibError(
						"Cannot write to '%s': directory does not exist" % path
					)
			if structure is UFOFileStructure.ZIP:
				if havePreviousFile:
					# we can't write a zip in-place, so we have to copy its
					# contents to a temporary location and work from there, then
					# upon closing UFOWriter we create the final zip file
					parentFS = fs.tempfs.TempFS()
					with fs.zipfs.ZipFS(path, encoding="utf-8") as origFS:
						fs.copy.copy_fs(origFS, parentFS)
					# if output path is an existing zip, we require that it contains
					# one, and only one, root directory (with arbitrary name), in turn
					# containing all the existing UFO contents
					rootDirs = [
						p.name for p in parentFS.scandir("/")
						# exclude macOS metadata contained in zip file
						if p.is_dir and p.name != "__MACOSX"
					]
					if len(rootDirs) != 1:
						raise UFOLibError(
							"Expected exactly 1 root directory, found %d" % len(rootDirs)
						)
					else:
						# 'ClosingSubFS' ensures that the parent filesystem is closed
						# when its root subdirectory is closed
						self.fs = parentFS.opendir(
							rootDirs[0], factory=fs.subfs.ClosingSubFS
						)
				else:
					# if the output zip file didn't exist, we create the root folder;
					# we name it the same as input 'path', but with '.ufo' extension
					rootDir = os.path.splitext(os.path.basename(path))[0] + ".ufo"
					parentFS = fs.zipfs.ZipFS(path, write=True, encoding="utf-8")
					parentFS.makedir(rootDir)
					self.fs = parentFS.opendir(rootDir, factory=fs.subfs.ClosingSubFS)
			else:
				self.fs = fs.osfs.OSFS(path, create=True)
			self._fileStructure = structure
			self._havePreviousFile = havePreviousFile
			self._shouldClose = True
		elif isinstance(path, fs.base.FS):
			filesystem = path
			try:
				filesystem.check()
			except fs.errors.FilesystemClosed:
				raise UFOLibError("the filesystem '%s' is closed" % path)
			else:
				self.fs = filesystem
			try:
				path = filesystem.getsyspath("/")
			except fs.errors.NoSysPath:
				# network or in-memory FS may not map to the local one
				path = unicode(filesystem)
			# if passed an FS object, always use 'package' structure
			if structure and structure is not UFOFileStructure.PACKAGE:
				import warnings

				warnings.warn(
					"The 'structure' argument is not used when input is an FS object",
					UserWarning,
					stacklevel=2,
				)
			self._fileStructure = UFOFileStructure.PACKAGE
			# if FS contains a "metainfo.plist", we consider it non-empty
			self._havePreviousFile = filesystem.exists(METAINFO_FILENAME)
			# the user is responsible for closing the FS object
			self._shouldClose = False
		else:
			raise TypeError(
				"Expected a path string or fs object, found %s"
				% type(path).__name__
			)

		# establish some basic stuff
		self._path = fsdecode(path)
		self._formatVersion = formatVersion
		self._fileCreator = fileCreator
		self._downConversionKerningData = None
		self._validate = validate
		# if the file already exists, get the format version.
		# this will be needed for up and down conversion.
		previousFormatVersion = None
		if self._havePreviousFile:
			metaInfo = self._getPlist(METAINFO_FILENAME)
			previousFormatVersion = metaInfo.get("formatVersion")
			try:
				previousFormatVersion = int(previousFormatVersion)
			except (ValueError, TypeError):
				self.fs.close()
				raise UFOLibError("The existing metainfo.plist is not properly formatted.")
			if previousFormatVersion not in supportedUFOFormatVersions:
				self.fs.close()
				raise UFOLibError("Unsupported UFO format (%d)." % formatVersion)
		# catch down conversion
		if previousFormatVersion is not None and previousFormatVersion > formatVersion:
			raise UFOLibError("The UFO located at this path is a higher version (%d) than the version (%d) that is trying to be written. This is not supported." % (previousFormatVersion, formatVersion))
		# handle the layer contents
		self.layerContents = {}
		if previousFormatVersion is not None and previousFormatVersion >= 3:
			# already exists
			self.layerContents = OrderedDict(self._readLayerContents(validate))
		else:
			# previous < 3
			# imply the layer contents
			if self.fs.exists(DEFAULT_GLYPHS_DIRNAME):
				self.layerContents = {DEFAULT_LAYER_NAME : DEFAULT_GLYPHS_DIRNAME}
		# write the new metainfo
		self._writeMetaInfo()

	# properties

	def _get_fileCreator(self):
		return self._fileCreator

	fileCreator = property(_get_fileCreator, doc="The file creator of the UFO. This is set into metainfo.plist during __init__.")

	# support methods for file system interaction

	def copyFromReader(self, reader, sourcePath, destPath):
		"""
		Copy the sourcePath in the provided UFOReader to destPath
		in this writer. The paths must be relative. This works with
		both individual files and directories.
		"""
		if not isinstance(reader, UFOReader):
			raise UFOLibError("The reader must be an instance of UFOReader.")
		sourcePath = fsdecode(sourcePath)
		destPath = fsdecode(destPath)
		if not reader.fs.exists(sourcePath):
			raise UFOLibError("The reader does not have data located at \"%s\"." % sourcePath)
		if self.fs.exists(destPath):
			raise UFOLibError("A file named \"%s\" already exists." % destPath)
		# create the destination directory if it doesn't exist
		self.fs.makedirs(fs.path.dirname(destPath), recreate=True)
		if reader.fs.isdir(sourcePath):
			fs.copy.copy_dir(reader.fs, sourcePath, self.fs, destPath)
		else:
			fs.copy.copy_file(reader.fs, sourcePath, self.fs, destPath)

	def writeBytesToPath(self, path, data):
		"""
		Write bytes to a path relative to the UFO filesystem's root.
		If writing to an existing UFO, check to see if data matches the data
		that is already in the file at path; if so, the file is not rewritten
		so that the modification date is preserved.
		If needed, the directory tree for the given path will be built.
		"""
		path = fsdecode(path)
		if self._havePreviousFile:
			if self.fs.isfile(path) and data == self.fs.readbytes(path):
				return
		try:
			self.fs.writebytes(path, data)
		except fs.errors.FileExpected:
			raise UFOLibError("A directory exists at '%s'" % path)
		except fs.errors.ResourceNotFound:
			self.fs.makedirs(fs.path.dirname(path), recreate=True)
			self.fs.writebytes(path, data)

	def getFileObjectForPath(self, path, mode="w", encoding=None):
		"""
		Returns a file (or file-like) object for the
		file at the given path. The path must be relative
		to the UFO path. Returns None if the file does
		not exist and the mode is "r" or "rb.
		An encoding may be passed if the file is opened in text mode.

		Note: The caller is responsible for closing the open file.
		"""
		path = fsdecode(path)
		try:
			return self.fs.open(path, mode=mode, encoding=encoding)
		except fs.errors.ResourceNotFound as e:
			m = mode[0]
			if m == "r":
				# XXX I think we should just let it raise. The docstring,
				# however, says that this returns None if mode is 'r'
				return None
			elif m == "w" or m == "a" or m == "x":
				self.fs.makedirs(fs.path.dirname(path), recreate=True)
				return self.fs.open(path, mode=mode, encoding=encoding)
		except fs.errors.ResourceError as e:
			return UFOLibError(
				"unable to open '%s' on %s: %s" % (path, self.fs, e)
			)

	def removePath(self, path, force=False, removeEmptyParents=True):
		"""
		Remove the file (or directory) at path. The path
		must be relative to the UFO.
		Raises UFOLibError if the path doesn't exist.
		If force=True, ignore non-existent paths.
		If the directory where 'path' is located becomes empty, it will
		be automatically removed, unless 'removeEmptyParents' is False.
		"""
		path = fsdecode(path)
		try:
			self.fs.remove(path)
		except fs.errors.FileExpected:
			self.fs.removetree(path)
		except fs.errors.ResourceNotFound:
			if not force:
				raise UFOLibError(
					"'%s' does not exist on %s" % (path, self.fs)
				)
		if removeEmptyParents:
			parent = fs.path.dirname(path)
			if parent:
				fs.tools.remove_empty(self.fs, parent)

	# alias kept for backward compatibility with old API
	removeFileForPath = removePath

	# UFO mod time

	def setModificationTime(self):
		"""
		Set the UFO modification time to the current time.
		This is never called automatically. It is up to the
		caller to call this when finished working on the UFO.
		"""
		path = self._path
		if path is not None and os.path.exists(path):
			try:
				# this may fail on some filesystems (e.g. SMB servers)
				os.utime(path, None)
			except OSError as e:
				logger.warning("Failed to set modified time: %s", e)

	# metainfo.plist

	def _writeMetaInfo(self):
		metaInfo = dict(
			creator=self._fileCreator,
			formatVersion=self._formatVersion
		)
		self._writePlist(METAINFO_FILENAME, metaInfo)

	# groups.plist

	def setKerningGroupConversionRenameMaps(self, maps):
		"""
		Set maps defining the renaming that should be done
		when writing groups and kerning in UFO 1 and UFO 2.
		This will effectively undo the conversion done when
		UFOReader reads this data. The dictionary should have
		this form:

			{
				"side1" : {"group name to use when writing" : "group name in data"},
				"side2" : {"group name to use when writing" : "group name in data"}
			}

		This is the same form returned by UFOReader's
		getKerningGroupConversionRenameMaps method.
		"""
		if self._formatVersion >= 3:
			return # XXX raise an error here
		# flip the dictionaries
		remap = {}
		for side in ("side1", "side2"):
			for writeName, dataName in list(maps[side].items()):
				remap[dataName] = writeName
		self._downConversionKerningData = dict(groupRenameMap=remap)

	def writeGroups(self, groups, validate=None):
		"""
		Write groups.plist. This method requires a
		dict of glyph groups as an argument.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		# validate the data structure
		if validate:
			valid, message = groupsValidator(groups)
			if not valid:
				raise UFOLibError(message)
		# down convert
		if self._formatVersion < 3 and self._downConversionKerningData is not None:
			remap = self._downConversionKerningData["groupRenameMap"]
			remappedGroups = {}
			# there are some edge cases here that are ignored:
			# 1. if a group is being renamed to a name that
			#    already exists, the existing group is always
			#    overwritten. (this is why there are two loops
			#    below.) there doesn't seem to be a logical
			#    solution to groups mismatching and overwriting
			#    with the specifiecd group seems like a better
			#    solution than throwing an error.
			# 2. if side 1 and side 2 groups are being renamed
			#    to the same group name there is no check to
			#    ensure that the contents are identical. that
			#    is left up to the caller.
			for name, contents in list(groups.items()):
				if name in remap:
					continue
				remappedGroups[name] = contents
			for name, contents in list(groups.items()):
				if name not in remap:
					continue
				name = remap[name]
				remappedGroups[name] = contents
			groups = remappedGroups
		# pack and write
		groupsNew = {}
		for key, value in groups.items():
			groupsNew[key] = list(value)
		if groupsNew:
			self._writePlist(GROUPS_FILENAME, groupsNew)
		elif self._havePreviousFile:
			self.removePath(GROUPS_FILENAME, force=True, removeEmptyParents=False)

	# fontinfo.plist

	def writeInfo(self, info, validate=None):
		"""
		Write info.plist. This method requires an object
		that supports getting attributes that follow the
		fontinfo.plist version 2 specification. Attributes
		will be taken from the given object and written
		into the file.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		# gather version 3 data
		infoData = {}
		for attr in list(fontInfoAttributesVersion3ValueData.keys()):
			if hasattr(info, attr):
				try:
					value = getattr(info, attr)
				except AttributeError:
					raise UFOLibError("The supplied info object does not support getting a necessary attribute (%s)." % attr)
				if value is None:
					continue
				infoData[attr] = value
		# down convert data if necessary and validate
		if self._formatVersion == 3:
			if validate:
				infoData = validateInfoVersion3Data(infoData)
		elif self._formatVersion == 2:
			infoData = _convertFontInfoDataVersion3ToVersion2(infoData)
			if validate:
				infoData = validateInfoVersion2Data(infoData)
		elif self._formatVersion == 1:
			infoData = _convertFontInfoDataVersion3ToVersion2(infoData)
			if validate:
				infoData = validateInfoVersion2Data(infoData)
			infoData = _convertFontInfoDataVersion2ToVersion1(infoData)
		# write file
		self._writePlist(FONTINFO_FILENAME, infoData)

	# kerning.plist

	def writeKerning(self, kerning, validate=None):
		"""
		Write kerning.plist. This method requires a
		dict of kerning pairs as an argument.

		This performs basic structural validation of the kerning,
		but it does not check for compliance with the spec in
		regards to conflicting pairs. The assumption is that the
		kerning data being passed is standards compliant.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		# validate the data structure
		if validate:
			invalidFormatMessage = "The kerning is not properly formatted."
			if not isDictEnough(kerning):
				raise UFOLibError(invalidFormatMessage)
			for pair, value in list(kerning.items()):
				if not isinstance(pair, (list, tuple)):
					raise UFOLibError(invalidFormatMessage)
				if not len(pair) == 2:
					raise UFOLibError(invalidFormatMessage)
				if not isinstance(pair[0], basestring):
					raise UFOLibError(invalidFormatMessage)
				if not isinstance(pair[1], basestring):
					raise UFOLibError(invalidFormatMessage)
				if not isinstance(value, numberTypes):
					raise UFOLibError(invalidFormatMessage)
		# down convert
		if self._formatVersion < 3 and self._downConversionKerningData is not None:
			remap = self._downConversionKerningData["groupRenameMap"]
			remappedKerning = {}
			for (side1, side2), value in list(kerning.items()):
				side1 = remap.get(side1, side1)
				side2 = remap.get(side2, side2)
				remappedKerning[side1, side2] = value
			kerning = remappedKerning
		# pack and write
		kerningDict = {}
		for left, right in kerning.keys():
			value = kerning[left, right]
			if left not in kerningDict:
				kerningDict[left] = {}
			kerningDict[left][right] = value
		if kerningDict:
			self._writePlist(KERNING_FILENAME, kerningDict)
		elif self._havePreviousFile:
			self.removePath(KERNING_FILENAME, force=True, removeEmptyParents=False)

	# lib.plist

	def writeLib(self, libDict, validate=None):
		"""
		Write lib.plist. This method requires a
		lib dict as an argument.

		``validate`` will validate the data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validate is None:
			validate = self._validate
		if validate:
			valid, message = fontLibValidator(libDict)
			if not valid:
				raise UFOLibError(message)
		if libDict:
			self._writePlist(LIB_FILENAME, libDict)
		elif self._havePreviousFile:
			self.removePath(LIB_FILENAME, force=True, removeEmptyParents=False)

	# features.fea

	def writeFeatures(self, features, validate=None):
		"""
		Write features.fea. This method requires a
		features string as an argument.
		"""
		if validate is None:
			validate = self._validate
		if self._formatVersion == 1:
			raise UFOLibError("features.fea is not allowed in UFO Format Version 1.")
		if validate:
			if not isinstance(features, basestring):
				raise UFOLibError("The features are not text.")
		if features:
			self.writeBytesToPath(FEATURES_FILENAME, features.encode("utf8"))
		elif self._havePreviousFile:
			self.removePath(FEATURES_FILENAME, force=True, removeEmptyParents=False)

	# glyph sets & layers

	def writeLayerContents(self, layerOrder=None, validate=None):
		"""
		Write the layercontents.plist file. This method  *must* be called
		after all glyph sets have been written.
		"""
		if validate is None:
			validate = self._validate
		if self.formatVersion < 3:
			return
		if layerOrder is not None:
			newOrder = []
			for layerName in layerOrder:
				if layerName is None:
					layerName = DEFAULT_LAYER_NAME
				else:
					layerName = tounicode(layerName)
				newOrder.append(layerName)
			layerOrder = newOrder
		else:
			layerOrder = list(self.layerContents.keys())
		if validate and set(layerOrder) != set(self.layerContents.keys()):
			raise UFOLibError("The layer order content does not match the glyph sets that have been created.")
		layerContents = [(layerName, self.layerContents[layerName]) for layerName in layerOrder]
		self._writePlist(LAYERCONTENTS_FILENAME, layerContents)

	def _findDirectoryForLayerName(self, layerName):
		foundDirectory = None
		for existingLayerName, directoryName in list(self.layerContents.items()):
			if layerName is None and directoryName == DEFAULT_GLYPHS_DIRNAME:
				foundDirectory = directoryName
				break
			elif existingLayerName == layerName:
				foundDirectory = directoryName
				break
		if not foundDirectory:
			raise UFOLibError("Could not locate a glyph set directory for the layer named %s." % layerName)
		return foundDirectory

	def getGlyphSet(self, layerName=None, defaultLayer=True, glyphNameToFileNameFunc=None, validateRead=None, validateWrite=None):
		"""
		Return the GlyphSet object associated with the
		appropriate glyph directory in the .ufo.
		If layerName is None, the default glyph set
		will be used. The defaultLayer flag indictes
		that the layer should be saved into the default
		glyphs directory.

		``validateRead`` will validate the read data, by default it is set to the
		class's validate value, can be overridden.
		``validateWrte`` will validate the written data, by default it is set to the
		class's validate value, can be overridden.
		"""
		if validateRead is None:
			validateRead = self._validate
		if validateWrite is None:
			validateWrite = self._validate
		# only default can be written in < 3
		if self._formatVersion < 3 and (not defaultLayer or layerName is not None):
			raise UFOLibError("Only the default layer can be writen in UFO %d." % self.formatVersion)
		# locate a layer name when None has been given
		if layerName is None and defaultLayer:
			for existingLayerName, directory in self.layerContents.items():
				if directory == DEFAULT_GLYPHS_DIRNAME:
					layerName = existingLayerName
			if layerName is None:
				layerName = DEFAULT_LAYER_NAME
		elif layerName is None and not defaultLayer:
			raise UFOLibError("A layer name must be provided for non-default layers.")
		# move along to format specific writing
		if self.formatVersion == 1:
			return self._getGlyphSetFormatVersion1(validateRead, validateWrite, glyphNameToFileNameFunc=glyphNameToFileNameFunc)
		elif self.formatVersion == 2:
			return self._getGlyphSetFormatVersion2(validateRead, validateWrite, glyphNameToFileNameFunc=glyphNameToFileNameFunc)
		elif self.formatVersion == 3:
			return self._getGlyphSetFormatVersion3(validateRead, validateWrite, layerName=layerName, defaultLayer=defaultLayer, glyphNameToFileNameFunc=glyphNameToFileNameFunc)
		else:
			raise AssertionError(self.formatVersion)

	def _getGlyphSetFormatVersion1(self, validateRead, validateWrite, glyphNameToFileNameFunc=None):
		from fontTools.ufoLib.glifLib import GlyphSet

		glyphSubFS = self.fs.makedir(DEFAULT_GLYPHS_DIRNAME, recreate=True)
		return GlyphSet(
			glyphSubFS,
			glyphNameToFileNameFunc=glyphNameToFileNameFunc,
			ufoFormatVersion=1,
			validateRead=validateRead,
			validateWrite=validateWrite,
		)

	def _getGlyphSetFormatVersion2(self, validateRead, validateWrite, glyphNameToFileNameFunc=None):
		from fontTools.ufoLib.glifLib import GlyphSet

		glyphSubFS = self.fs.makedir(DEFAULT_GLYPHS_DIRNAME, recreate=True)
		return GlyphSet(
			glyphSubFS,
			glyphNameToFileNameFunc=glyphNameToFileNameFunc,
			ufoFormatVersion=2,
			validateRead=validateRead,
			validateWrite=validateWrite,
		)

	def _getGlyphSetFormatVersion3(self, validateRead, validateWrite, layerName=None, defaultLayer=True, glyphNameToFileNameFunc=None):
		from fontTools.ufoLib.glifLib import GlyphSet

		# if the default flag is on, make sure that the default in the file
		# matches the default being written. also make sure that this layer
		# name is not already linked to a non-default layer.
		if defaultLayer:
			for existingLayerName, directory in self.layerContents.items():
				if directory == DEFAULT_GLYPHS_DIRNAME:
					if existingLayerName != layerName:
						raise UFOLibError(
							"Another layer ('%s') is already mapped to the default directory."
							% existingLayerName
						)
				elif existingLayerName == layerName:
					raise UFOLibError("The layer name is already mapped to a non-default layer.")
		# get an existing directory name
		if layerName in self.layerContents:
			directory = self.layerContents[layerName]
		# get a  new directory name
		else:
			if defaultLayer:
				directory = DEFAULT_GLYPHS_DIRNAME
			else:
				# not caching this could be slightly expensive,
				# but caching it will be cumbersome
				existing = {d.lower() for d in self.layerContents.values()}
				if not isinstance(layerName, unicode):
					try:
						layerName = unicode(layerName)
					except UnicodeDecodeError:
						raise UFOLibError("The specified layer name is not a Unicode string.")
				directory = userNameToFileName(layerName, existing=existing, prefix="glyphs.")
		# make the directory
		glyphSubFS = self.fs.makedir(directory, recreate=True)
		# store the mapping
		self.layerContents[layerName] = directory
		# load the glyph set
		return GlyphSet(
			glyphSubFS,
			glyphNameToFileNameFunc=glyphNameToFileNameFunc,
			ufoFormatVersion=3,
			validateRead=validateRead,
			validateWrite=validateWrite,
		)

	def renameGlyphSet(self, layerName, newLayerName, defaultLayer=False):
		"""
		Rename a glyph set.

		Note: if a GlyphSet object has already been retrieved for
		layerName, it is up to the caller to inform that object that
		the directory it represents has changed.
		"""
		if self._formatVersion < 3:
			# ignore renaming glyph sets for UFO1 UFO2
			# just write the data from the default layer
			return
		# the new and old names can be the same
		# as long as the default is being switched
		if layerName == newLayerName:
			# if the default is off and the layer is already not the default, skip
			if self.layerContents[layerName] != DEFAULT_GLYPHS_DIRNAME and not defaultLayer:
				return
			# if the default is on and the layer is already the default, skip
			if self.layerContents[layerName] == DEFAULT_GLYPHS_DIRNAME and defaultLayer:
				return
		else:
			# make sure the new layer name doesn't already exist
			if newLayerName is None:
				newLayerName = DEFAULT_LAYER_NAME
			if newLayerName in self.layerContents:
				raise UFOLibError("A layer named %s already exists." % newLayerName)
			# make sure the default layer doesn't already exist
			if defaultLayer and DEFAULT_GLYPHS_DIRNAME in self.layerContents.values():
				raise UFOLibError("A default layer already exists.")
		# get the paths
		oldDirectory = self._findDirectoryForLayerName(layerName)
		if defaultLayer:
			newDirectory = DEFAULT_GLYPHS_DIRNAME
		else:
			existing = {name.lower() for name in self.layerContents.values()}
			newDirectory = userNameToFileName(newLayerName, existing=existing, prefix="glyphs.")
		# update the internal mapping
		del self.layerContents[layerName]
		self.layerContents[newLayerName] = newDirectory
		# do the file system copy
		self.fs.movedir(oldDirectory, newDirectory, create=True)

	def deleteGlyphSet(self, layerName):
		"""
		Remove the glyph set matching layerName.
		"""
		if self._formatVersion < 3:
			# ignore deleting glyph sets for UFO1 UFO2 as there are no layers
			# just write the data from the default layer
			return
		foundDirectory = self._findDirectoryForLayerName(layerName)
		self.removePath(foundDirectory, removeEmptyParents=False)
		del self.layerContents[layerName]

	def writeData(self, fileName, data):
		"""
		Write data to fileName in the 'data' directory.
		The data must be a bytes string.
		"""
		self.writeBytesToPath("%s/%s" % (DATA_DIRNAME, fsdecode(fileName)), data)

	def removeData(self, fileName):
		"""
		Remove the file named fileName from the data directory.
		"""
		self.removePath("%s/%s" % (DATA_DIRNAME, fsdecode(fileName)))

	# /images

	def writeImage(self, fileName, data, validate=None):
		"""
		Write data to fileName in the images directory.
		The data must be a valid PNG.
		"""
		if validate is None:
			validate = self._validate
		if self._formatVersion < 3:
			raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
		fileName = fsdecode(fileName)
		if validate:
			valid, error = pngValidator(data=data)
			if not valid:
				raise UFOLibError(error)
		self.writeBytesToPath("%s/%s" % (IMAGES_DIRNAME, fileName), data)

	def removeImage(self, fileName, validate=None):  # XXX remove unused 'validate'?
		"""
		Remove the file named fileName from the
		images directory.
		"""
		if self._formatVersion < 3:
			raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
		self.removePath("%s/%s" % (IMAGES_DIRNAME, fsdecode(fileName)))

	def copyImageFromReader(self, reader, sourceFileName, destFileName, validate=None):
		"""
		Copy the sourceFileName in the provided UFOReader to destFileName
		in this writer. This uses the most memory efficient method possible
		for copying the data possible.
		"""
		if validate is None:
			validate = self._validate
		if self._formatVersion < 3:
			raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
		sourcePath = "%s/%s" % (IMAGES_DIRNAME, fsdecode(sourceFileName))
		destPath = "%s/%s" % (IMAGES_DIRNAME, fsdecode(destFileName))
		self.copyFromReader(reader, sourcePath, destPath)

	def close(self):
		if self._havePreviousFile and self._fileStructure is UFOFileStructure.ZIP:
			# if we are updating an existing zip file, we can now compress the
			# contents of the temporary filesystem in the destination path
			rootDir = os.path.splitext(os.path.basename(self._path))[0] + ".ufo"
			with fs.zipfs.ZipFS(self._path, write=True, encoding="utf-8") as destFS:
				fs.copy.copy_fs(self.fs, destFS.makedir(rootDir))
		super(UFOWriter, self).close()


# just an alias, makes it more explicit
UFOReaderWriter = UFOWriter


# ----------------
# Helper Functions
# ----------------


def _sniffFileStructure(ufo_path):
	"""Return UFOFileStructure.ZIP if the UFO at path 'ufo_path' (basestring)
	is a zip file, else return UFOFileStructure.PACKAGE if 'ufo_path' is a
	directory.
	Raise UFOLibError if it is a file with unknown structure, or if the path
	does not exist.
	"""
	if zipfile.is_zipfile(ufo_path):
		return UFOFileStructure.ZIP
	elif os.path.isdir(ufo_path):
		return UFOFileStructure.PACKAGE
	elif os.path.isfile(ufo_path):
		raise UFOLibError(
			"The specified UFO does not have a known structure: '%s'" % ufo_path
		)
	else:
		raise UFOLibError("No such file or directory: '%s'" % ufo_path)


def makeUFOPath(path):
	"""
	Return a .ufo pathname.

	>>> makeUFOPath("directory/something.ext") == (
	... 	os.path.join('directory', 'something.ufo'))
	True
	>>> makeUFOPath("directory/something.another.thing.ext") == (
	... 	os.path.join('directory', 'something.another.thing.ufo'))
	True
	"""
	dir, name = os.path.split(path)
	name = ".".join([".".join(name.split(".")[:-1]), "ufo"])
	return os.path.join(dir, name)

# ----------------------
# fontinfo.plist Support
# ----------------------

# Version Validators

# There is no version 1 validator and there shouldn't be.
# The version 1 spec was very loose and there were numerous
# cases of invalid values.

def validateFontInfoVersion2ValueForAttribute(attr, value):
	"""
	This performs very basic validation of the value for attribute
	following the UFO 2 fontinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the value
	is of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	dataValidationDict = fontInfoAttributesVersion2ValueData[attr]
	valueType = dataValidationDict.get("type")
	validator = dataValidationDict.get("valueValidator")
	valueOptions = dataValidationDict.get("valueOptions")
	# have specific options for the validator
	if valueOptions is not None:
		isValidValue = validator(value, valueOptions)
	# no specific options
	else:
		if validator == genericTypeValidator:
			isValidValue = validator(value, valueType)
		else:
			isValidValue = validator(value)
	return isValidValue

def validateInfoVersion2Data(infoData):
	"""
	This performs very basic validation of the value for infoData
	following the UFO 2 fontinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the values
	are of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	validInfoData = {}
	for attr, value in list(infoData.items()):
		isValidValue = validateFontInfoVersion2ValueForAttribute(attr, value)
		if not isValidValue:
			raise UFOLibError("Invalid value for attribute %s (%s)." % (attr, repr(value)))
		else:
			validInfoData[attr] = value
	return validInfoData

def validateFontInfoVersion3ValueForAttribute(attr, value):
	"""
	This performs very basic validation of the value for attribute
	following the UFO 3 fontinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the value
	is of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	dataValidationDict = fontInfoAttributesVersion3ValueData[attr]
	valueType = dataValidationDict.get("type")
	validator = dataValidationDict.get("valueValidator")
	valueOptions = dataValidationDict.get("valueOptions")
	# have specific options for the validator
	if valueOptions is not None:
		isValidValue = validator(value, valueOptions)
	# no specific options
	else:
		if validator == genericTypeValidator:
			isValidValue = validator(value, valueType)
		else:
			isValidValue = validator(value)
	return isValidValue

def validateInfoVersion3Data(infoData):
	"""
	This performs very basic validation of the value for infoData
	following the UFO 3 fontinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the values
	are of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	validInfoData = {}
	for attr, value in list(infoData.items()):
		isValidValue = validateFontInfoVersion3ValueForAttribute(attr, value)
		if not isValidValue:
			raise UFOLibError("Invalid value for attribute %s (%s)." % (attr, repr(value)))
		else:
			validInfoData[attr] = value
	return validInfoData

# Value Options

fontInfoOpenTypeHeadFlagsOptions = list(range(0, 15))
fontInfoOpenTypeOS2SelectionOptions = [1, 2, 3, 4, 7, 8, 9]
fontInfoOpenTypeOS2UnicodeRangesOptions = list(range(0, 128))
fontInfoOpenTypeOS2CodePageRangesOptions = list(range(0, 64))
fontInfoOpenTypeOS2TypeOptions = [0, 1, 2, 3, 8, 9]

# Version Attribute Definitions
# This defines the attributes, types and, in some
# cases the possible values, that can exist is
# fontinfo.plist.

fontInfoAttributesVersion1 = set([
	"familyName",
	"styleName",
	"fullName",
	"fontName",
	"menuName",
	"fontStyle",
	"note",
	"versionMajor",
	"versionMinor",
	"year",
	"copyright",
	"notice",
	"trademark",
	"license",
	"licenseURL",
	"createdBy",
	"designer",
	"designerURL",
	"vendorURL",
	"unitsPerEm",
	"ascender",
	"descender",
	"capHeight",
	"xHeight",
	"defaultWidth",
	"slantAngle",
	"italicAngle",
	"widthName",
	"weightName",
	"weightValue",
	"fondName",
	"otFamilyName",
	"otStyleName",
	"otMacName",
	"msCharSet",
	"fondID",
	"uniqueID",
	"ttVendor",
	"ttUniqueID",
	"ttVersion",
])

fontInfoAttributesVersion2ValueData = {
	"familyName"							: dict(type=basestring),
	"styleName"								: dict(type=basestring),
	"styleMapFamilyName"					: dict(type=basestring),
	"styleMapStyleName"						: dict(type=basestring, valueValidator=fontInfoStyleMapStyleNameValidator),
	"versionMajor"							: dict(type=int),
	"versionMinor"							: dict(type=int),
	"year"									: dict(type=int),
	"copyright"								: dict(type=basestring),
	"trademark"								: dict(type=basestring),
	"unitsPerEm"							: dict(type=(int, float)),
	"descender"								: dict(type=(int, float)),
	"xHeight"								: dict(type=(int, float)),
	"capHeight"								: dict(type=(int, float)),
	"ascender"								: dict(type=(int, float)),
	"italicAngle"							: dict(type=(float, int)),
	"note"									: dict(type=basestring),
	"openTypeHeadCreated"					: dict(type=basestring, valueValidator=fontInfoOpenTypeHeadCreatedValidator),
	"openTypeHeadLowestRecPPEM"				: dict(type=(int, float)),
	"openTypeHeadFlags"						: dict(type="integerList", valueValidator=genericIntListValidator, valueOptions=fontInfoOpenTypeHeadFlagsOptions),
	"openTypeHheaAscender"					: dict(type=(int, float)),
	"openTypeHheaDescender"					: dict(type=(int, float)),
	"openTypeHheaLineGap"					: dict(type=(int, float)),
	"openTypeHheaCaretSlopeRise"			: dict(type=int),
	"openTypeHheaCaretSlopeRun"				: dict(type=int),
	"openTypeHheaCaretOffset"				: dict(type=(int, float)),
	"openTypeNameDesigner"					: dict(type=basestring),
	"openTypeNameDesignerURL"				: dict(type=basestring),
	"openTypeNameManufacturer"				: dict(type=basestring),
	"openTypeNameManufacturerURL"			: dict(type=basestring),
	"openTypeNameLicense"					: dict(type=basestring),
	"openTypeNameLicenseURL"				: dict(type=basestring),
	"openTypeNameVersion"					: dict(type=basestring),
	"openTypeNameUniqueID"					: dict(type=basestring),
	"openTypeNameDescription"				: dict(type=basestring),
	"openTypeNamePreferredFamilyName"		: dict(type=basestring),
	"openTypeNamePreferredSubfamilyName"	: dict(type=basestring),
	"openTypeNameCompatibleFullName"		: dict(type=basestring),
	"openTypeNameSampleText"				: dict(type=basestring),
	"openTypeNameWWSFamilyName"				: dict(type=basestring),
	"openTypeNameWWSSubfamilyName"			: dict(type=basestring),
	"openTypeOS2WidthClass"					: dict(type=int, valueValidator=fontInfoOpenTypeOS2WidthClassValidator),
	"openTypeOS2WeightClass"				: dict(type=int, valueValidator=fontInfoOpenTypeOS2WeightClassValidator),
	"openTypeOS2Selection"					: dict(type="integerList", valueValidator=genericIntListValidator, valueOptions=fontInfoOpenTypeOS2SelectionOptions),
	"openTypeOS2VendorID"					: dict(type=basestring),
	"openTypeOS2Panose"						: dict(type="integerList", valueValidator=fontInfoVersion2OpenTypeOS2PanoseValidator),
	"openTypeOS2FamilyClass"				: dict(type="integerList", valueValidator=fontInfoOpenTypeOS2FamilyClassValidator),
	"openTypeOS2UnicodeRanges"				: dict(type="integerList", valueValidator=genericIntListValidator, valueOptions=fontInfoOpenTypeOS2UnicodeRangesOptions),
	"openTypeOS2CodePageRanges"				: dict(type="integerList", valueValidator=genericIntListValidator, valueOptions=fontInfoOpenTypeOS2CodePageRangesOptions),
	"openTypeOS2TypoAscender"				: dict(type=(int, float)),
	"openTypeOS2TypoDescender"				: dict(type=(int, float)),
	"openTypeOS2TypoLineGap"				: dict(type=(int, float)),
	"openTypeOS2WinAscent"					: dict(type=(int, float)),
	"openTypeOS2WinDescent"					: dict(type=(int, float)),
	"openTypeOS2Type"						: dict(type="integerList", valueValidator=genericIntListValidator, valueOptions=fontInfoOpenTypeOS2TypeOptions),
	"openTypeOS2SubscriptXSize"				: dict(type=(int, float)),
	"openTypeOS2SubscriptYSize"				: dict(type=(int, float)),
	"openTypeOS2SubscriptXOffset"			: dict(type=(int, float)),
	"openTypeOS2SubscriptYOffset"			: dict(type=(int, float)),
	"openTypeOS2SuperscriptXSize"			: dict(type=(int, float)),
	"openTypeOS2SuperscriptYSize"			: dict(type=(int, float)),
	"openTypeOS2SuperscriptXOffset"			: dict(type=(int, float)),
	"openTypeOS2SuperscriptYOffset"			: dict(type=(int, float)),
	"openTypeOS2StrikeoutSize"				: dict(type=(int, float)),
	"openTypeOS2StrikeoutPosition"			: dict(type=(int, float)),
	"openTypeVheaVertTypoAscender"			: dict(type=(int, float)),
	"openTypeVheaVertTypoDescender"			: dict(type=(int, float)),
	"openTypeVheaVertTypoLineGap"			: dict(type=(int, float)),
	"openTypeVheaCaretSlopeRise"			: dict(type=int),
	"openTypeVheaCaretSlopeRun"				: dict(type=int),
	"openTypeVheaCaretOffset"				: dict(type=(int, float)),
	"postscriptFontName"					: dict(type=basestring),
	"postscriptFullName"					: dict(type=basestring),
	"postscriptSlantAngle"					: dict(type=(float, int)),
	"postscriptUniqueID"					: dict(type=int),
	"postscriptUnderlineThickness"			: dict(type=(int, float)),
	"postscriptUnderlinePosition"			: dict(type=(int, float)),
	"postscriptIsFixedPitch"				: dict(type=bool),
	"postscriptBlueValues"					: dict(type="integerList", valueValidator=fontInfoPostscriptBluesValidator),
	"postscriptOtherBlues"					: dict(type="integerList", valueValidator=fontInfoPostscriptOtherBluesValidator),
	"postscriptFamilyBlues"					: dict(type="integerList", valueValidator=fontInfoPostscriptBluesValidator),
	"postscriptFamilyOtherBlues"			: dict(type="integerList", valueValidator=fontInfoPostscriptOtherBluesValidator),
	"postscriptStemSnapH"					: dict(type="integerList", valueValidator=fontInfoPostscriptStemsValidator),
	"postscriptStemSnapV"					: dict(type="integerList", valueValidator=fontInfoPostscriptStemsValidator),
	"postscriptBlueFuzz"					: dict(type=(int, float)),
	"postscriptBlueShift"					: dict(type=(int, float)),
	"postscriptBlueScale"					: dict(type=(float, int)),
	"postscriptForceBold"					: dict(type=bool),
	"postscriptDefaultWidthX"				: dict(type=(int, float)),
	"postscriptNominalWidthX"				: dict(type=(int, float)),
	"postscriptWeightName"					: dict(type=basestring),
	"postscriptDefaultCharacter"			: dict(type=basestring),
	"postscriptWindowsCharacterSet"			: dict(type=int, valueValidator=fontInfoPostscriptWindowsCharacterSetValidator),
	"macintoshFONDFamilyID"					: dict(type=int),
	"macintoshFONDName"						: dict(type=basestring),
}
fontInfoAttributesVersion2 = set(fontInfoAttributesVersion2ValueData.keys())

fontInfoAttributesVersion3ValueData = deepcopy(fontInfoAttributesVersion2ValueData)
fontInfoAttributesVersion3ValueData.update({
	"versionMinor"							: dict(type=int, valueValidator=genericNonNegativeIntValidator),
	"unitsPerEm"							: dict(type=(int, float), valueValidator=genericNonNegativeNumberValidator),
	"openTypeHeadLowestRecPPEM"				: dict(type=int, valueValidator=genericNonNegativeNumberValidator),
	"openTypeHheaAscender"					: dict(type=int),
	"openTypeHheaDescender"					: dict(type=int),
	"openTypeHheaLineGap"					: dict(type=int),
	"openTypeHheaCaretOffset"				: dict(type=int),
	"openTypeOS2Panose"						: dict(type="integerList", valueValidator=fontInfoVersion3OpenTypeOS2PanoseValidator),
	"openTypeOS2TypoAscender"				: dict(type=int),
	"openTypeOS2TypoDescender"				: dict(type=int),
	"openTypeOS2TypoLineGap"				: dict(type=int),
	"openTypeOS2WinAscent"					: dict(type=int, valueValidator=genericNonNegativeNumberValidator),
	"openTypeOS2WinDescent"					: dict(type=int, valueValidator=genericNonNegativeNumberValidator),
	"openTypeOS2SubscriptXSize"				: dict(type=int),
	"openTypeOS2SubscriptYSize"				: dict(type=int),
	"openTypeOS2SubscriptXOffset"			: dict(type=int),
	"openTypeOS2SubscriptYOffset"			: dict(type=int),
	"openTypeOS2SuperscriptXSize"			: dict(type=int),
	"openTypeOS2SuperscriptYSize"			: dict(type=int),
	"openTypeOS2SuperscriptXOffset"			: dict(type=int),
	"openTypeOS2SuperscriptYOffset"			: dict(type=int),
	"openTypeOS2StrikeoutSize"				: dict(type=int),
	"openTypeOS2StrikeoutPosition"			: dict(type=int),
	"openTypeGaspRangeRecords"				: dict(type="dictList", valueValidator=fontInfoOpenTypeGaspRangeRecordsValidator),
	"openTypeNameRecords"					: dict(type="dictList", valueValidator=fontInfoOpenTypeNameRecordsValidator),
	"openTypeVheaVertTypoAscender"			: dict(type=int),
	"openTypeVheaVertTypoDescender"			: dict(type=int),
	"openTypeVheaVertTypoLineGap"			: dict(type=int),
	"openTypeVheaCaretOffset"				: dict(type=int),
	"woffMajorVersion"						: dict(type=int, valueValidator=genericNonNegativeIntValidator),
	"woffMinorVersion"						: dict(type=int, valueValidator=genericNonNegativeIntValidator),
	"woffMetadataUniqueID"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataUniqueIDValidator),
	"woffMetadataVendor"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataVendorValidator),
	"woffMetadataCredits"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataCreditsValidator),
	"woffMetadataDescription"				: dict(type=dict, valueValidator=fontInfoWOFFMetadataDescriptionValidator),
	"woffMetadataLicense"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataLicenseValidator),
	"woffMetadataCopyright"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataCopyrightValidator),
	"woffMetadataTrademark"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataTrademarkValidator),
	"woffMetadataLicensee"					: dict(type=dict, valueValidator=fontInfoWOFFMetadataLicenseeValidator),
	"woffMetadataExtensions"				: dict(type=list, valueValidator=fontInfoWOFFMetadataExtensionsValidator),
	"guidelines"							: dict(type=list, valueValidator=guidelinesValidator)
})
fontInfoAttributesVersion3 = set(fontInfoAttributesVersion3ValueData.keys())

# insert the type validator for all attrs that
# have no defined validator.
for attr, dataDict in list(fontInfoAttributesVersion2ValueData.items()):
	if "valueValidator" not in dataDict:
		dataDict["valueValidator"] = genericTypeValidator

for attr, dataDict in list(fontInfoAttributesVersion3ValueData.items()):
	if "valueValidator" not in dataDict:
		dataDict["valueValidator"] = genericTypeValidator

# Version Conversion Support
# These are used from converting from version 1
# to version 2 or vice-versa.

def _flipDict(d):
	flipped = {}
	for key, value in list(d.items()):
		flipped[value] = key
	return flipped

fontInfoAttributesVersion1To2 = {
	"menuName"		: "styleMapFamilyName",
	"designer"		: "openTypeNameDesigner",
	"designerURL"	: "openTypeNameDesignerURL",
	"createdBy"		: "openTypeNameManufacturer",
	"vendorURL"		: "openTypeNameManufacturerURL",
	"license"		: "openTypeNameLicense",
	"licenseURL"	: "openTypeNameLicenseURL",
	"ttVersion"		: "openTypeNameVersion",
	"ttUniqueID"	: "openTypeNameUniqueID",
	"notice"		: "openTypeNameDescription",
	"otFamilyName"	: "openTypeNamePreferredFamilyName",
	"otStyleName"	: "openTypeNamePreferredSubfamilyName",
	"otMacName"		: "openTypeNameCompatibleFullName",
	"weightName"	: "postscriptWeightName",
	"weightValue"	: "openTypeOS2WeightClass",
	"ttVendor"		: "openTypeOS2VendorID",
	"uniqueID"		: "postscriptUniqueID",
	"fontName"		: "postscriptFontName",
	"fondID"		: "macintoshFONDFamilyID",
	"fondName"		: "macintoshFONDName",
	"defaultWidth"	: "postscriptDefaultWidthX",
	"slantAngle"	: "postscriptSlantAngle",
	"fullName"		: "postscriptFullName",
	# require special value conversion
	"fontStyle"		: "styleMapStyleName",
	"widthName"		: "openTypeOS2WidthClass",
	"msCharSet"		: "postscriptWindowsCharacterSet"
}
fontInfoAttributesVersion2To1 = _flipDict(fontInfoAttributesVersion1To2)
deprecatedFontInfoAttributesVersion2 = set(fontInfoAttributesVersion1To2.keys())

_fontStyle1To2 = {
	64 : "regular",
	1  : "italic",
	32 : "bold",
	33 : "bold italic"
}
_fontStyle2To1 = _flipDict(_fontStyle1To2)
# Some UFO 1 files have 0
_fontStyle1To2[0] = "regular"

_widthName1To2 = {
	"Ultra-condensed" : 1,
	"Extra-condensed" : 2,
	"Condensed"		  : 3,
	"Semi-condensed"  : 4,
	"Medium (normal)" : 5,
	"Semi-expanded"	  : 6,
	"Expanded"		  : 7,
	"Extra-expanded"  : 8,
	"Ultra-expanded"  : 9
}
_widthName2To1 = _flipDict(_widthName1To2)
# FontLab's default width value is "Normal".
# Many format version 1 UFOs will have this.
_widthName1To2["Normal"] = 5
# FontLab has an "All" width value. In UFO 1
# move this up to "Normal".
_widthName1To2["All"] = 5
# "medium" appears in a lot of UFO 1 files.
_widthName1To2["medium"] = 5
# "Medium" appears in a lot of UFO 1 files.
_widthName1To2["Medium"] = 5

_msCharSet1To2 = {
	0	: 1,
	1	: 2,
	2	: 3,
	77	: 4,
	128 : 5,
	129 : 6,
	130 : 7,
	134 : 8,
	136 : 9,
	161 : 10,
	162 : 11,
	163 : 12,
	177 : 13,
	178 : 14,
	186 : 15,
	200 : 16,
	204 : 17,
	222 : 18,
	238 : 19,
	255 : 20
}
_msCharSet2To1 = _flipDict(_msCharSet1To2)

# 1 <-> 2

def convertFontInfoValueForAttributeFromVersion1ToVersion2(attr, value):
	"""
	Convert value from version 1 to version 2 format.
	Returns the new attribute name and the converted value.
	If the value is None, None will be returned for the new value.
	"""
	# convert floats to ints if possible
	if isinstance(value, float):
		if int(value) == value:
			value = int(value)
	if value is not None:
		if attr == "fontStyle":
			v = _fontStyle1To2.get(value)
			if v is None:
				raise UFOLibError("Cannot convert value (%s) for attribute %s." % (repr(value), attr))
			value = v
		elif attr == "widthName":
			v = _widthName1To2.get(value)
			if v is None:
				raise UFOLibError("Cannot convert value (%s) for attribute %s." % (repr(value), attr))
			value = v
		elif attr == "msCharSet":
			v = _msCharSet1To2.get(value)
			if v is None:
				raise UFOLibError("Cannot convert value (%s) for attribute %s." % (repr(value), attr))
			value = v
	attr = fontInfoAttributesVersion1To2.get(attr, attr)
	return attr, value

def convertFontInfoValueForAttributeFromVersion2ToVersion1(attr, value):
	"""
	Convert value from version 2 to version 1 format.
	Returns the new attribute name and the converted value.
	If the value is None, None will be returned for the new value.
	"""
	if value is not None:
		if attr == "styleMapStyleName":
			value = _fontStyle2To1.get(value)
		elif attr == "openTypeOS2WidthClass":
			value = _widthName2To1.get(value)
		elif attr == "postscriptWindowsCharacterSet":
			value = _msCharSet2To1.get(value)
	attr = fontInfoAttributesVersion2To1.get(attr, attr)
	return attr, value

def _convertFontInfoDataVersion1ToVersion2(data):
	converted = {}
	for attr, value in list(data.items()):
		# FontLab gives -1 for the weightValue
		# for fonts wil no defined value. Many
		# format version 1 UFOs will have this.
		if attr == "weightValue" and value == -1:
			continue
		newAttr, newValue = convertFontInfoValueForAttributeFromVersion1ToVersion2(attr, value)
		# skip if the attribute is not part of version 2
		if newAttr not in fontInfoAttributesVersion2:
			continue
		# catch values that can't be converted
		if value is None:
			raise UFOLibError("Cannot convert value (%s) for attribute %s." % (repr(value), newAttr))
		# store
		converted[newAttr] = newValue
	return converted

def _convertFontInfoDataVersion2ToVersion1(data):
	converted = {}
	for attr, value in list(data.items()):
		newAttr, newValue = convertFontInfoValueForAttributeFromVersion2ToVersion1(attr, value)
		# only take attributes that are registered for version 1
		if newAttr not in fontInfoAttributesVersion1:
			continue
		# catch values that can't be converted
		if value is None:
			raise UFOLibError("Cannot convert value (%s) for attribute %s." % (repr(value), newAttr))
		# store
		converted[newAttr] = newValue
	return converted

# 2 <-> 3

_ufo2To3NonNegativeInt = set((
	"versionMinor",
	"openTypeHeadLowestRecPPEM",
	"openTypeOS2WinAscent",
	"openTypeOS2WinDescent"
))
_ufo2To3NonNegativeIntOrFloat = set((
	"unitsPerEm"
))
_ufo2To3FloatToInt = set(((
	"openTypeHeadLowestRecPPEM",
	"openTypeHheaAscender",
	"openTypeHheaDescender",
	"openTypeHheaLineGap",
	"openTypeHheaCaretOffset",
	"openTypeOS2TypoAscender",
	"openTypeOS2TypoDescender",
	"openTypeOS2TypoLineGap",
	"openTypeOS2WinAscent",
	"openTypeOS2WinDescent",
	"openTypeOS2SubscriptXSize",
	"openTypeOS2SubscriptYSize",
	"openTypeOS2SubscriptXOffset",
	"openTypeOS2SubscriptYOffset",
	"openTypeOS2SuperscriptXSize",
	"openTypeOS2SuperscriptYSize",
	"openTypeOS2SuperscriptXOffset",
	"openTypeOS2SuperscriptYOffset",
	"openTypeOS2StrikeoutSize",
	"openTypeOS2StrikeoutPosition",
	"openTypeVheaVertTypoAscender",
	"openTypeVheaVertTypoDescender",
	"openTypeVheaVertTypoLineGap",
	"openTypeVheaCaretOffset"
)))

def convertFontInfoValueForAttributeFromVersion2ToVersion3(attr, value):
	"""
	Convert value from version 2 to version 3 format.
	Returns the new attribute name and the converted value.
	If the value is None, None will be returned for the new value.
	"""
	if attr in _ufo2To3FloatToInt:
		try:
			v = int(round(value))
		except (ValueError, TypeError):
			raise UFOLibError("Could not convert value for %s." % attr)
		if v != value:
			value = v
	if attr in _ufo2To3NonNegativeInt:
		try:
			v = int(abs(value))
		except (ValueError, TypeError):
			raise UFOLibError("Could not convert value for %s." % attr)
		if v != value:
			value = v
	elif attr in _ufo2To3NonNegativeIntOrFloat:
		try:
			v = float(abs(value))
		except (ValueError, TypeError):
			raise UFOLibError("Could not convert value for %s." % attr)
		if v == int(v):
			v = int(v)
		if v != value:
			value = v
	return attr, value

def convertFontInfoValueForAttributeFromVersion3ToVersion2(attr, value):
	"""
	Convert value from version 3 to version 2 format.
	Returns the new attribute name and the converted value.
	If the value is None, None will be returned for the new value.
	"""
	return attr, value

def _convertFontInfoDataVersion3ToVersion2(data):
	converted = {}
	for attr, value in list(data.items()):
		newAttr, newValue = convertFontInfoValueForAttributeFromVersion3ToVersion2(attr, value)
		if newAttr not in fontInfoAttributesVersion2:
			continue
		converted[newAttr] = newValue
	return converted

def _convertFontInfoDataVersion2ToVersion3(data):
	converted = {}
	for attr, value in list(data.items()):
		attr, value = convertFontInfoValueForAttributeFromVersion2ToVersion3(attr, value)
		converted[attr] = value
	return converted

if __name__ == "__main__":
	import doctest
	doctest.testmod()
