DJ デミオ エアコン故障
去年の夏、エアコンが故障し、助手席側から暑い空気しか出なくなった。 運転手側はわずかに涼しい風が出てる。 30度超えると、車内は冷えなくなる。
冬は、特に気にならなかった。
定期点検にだしたところ、コンデンサーの故障ということになった。 一週間、代車をもらって、修理した。
今回は、メーカー保証になったので、修理費はかからなかった。
plistlib.dump(obj, fp)
defcon/object/font.py def save( self, path=None, formatVersion=None, removeUnreferencedImages=False, progressBar=None, structure=None, ): """ Save the font to **path**. If path is None, the path from the last save or when the font was first opened will be used. The UFO will be saved using the format found at ``ufoFormatVersion``. This value is either the format version from the exising UFO or the format version specified in a previous save. If neither of these is available, the UFO will be written as format version 3. If you wish to specifiy the format version for saving, pass the desired number as the **formatVersion** argument. Optionally, the UFO can be purged of unreferenced images during this operation. To do this, pass ``True`` as the value for the removeUnreferencedImages argument. 'structure' can be either None, "zip" or "package". If it's None, the destination UFO will use the same structure as original, provided that is compatible with any previous UFO at the output path. If 'structure' is "zip" the UFO will be saved as compressed archive, else it is saved as a regular folder or "package". """ isNewFont = self._path is None if path is None: if isNewFont: from defcon.errors import DefconError raise DefconError("Can't save new font without a 'path'") # saving in-place to the same original path path = self._path saveAs = False else: if not isinstance(path, basestring) and not hasattr(path, "__fspath__"): raise TypeError( "invalid path: expected string or os.PathLike, found %s" % type(path).__name__ ) if isNewFont: # saving a new font is always a 'saveAs' operation saveAs = True else: # 'saveAs' if source and destination path are different saveAs = not samepath(self._path, path) # validate 'structure' argument if structure is not None: try: structure = UFOFileStructure(structure) except ValueError: from defcon.errors import DefconError raise DefconError( "'%s' is not a valid UFOFileStructure; choose between %s" % (structure, tuple(e.value for e in UFOFileStructure)) ) elif self._ufoFileStructure is not None: # if structure is None, fall back to the same as when first loaded structure = self._ufoFileStructure else: # if both None, default to "package" structure structure = UFOFileStructure.PACKAGE # if destination is an existing path, ensure matches the desired structure isExistingOSPath = os.path.exists(path) if isExistingOSPath: try: with UFOReader(path, validate=True) as reader: existingStructure = reader.fileStructure except UFOLibError: # destination is an existing file but not a valid UFO, we'll # silently overwrite it. Perhaps we should blow up... saveAs = True if not saveAs and structure and structure is not existingStructure: from defcon.errors import DefconError raise DefconError( "Can't save font in-place with a different structure; " "expected %s, got %s" % (existingStructure.value, structure.value) ) # sanity checks on layer data before doing anything destructive assert self.layers.defaultLayer is not None if self.layers.defaultLayer.name != "public.default": assert "public.default" not in self.layers.layerOrder ## work out the format version # if None is given, fallback to the one that # came in when the UFO was loaded if formatVersion is None and self._ufoFormatVersion is not None: formatVersion = self._ufoFormatVersion # otherwise fallback to 3 elif formatVersion is None: formatVersion = 3 # if down-converting in-place or "saving as" to a pre-existing path, # we first write to a temporary folder, then move to destination overwritePath = None if ((not saveAs and formatVersion != self._ufoFormatVersion) or (saveAs and isExistingOSPath)): saveAs = True overwritePath = path path = os.path.join(tempfile.mkdtemp(), "temp.ufo") try: # make a UFOWriter try: writer = UFOWriter( path, formatVersion=formatVersion, validate=self.ufoLibWriteValidate, structure=structure, ) except UFOLibError: if overwritePath is None and isExistingOSPath: logger.exception("Invalid ufo found '%s', the existing ufo " "will be removed. Save will be handled as " "save-as.", path) saveAs = True overwritePath = path path = os.path.join(tempfile.mkdtemp(), "temp.ufo") writer = UFOWriter( path, formatVersion=formatVersion, validate=self.ufoLibWriteValidate, structure=structure, ) else: raise # if changing ufo format versions, flag all objects # as dirty so that they will be saved if self._ufoFormatVersion != formatVersion: self.info.dirty = True self.groups.dirty = True self.kerning.dirty = True self.lib.dirty = True if formatVersion > 1: self.features.dirty = True # set the kerning group remap if necessary if formatVersion < 3 and self._kerningGroupConversionRenameMaps is not None: writer.setKerningGroupConversionRenameMaps(self._kerningGroupConversionRenameMaps) # save the objects self._saveInfo(writer=writer, saveAs=saveAs, progressBar=progressBar) <==========ここ self._saveGroups(writer=writer, saveAs=saveAs, progressBar=progressBar) # Note: the outgoing kerning data has not been validated. # Gremlins may be sneaking out through here. self._saveKerning(writer=writer, saveAs=saveAs, progressBar=progressBar) self._saveLib(writer=writer, saveAs=saveAs, progressBar=progressBar) if formatVersion >= 2: self._saveFeatures(writer=writer, saveAs=saveAs, progressBar=progressBar) if formatVersion >= 3: self.saveImages(writer=writer, removeUnreferencedImages=removeUnreferencedImages, saveAs=saveAs, progressBar=progressBar) self.saveData(writer=writer, saveAs=saveAs, progressBar=progressBar) self.layers.save(writer, saveAs=saveAs, progressBar=progressBar) # we must close the writer's filesystem to actually create the zip; # Note that calling writer.close() makes all the SubFS instances # derived from it unusable if writer.fileStructure is UFOFileStructure.ZIP: writer.close() writer.setModificationTime() if overwritePath is not None: if os.path.isfile(overwritePath): os.remove(overwritePath) elif os.path.isdir(overwritePath): shutil.rmtree(overwritePath) shutil.move(path, overwritePath) finally: # if down converting in place or overwriting, handle the temp if overwritePath is not None: shutil.rmtree(os.path.dirname(path)) path = overwritePath # done self._path = path self._ufoFormatVersion = formatVersion self._ufoFileStructure = writer.fileStructure self.dirty = False
defcon/object/font.py def _saveInfo(self, writer, saveAs=False, progressBar=None): # info should always be saved if progressBar is not None: progressBar.update(text="Saving info...", increment=0) self.saveInfo(writer) <=====ここ self.info.dirty = False self._stampInfoDataState(writer) if progressBar is not None: progressBar.update()
defcon/object/font.py def saveInfo(self, writer): """ Save info. This method should not be called externally. Subclasses may override this method to implement custom saving behavior. """ writer.writeInfo(self.info, validate=self.info.ufoLibWriteValidate) <===ここ
fontTools/ufolib/__init__.py 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) <=====ここ
fontTools/ufolib/__init__.py class UFOWriter(UFOReader): 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, str): # 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 = str(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() <==============ここの中へ
fontTools/ufolib/__init__.py # metainfo.plist def _writeMetaInfo(self): metaInfo = dict( creator=self._fileCreator, formatVersion=self._formatVersion ) self._writePlist(METAINFO_FILENAME, metaInfo)
fontTools/ufolib/__init__.py class _UFOBaseIO: def getFileModificationTime(self, path): def _getPlist(self, fileName, default=None): 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) )
fontTools/misc/plistlib.py def dump( value, fp, sort_keys=True, skipkeys=False, use_builtin_types=None, pretty_print=True, ): if not hasattr(fp, "write"): raise AttributeError( "'%s' object has no attribute 'write'" % type(fp).__name__ ) root = etree.Element("plist", version="1.0") el = totree( value, sort_keys=sort_keys, skipkeys=skipkeys, use_builtin_types=use_builtin_types, pretty_print=pretty_print, ) root.append(el) tree = etree.ElementTree(root) # we write the doctype ourselves instead of using the 'doctype' argument # of 'write' method, becuse lxml will force adding a '\n' even when # pretty_print is False. if pretty_print: header = b"\n".join((XML_DECLARATION, PLIST_DOCTYPE, b"")) else: header = XML_DECLARATION + PLIST_DOCTYPE fp.write(header) tree.write( fp, encoding="utf-8", pretty_print=pretty_print, xml_declaration=False )
ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters
import defcon import extractor ufo = defcon.Font() extractor.extractUFO("./font.otf", ufo) ufo.save("./font_otf.ufo")
UnicodeかAscii以外の文字があるから、エラーなのかな?
myExtracotr2.py Traceback (most recent call last): File "fontTools\ufoLib\__init__.py", line 181, in _writePlist plistlib.dump(obj, fp) File "fontTools\misc\plistlib.py", line 472, in dump pretty_print=pretty_print, File "fontTools\misc\plistlib.py", line 409, in totree return _make_element(value, context) File "Python37_64\lib\functools.py", line 840, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "fontTools\misc\plistlib.py", line 323, in _dict_element el.append(_make_element(value, ctx)) File "Python37_64\lib\functools.py", line 840, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "fontTools\misc\plistlib.py", line 284, in _string_element el.text = value File "src\lxml\etree.pyx", line 1025, in lxml.etree._Element.text.__set__ File "src\lxml\apihelpers.pxi", line 734, in lxml.etree._setNodeText File "src\lxml\apihelpers.pxi", line 722, in lxml.etree._createTextNode File "src\lxml\apihelpers.pxi", line 1527, in lxml.etree._utf8 ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters
During handling of the above exception, another exception occurred: Traceback (most recent call last): File "myExtracotr2.py", line 7, in <module> ufo.save("./AP-OTF-A1GothicStd-Regular_otf.ufo") File "\defcon\objects\font.py", line 851, in save self._saveInfo(writer=writer, saveAs=saveAs, progressBar=progressBar) File "\defcon\objects\font.py", line 890, in _saveInfo self.saveInfo(writer) File "\defcon\objects\font.py", line 901, in saveInfo writer.writeInfo(self.info, validate=self.info.ufoLibWriteValidate) File "\fontTools\ufoLib\__init__.py", line 1215, in writeInfo self._writePlist(FONTINFO_FILENAME, infoData) File "\fontTools\ufoLib\__init__.py", line 186, in _writePlist % (fileName, self.fs, e) fontTools.ufoLib.errors.UFOLibError: 'fontinfo.plist' could not be written on <osfs 'font_otf.ufo'> because the data is not properly formatted: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters Process finished with exit code 1