def run(args): for filename in args.files: if not Path(filename).exists(): print(f'File "{filename}" not found.') continue if is_binary_dxf_file(filename): binary_dxf = True else: binary_dxf = False if not is_dxf_file(filename): print(f'File "{filename}" is not a DXF file.') continue if args.raw: html_path = raw_pretty_print( Path(filename), compile_tags=not args.nocompile, legacy_mode=args.legacy, is_binary_dxf=binary_dxf, ) else: html_path = pretty_print( Path(filename), is_binary_dxf=binary_dxf) # legacy mode is always used print(f'Created "{html_path}"') if args.open: webbrowser.open(str(html_path))
def load_every_document(filename: str): def io_error() -> str: msg = f'Not a DXF file or a generic I/O error: "{filename}"' print(msg, file=sys.stderr) return msg def structure_error() -> str: msg = f'Invalid or corrupted DXF file: "{filename}"' print(msg, file=sys.stderr) return msg binary_fmt = False if is_binary_dxf_file(filename): try: doc = ezdxf.readfile(filename) except IOError: raise const.DXFLoadError(io_error()) except const.DXFStructureError: raise const.DXFLoadError(structure_error()) auditor = doc.audit() binary_fmt = True else: try: doc, auditor = recover.readfile(filename) except IOError: raise const.DXFLoadError(io_error()) except const.DXFStructureError: raise const.DXFLoadError(structure_error()) return doc, auditor, binary_fmt
def readfile(filename: str, encoding: str = None, legacy_mode: bool = False, filter_stack=None) -> 'Drawing': """ Read DXF document specified by `filename` from file-system. This is the preferred method to open existing ASCII or Binary DXF files. Read the DXF drawing from the file-system with auto-detection of encoding for ASCII DXF files. Decoding errors will be ignored. Override encoding detection by setting argument `encoding` to the estimated encoding. (use Python encoding names like in the :func:`open` function). If argument `legacy_mode` is ``True``, `ezdxf` tries to reorder the coordinates of the LINE entity in files from CAD applications which wrote the coordinates in the order: x1, x2, y1, y2. Additional fixes may be added later. The legacy mode has a speed penalty of around 5%. .. hint:: Try argument :code:`legacy_mode=True` if error ``'Missing required y coordinate near line: ...'`` occurs. Args: filename: filename of ASCII or Binary DXF document encoding: use ``None`` for auto detect (default), or set a specific encoding like ``'utf-8'``, ignored for Binary DXF files legacy_mode: adds an extra trouble shooting import layer if ``True`` filter_stack: interface to put filters between reading layers Raises: IOError: File `filename` is not a DXF file or does not exist. DXFStructureError: for invalid DXF structure """ # for argument filter_stack see :class:`~ezdxf.drawing.Drawing.read` for more information from ezdxf.lldxf.validator import is_dxf_file, is_binary_dxf_file from ezdxf.tools.codepage import is_supported_encoding from ezdxf.lldxf.tagger import binary_tags_loader if is_binary_dxf_file(filename): with open(filename, 'rb') as fp: data = fp.read() loader = binary_tags_loader(data) return Drawing.load(loader, legacy_mode, filter_stack) if not is_dxf_file(filename): raise IOError("File '{}' is not a DXF file.".format(filename)) info = dxf_file_info(filename) if encoding is not None: # override default encodings if absolute necessary info.encoding = encoding with open(filename, mode='rt', encoding=info.encoding, errors='ignore') as fp: doc = read(fp, legacy_mode=legacy_mode, filter_stack=filter_stack) doc.filename = filename if encoding is not None and is_supported_encoding(encoding): # store overridden encoding if supported by AutoCAD, else default encoding stored in $DWGENCODING is used # as document encoding or 'cp1252' if $DWGENCODING is unset. doc.encoding = encoding return doc
def readfile(filename: str, version: str = None, audit=False) -> Optional[Drawing]: """ Use an installed `ODA File Converter`_ to convert a DWG/DXB/DXF file into a temporary DXF file and load this file by `ezdxf`. Args: filename: file to load by ODA File Converter version: load file as specific DXF version, by default the same version as the source file or if not detectable the latest by `ezdxf` supported version. audit: audit source file before loading """ infile = Path(filename).absolute() if not infile.exists(): raise FileNotFoundError(f"No such file or directory: '{infile}'") in_folder = infile.parent name = infile.name ext = infile.suffix.lower() tmp_folder = Path(temp_path).absolute() if not tmp_folder.exists(): tmp_folder.mkdir() dxf_temp_file = (tmp_folder / name).with_suffix('.dxf') _version = 'ACAD2018' if ext == '.dxf': if is_binary_dxf_file(str(infile)): pass elif is_dxf_file(str(infile)): with open(filename, 'rt') as fp: info = dxf_info(fp) _version = VERSION_MAP[info.version] elif ext == '.dwg': _version = dwg_version(str(infile)) if _version is None: raise ValueError('Unknown or unsupported DWG version.') else: raise ValueError(f"Unsupported file format: '{ext}'") if version is None: version = _version version = map_version(version) cmd = _odafc_cmd(name, str(in_folder), str(tmp_folder), fmt='DXF', version=version, audit=audit) _execute_odafc(cmd) if dxf_temp_file.exists(): doc = ezdxf.readfile(str(dxf_temp_file)) dxf_temp_file.unlink() doc.filename = infile.with_suffix('.dxf') return doc return None
def get_tag_loader( filename: Union[str, Path], errors: str = "ignore" ) -> Iterable[DXFTag]: filename = str(filename) if is_binary_dxf_file(filename): with open(filename, "rb") as fp: data = fp.read() return binary_tags_loader(data, errors=errors) if not is_dxf_file(filename): raise IOError(f"File '{filename}' is not a DXF file.") info = dxf_file_info(filename) with open(filename, mode="rt", encoding=info.encoding, errors=errors) as fp: # type: ignore return list(ascii_tags_loader(fp, skip_comments=True)) # type: ignore
def _detect_version(path: str) -> str: version = 'ACAD2018' ext = os.path.splitext(path)[1].lower() if ext == '.dxf': if is_binary_dxf_file(path): pass elif is_dxf_file(path): with open(path, 'rt') as fp: info = dxf_info(fp) version = VERSION_MAP[info.version] elif ext == '.dwg': version = dwg_version(path) if version is None: raise ValueError('Unknown or unsupported DWG version.') else: raise ValueError(f"Unsupported file format: '{ext}'") return map_version(version)
def _detect_version(path: str) -> str: version = "ACAD2018" ext = os.path.splitext(path)[1].lower() if ext == ".dxf": if is_binary_dxf_file(path): pass elif is_dxf_file(path): with open(path, "rt") as fp: info = dxf_info(fp) version = VERSION_MAP[info.version] elif ext == ".dwg": version = dwg_version(path) # type: ignore if version is None: raise ValueError("Unknown or unsupported DWG version.") else: raise ValueError(f"Unsupported file format: '{ext}'") return map_version(version)
def main(): parser = argparse.ArgumentParser() parser.add_argument( 'files', metavar='FILE', nargs='+', help='DXF files pretty print', ) parser.add_argument( '-o', '--open', action='store_true', help='open generated HTML file with the default web browser', ) parser.add_argument( '-r', '--raw', action='store_true', help='raw mode - just print tags, no DXF structure interpretation', ) parser.add_argument( '-x', '--nocompile', action='store_true', help="don't compile points coordinates into single tags " "(only in raw mode)", ) parser.add_argument( '-l', '--legacy', action='store_true', help="legacy mode - reorders DXF point coordinates", ) parser.add_argument( '-s', '--sections', action='store', default='hctbeo', help="choose sections to include and their order, h=HEADER, c=CLASSES, " "t=TABLES, b=BLOCKS, e=ENTITIES, o=OBJECTS", ) args = parser.parse_args(sys.argv[1:]) options.compress_binary_data = True for filename in args.files: if not Path(filename).exists(): print(f"File '{filename}' not found.") continue if is_binary_dxf_file(filename): binary_dxf = True else: binary_dxf = False if not is_dxf_file(filename): print(f"File '{filename}' is not a DXF file.") continue if args.raw: html_path = raw_pretty_print(Path(filename), compile_tags=not args.nocompile, legacy_mode=args.legacy, is_binary_dxf=binary_dxf) else: html_path = pretty_print( Path(filename), is_binary_dxf=binary_dxf) # legacy mode is always used print(f"dxfpp created '{html_path}'") if args.open: webbrowser.open(str(html_path))
def readfile(filename: Union[str, 'Path'], encoding: str = None, errors: str = 'surrogateescape') -> 'Drawing': """ Read the DXF document `filename` from the file-system. This is the preferred method to load existing ASCII or Binary DXF files, the required text encoding will be detected automatically and decoding errors will be ignored. Override encoding detection by setting argument `encoding` to the estimated encoding. (use Python encoding names like in the :func:`open` function). If this function struggles to load the DXF document and raises a :class:`DXFStructureError` exception, try the :func:`ezdxf.recover.readfile` function to load this corrupt DXF document. Args: filename: filename of the ASCII- or Binary DXF document encoding: use ``None`` for auto detect (default), or set a specific encoding like "utf-8", argument is ignored for Binary DXF files errors: specify decoding error handler - "surrogateescape" to preserve possible binary data (default) - "ignore" to use the replacement char U+FFFD "\ufffd" for invalid data - "strict" to raise an :class:`UnicodeDecodeError` exception for invalid data Raises: IOError: not a DXF file or file does not exist DXFStructureError: for invalid or corrupted DXF structures UnicodeDecodeError: if `errors` is "strict" and a decoding error occurs .. deprecated:: v0.14 argument `legacy_mode`, use module :mod:`ezdxf.recover` to load DXF documents with structural flaws. """ from ezdxf.lldxf.validator import is_dxf_file, is_binary_dxf_file from ezdxf.tools.codepage import is_supported_encoding from ezdxf.lldxf.tagger import binary_tags_loader filename = str(filename) if is_binary_dxf_file(filename): with open(filename, 'rb') as fp: data = fp.read() loader = binary_tags_loader(data, errors=errors) return Drawing.load(loader) if not is_dxf_file(filename): raise IOError(f"File '{filename}' is not a DXF file.") info = dxf_file_info(filename) if encoding is not None: # override default encodings if absolute necessary info.encoding = encoding with open(filename, mode='rt', encoding=info.encoding, errors=errors) as fp: doc = read(fp) doc.filename = filename if encoding is not None and is_supported_encoding(encoding): # store overridden encoding if supported by AutoCAD, else default # encoding stored in $DWGENCODING is used as document encoding or # 'cp1252' if $DWGENCODING is unset. doc.encoding = encoding return doc
def readfile(filename: str, encoding: str = None, legacy_mode: bool = False) -> 'Drawing': """ Read the DXF document `filename` from the file-system. This is the preferred method to load existing ASCII or Binary DXF files, the required text encoding will be detected automatically and decoding errors will be ignored. Override encoding detection by setting argument `encoding` to the estimated encoding. (use Python encoding names like in the :func:`open` function). If this function struggles to load the DXF document and raises a :class:`DXFStructureError` exception, try the :func:`ezdxf.recover.readfile` function to load this corrupt DXF document. Args: filename: filename of the ASCII- or Binary DXF document encoding: use ``None`` for auto detect (default), or set a specific encoding like "utf-8", argument is ignored for Binary DXF files legacy_mode: adds an extra trouble shooting import layer if ``True`` (deprecated) Raises: IOError: File `filename` is not a DXF file or does not exist. DXFStructureError: for invalid DXF structure .. deprecated:: v0.14 argument `legacy_mode`, use module :mod:`ezdxf.recover` to load DXF documents with structural flaws. """ from ezdxf.lldxf.validator import is_dxf_file, is_binary_dxf_file from ezdxf.tools.codepage import is_supported_encoding from ezdxf.lldxf.tagger import binary_tags_loader if legacy_mode: warnings.warn( '"legacy_mode" is deprecated (removed in v0.16), replace call by ' 'ezdxf.recover.read().', DeprecationWarning) filename = str(filename) if is_binary_dxf_file(filename): with open(filename, 'rb') as fp: data = fp.read() loader = binary_tags_loader(data) return Drawing.load(loader, legacy_mode) if not is_dxf_file(filename): raise IOError("File '{}' is not a DXF file.".format(filename)) info = dxf_file_info(filename) if encoding is not None: # override default encodings if absolute necessary info.encoding = encoding with open(filename, mode='rt', encoding=info.encoding, errors='ignore') as fp: doc = read(fp, legacy_mode=legacy_mode) doc.filename = filename if encoding is not None and is_supported_encoding(encoding): # store overridden encoding if supported by AutoCAD, else default # encoding stored in $DWGENCODING is used as document encoding or # 'cp1252' if $DWGENCODING is unset. doc.encoding = encoding return doc