Merge fixes from branch 'xorn'
[geda-gaf.git] / xorn / src / command / convert.py
blob88bec79c7119b41199e39bb5a71376b8d00cdd9d
1 # Copyright (C) 2013-2020 Roland Lutz
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 import codecs, getopt, os, sys
18 from gettext import gettext as _
19 import xorn.command
20 import xorn.fileutils
21 import gaf.clib
22 import gaf.read
23 import gaf.write
24 import gaf.xmlread
25 import gaf.xmlwrite
27 def check_if_directory(path, option_name):
28 if os.path.isdir(path):
29 return
30 sys.stderr.write(_("%s: \"%s\" is not a directory (passed to %s)\n")
31 % (xorn.command.program_short_name, path, option_name))
32 sys.exit(1)
34 def main():
35 try:
36 options, args = getopt.getopt(
37 xorn.command.args, 'o:I:O:', [
38 'output-file=', 'input-format=', 'output-format=',
39 'symbol-library=', 'symbol-library-search=',
40 'symbol-library-command=', 'reset-symbol-library',
41 'omit-symbols', 'omit-pixmaps',
42 'enable-hybridnum', 'disable-hybridnum',
43 'help', 'version'])
44 except getopt.GetoptError as e:
45 xorn.command.invalid_arguments(e.msg)
47 input_file = None
48 output_file = None
49 input_format = None
50 output_format = None
52 omit_symbols = False
53 omit_pixmaps = False
55 use_hybridnum = False
57 for option, value in options:
58 if option == '-o' or option == '--output-file':
59 if output_file is not None:
60 xorn.command.invalid_arguments(
61 "option `-o' can only be given once")
62 output_file = value
63 elif option == '-I' or option == '--input-format':
64 if input_format is not None:
65 xorn.command.invalid_arguments(
66 "option `-I' can only be given once")
67 try:
68 input_format = gaf.fileformat.VALID_FORMATS[value]
69 except KeyError:
70 xorn.command.invalid_arguments(
71 "%s is not a valid format" % value)
72 elif option == '-O' or option == '--output-format':
73 if output_format is not None:
74 xorn.command.invalid_arguments(
75 "option `-O' can only be given once")
76 try:
77 output_format = gaf.fileformat.VALID_FORMATS[value]
78 except KeyError:
79 xorn.command.invalid_arguments(
80 "%s is not a valid format" % value)
82 # symbol library
84 elif option == '--symbol-library':
85 check_if_directory(value, option)
86 gaf.clib.add_source(
87 gaf.clib.DirectorySource(value, False),
88 gaf.clib.uniquify_source_name(os.path.basename(value)))
90 elif option == '--symbol-library-search':
91 check_if_directory(value, option)
92 gaf.clib.add_source(
93 gaf.clib.DirectorySource(value, True),
94 gaf.clib.uniquify_source_name(os.path.basename(value)))
96 elif option == '--symbol-library-command':
97 tokens = value.split(':')
98 if len(tokens) != 2:
99 sys.stderr.write(_("Invalid library command argument: %s\n"
100 "Must be 'list' and 'get' commands "
101 "separated by colons\n") % value)
102 sys.exit(1)
103 listcmd, getcmd = tokens
104 gaf.clib.add_source(
105 gaf.clib.CommandSource(listcmd, getcmd),
106 gaf.clib.uniquify_source_name('command source'))
108 elif option == '--reset-symbol-library':
109 gaf.clib.reset()
111 # omit symbols/pixmaps
113 elif option == '--omit-symbols':
114 omit_symbols = True
115 elif option == '--omit-pixmaps':
116 omit_pixmaps = True
118 # file format features
120 elif option == '--enable-hybridnum':
121 use_hybridnum = True
122 elif option == '--disable-hybridnum':
123 use_hybridnum = False
125 elif option == '--help':
126 sys.stdout.write(_(
127 "Usage: %s [OPTION]... INPUT-FILE [OUTPUT-FILE]\n"
128 " %s [OPTION]... [-o OUTPUT-FILE] [INPUT-FILE]\n")
129 % ((xorn.command.program_name, ) * 2))
130 sys.stdout.write(_(
131 "Convert files from one file format to another\n"))
132 sys.stdout.write("\n")
133 sys.stdout.write(_("""\
134 -o, --output-file=FILE write to FILE (can be `-' for stdout)
135 -I, --input-format=FORMAT input file format (optional if it can be
136 deduced from the input file name)
137 -O, --output-format=FORMAT output file format (optional if it can be
138 deduced from the output file name)
140 --symbol-library=PATH add PATH to the symbol library
141 --symbol-library-search=PATH add PATH and its subdirectories to the symbol
142 library
143 --symbol-library-command=LISTCMD:GETCMD
144 add the source commands LISTCMD and GETCMD to
145 the symbol library
146 --reset-symbol-library clear all previous symbol library sources
148 --omit-symbols don't include referenced symbols in the output
149 --omit-pixmaps don't include referenced pixmaps in the output
151 --enable-hybridnum enable/disable use of hybrid number format
152 --disable-hybridnum
153 """))
154 sys.stdout.write("\n")
155 sys.stdout.write(_("Valid formats are: %s\n") %
156 ', '.join(sorted(gaf.fileformat.VALID_FORMATS)))
157 sys.stdout.write("\n")
158 sys.stdout.write(_(
159 "Both input and output filename can be `-' for the standard input or output,\n"
160 "respectively. In this case, the corresponding format option is mandatory.\n"))
161 sys.stdout.write("\n")
162 sys.stdout.write(_("Report %s bugs to %s\n")
163 % (xorn.config.PACKAGE_NAME,
164 xorn.config.PACKAGE_BUGREPORT))
165 sys.exit(0)
166 elif option == '--version':
167 xorn.command.core_version()
169 if args:
170 input_file = args[0]
171 if len(args) > 1:
172 if output_file is not None:
173 xorn.command.invalid_arguments(
174 "output file name specified more than once")
175 output_file = args[1]
176 if len(args) > 2:
177 xorn.command.invalid_arguments("too many arguments")
179 if input_file is None:
180 input_file = '-'
181 if output_file is None:
182 output_file = '-'
184 if input_format is None:
185 if input_file == '-':
186 xorn.command.invalid_arguments(
187 "Input format must be specified when reading from stdin.")
188 try:
189 input_format = gaf.fileformat.guess_format(input_file)
190 except gaf.fileformat.UnknownFormatError:
191 sys.stderr.write(_(
192 "%s: Input format could not be deduced from input file name.\n"
193 "%s: Please specify an input format using `-I FORMAT'.\n")
194 % ((xorn.command.program_short_name, ) * 2))
195 sys.exit(1)
197 if output_format is None:
198 if output_file == '-':
199 xorn.command.invalid_arguments(
200 "Output format must be specified when reading from stdin.")
201 try:
202 output_format = gaf.fileformat.guess_format(output_file)
203 except gaf.fileformat.UnknownFormatError:
204 sys.stderr.write(_(
205 "%s: Output format could not be deduced from output file name.\n"
206 "%s: Please specify an output format using `-O FORMAT'.\n")
207 % ((xorn.command.program_short_name, ) * 2))
208 sys.exit(1)
210 # read revision from input file
212 output_format_is_xml = output_format in (
213 gaf.fileformat.FORMAT_SYM_XML,
214 gaf.fileformat.FORMAT_SCH_XML)
215 load_symbols = output_format_is_xml and not omit_symbols
216 load_pixmaps = output_format_is_xml and not omit_pixmaps
217 gaf.clib.load_pixmaps = load_pixmaps
219 try:
220 if input_file == '-':
221 input_file = '<stdin>'
222 rev = gaf.read.read_file(sys.stdin, '<stdin>', input_format,
223 load_symbols = load_symbols,
224 load_pixmaps = load_pixmaps)
225 else:
226 rev = gaf.read.read(input_file, input_format,
227 load_symbols = load_symbols,
228 load_pixmaps = load_pixmaps)
229 except IOError as e:
230 sys.stderr.write(_("%s: %s: %s\n")
231 % (xorn.command.program_short_name,
232 input_file, e.strerror))
233 sys.exit(1)
234 except UnicodeDecodeError as e:
235 sys.stderr.write(_("%s: %s: %s\n")
236 % (xorn.command.program_short_name,
237 input_file, str(e)))
238 sys.exit(1)
239 except gaf.read.ParseError:
240 sys.exit(1)
242 # write revision to output file
244 if output_format == gaf.fileformat.FORMAT_SYM_XML or \
245 output_format == gaf.fileformat.FORMAT_SCH_XML:
246 kwds = { 'use_hybridnum': use_hybridnum,
247 'omit_symbols': omit_symbols,
248 'omit_pixmaps': omit_pixmaps }
249 else:
250 kwds = {}
252 try:
253 if output_file == '-':
254 output_file = '<stdout>'
255 gaf.write.write_file(sys.stdout, rev, output_format, **kwds)
256 else:
257 gaf.write.write(rev, output_file, output_format,
258 { 'backup': False, 'fsync': False }, **kwds)
259 except IOError as e:
260 sys.stderr.write(_("%s: %s: %s\n")
261 % (xorn.command.program_short_name,
262 output_file, e.strerror))
263 sys.exit(1)