1#############################################################################
2##
3## Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4##
5## This file is part of PyQt5.
6##
7## This file may be used under the terms of the GNU General Public License
8## version 3.0 as published by the Free Software Foundation and appearing in
9## the file LICENSE included in the packaging of this file.  Please review the
10## following information to ensure the GNU General Public License version 3.0
11## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12##
13## If you do not wish to use this file under the terms of the GPL version 3.0
14## then you may purchase a commercial license.  For more information contact
15## info@riverbankcomputing.com.
16##
17## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19##
20#############################################################################
21
22
23import sys
24import logging
25
26from . import compileUi, loadUi
27
28
29class Driver(object):
30    """ This encapsulates access to the pyuic functionality so that it can be
31    called by code that is Python v2/v3 specific.
32    """
33
34    LOGGER_NAME = 'PyQt5.uic'
35
36    def __init__(self, opts, ui_file):
37        """ Initialise the object.  opts is the parsed options.  ui_file is the
38        name of the .ui file.
39        """
40
41        if opts.debug:
42            logger = logging.getLogger(self.LOGGER_NAME)
43            handler = logging.StreamHandler()
44            handler.setFormatter(logging.Formatter("%(name)s: %(message)s"))
45            logger.addHandler(handler)
46            logger.setLevel(logging.DEBUG)
47
48        self._opts = opts
49        self._ui_file = ui_file
50
51    def invoke(self):
52        """ Invoke the action as specified by the parsed options.  Returns 0 if
53        there was no error.
54        """
55
56        if self._opts.preview:
57            return self._preview()
58
59        self._generate()
60
61        return 0
62
63    def _preview(self):
64        """ Preview the .ui file.  Return the exit status to be passed back to
65        the parent process.
66        """
67
68        from PyQt5 import QtWidgets
69
70        app = QtWidgets.QApplication([self._ui_file])
71        widget = loadUi(self._ui_file)
72        widget.show()
73
74        return app.exec_()
75
76    def _generate(self):
77        """ Generate the Python code. """
78
79        needs_close = False
80
81        if sys.hexversion >= 0x03000000:
82            if self._opts.output == '-':
83                from io import TextIOWrapper
84
85                pyfile = TextIOWrapper(sys.stdout.buffer, encoding='utf8')
86            else:
87                pyfile = open(self._opts.output, 'wt', encoding='utf8')
88                needs_close = True
89        else:
90            if self._opts.output == '-':
91                pyfile = sys.stdout
92            else:
93                pyfile = open(self._opts.output, 'wt')
94                needs_close = True
95
96        import_from = self._opts.import_from
97
98        if import_from:
99            from_imports = True
100        elif self._opts.from_imports:
101            from_imports = True
102            import_from = '.'
103        else:
104            from_imports = False
105
106        compileUi(self._ui_file, pyfile, self._opts.execute, self._opts.indent,
107                from_imports, self._opts.resource_suffix, import_from)
108
109        if needs_close:
110            pyfile.close()
111
112    def on_IOError(self, e):
113        """ Handle an IOError exception. """
114
115        sys.stderr.write("Error: %s: \"%s\"\n" % (e.strerror, e.filename))
116
117    def on_SyntaxError(self, e):
118        """ Handle a SyntaxError exception. """
119
120        sys.stderr.write("Error in input file: %s\n" % e)
121
122    def on_NoSuchClassError(self, e):
123        """ Handle a NoSuchClassError exception. """
124
125        sys.stderr.write(str(e) + "\n")
126
127    def on_NoSuchWidgetError(self, e):
128        """ Handle a NoSuchWidgetError exception. """
129
130        sys.stderr.write(str(e) + "\n")
131
132    def on_Exception(self, e):
133        """ Handle a generic exception. """
134
135        if logging.getLogger(self.LOGGER_NAME).level == logging.DEBUG:
136            import traceback
137
138            traceback.print_exception(*sys.exc_info())
139        else:
140            from PyQt5 import QtCore
141
142            sys.stderr.write("""An unexpected error occurred.
143Check that you are using the latest version of PyQt5 and send an error report to
144support@riverbankcomputing.com, including the following information:
145
146  * your version of PyQt (%s)
147  * the UI file that caused this error
148  * the debug output of pyuic5 (use the -d flag when calling pyuic5)
149""" % QtCore.PYQT_VERSION_STR)
150