1#!/usr/bin/env python
2# coding:utf-8
3# Author:  mozman -- <mozman@gmx.at>
4# Purpose: build header var tables
5# Created: 12.03.2011
6# Copyright (C) 2011, Manfred Moitzi
7# License: MIT License
8from collections import OrderedDict
9from pathlib import Path
10from ezdxf.lldxf.loader import load_dxf_structure
11
12TABLEPRELUDE = """# auto-generated by buildheadertables.py - do not edit
13# Copyright (C) 2019, Manfred Moitzi
14# License: MIT License
15from functools import partial
16from ezdxf.lldxf.hdrvars import SingleValue, Point2D, Point3D, HeaderVarDef
17from ezdxf.lldxf.const import DXF12, DXF2000, DXF2004, DXF2007, DXF2010, DXF2013, DXF2018
18
19HEADER_VAR_MAP = {
20"""
21TABLEEPILOGUE = "}\n"
22DXF_FILES = ['DXF12', 'DXF2000', 'DXF2004', 'DXF2007', 'DXF2010', 'DXF2013', 'DXF2018']
23TEMPLATES = Path(r'D:\Source\dxftest\templates')
24
25
26def write_table(filename, vars):
27    def write_var(var):
28        value = var.value
29        if isinstance(value, tuple):
30            if len(value) == 2:
31                factory = "Point2D"
32            else:
33                factory = "Point3D"
34        else:
35            factory = "partial(SingleValue, code=%d)" % var.code
36        if isinstance(value, str):
37            default = "'{}'".format(value)
38        else:
39            default = value
40        fp.write(
41            "    '{v.name}': HeaderVarDef(\n"
42            "        name='{v.name}',\n"
43            "        code={v.code},\n"
44            "        factory={f}, \n"
45            "        mindxf={v.mindxf},\n"
46            "        maxdxf={v.maxdxf},\n"
47            "        priority={v.priority},\n"
48            "        default={default}),\n".format(v=var, f=factory, default=default))
49
50    with open(filename, 'wt') as fp:
51        fp.write(TABLEPRELUDE)
52        for var in vars:
53            write_var(var)
54        fp.write(TABLEEPILOGUE)
55
56
57class HeaderVar:
58    def __init__(self, name, code, value, priority, dxf):
59        self.name = name
60        self.code = code
61        self.value = value
62        self.priority = priority
63        self.mindxf = dxf
64        self.maxdxf = dxf
65
66    def set_dxf(self, dxf):
67        if self.mindxf:
68            if dxf < self.mindxf:
69                self.mindxf = dxf
70        else:
71            self.mindxf = dxf
72
73        if self.maxdxf:
74            if dxf > self.maxdxf:
75                self.maxdxf = dxf
76        else:
77            self.maxdxf = dxf
78
79
80def add_vars(header, vars, dxf):
81    priority = 0
82    for name_tag, value_tag in zip(header[::2], header[1::2]):
83        name = name_tag.value
84        code = value_tag.code
85        value = value_tag.value
86        h = vars.get(name, None)
87        if h:
88            h.set_dxf(dxf)
89        else:
90            vars[name] = HeaderVar(name, code, value, priority, dxf)
91        priority += 100
92
93
94def read(stream):
95    """ Open an existing drawing. """
96    from ezdxf.lldxf.tagger import ascii_tags_loader, tag_compiler
97
98    tagger = list(ascii_tags_loader(stream))
99    return tag_compiler(iter(tagger))
100
101
102def get_tagger(filename):
103    from ezdxf.lldxf.validator import is_dxf_file
104    from ezdxf.filemanagement import dxf_file_info
105    if not is_dxf_file(filename):
106        raise IOError("File '{}' is not a DXF file.".format(filename))
107
108    info = dxf_file_info(filename)
109    with open(filename, mode='rt', encoding=info.encoding, errors='ignore') as fp:
110        tagger = read(fp)
111    return tagger
112
113
114def get_header_section(filename):
115    tagger = list(get_tagger(filename))
116    sections = load_dxf_structure(tagger)
117    return sections.get('HEADER', [None])[0]  # all tags in the first DXF structure entity
118
119
120def main():
121    header_vars = OrderedDict()
122    for dxf in reversed(DXF_FILES):
123        header = get_header_section(TEMPLATES / f'{dxf}.dxf')
124        add_vars(header[2:], header_vars, dxf)
125    write_table(TEMPLATES / 'headervars.py', sorted(header_vars.values(), key=lambda v: v.priority))
126
127
128if __name__ == '__main__':
129    main()
130