Beispiel #1
0
    def test_human_readable_output(self):
        """
        Basic check of the human-readable output.

        Does not test: the full line format, truncation
        """
        data = [['first', 'second']]
        checker = Checker(dict.fromkeys(self.check))
        setattr(checker, self.check[0], data)
        stdout = PolyglotBytesIO()
        _print_check_library_results(checker,
                                     self.check,
                                     out=stdout,
                                     as_csv=False)

        result = stdout.getvalue().decode('utf-8', 'replace').split('\n')
        self.assertEqual(len(result), len(data) + 2)
        self.assertEqual(result[0], self.check[1])

        result_first = result[1].split('-')[0].strip()
        result_second = result[1].split('-')[1].strip()

        self.assertEqual(result_first, 'first')
        self.assertEqual(result_second, 'second')

        self.assertEqual(result[-1], '')
Beispiel #2
0
 def test_prints_nothing_if_no_errors(self):
     stdout = PolyglotBytesIO()
     checker = Checker(dict.fromkeys(self.check))
     _print_check_library_results(checker, self.check, as_csv=False, out=stdout)
     self.assertEqual(stdout.getvalue(), b'')
     _print_check_library_results(checker, self.check, as_csv=True, out=stdout)
     self.assertEqual(stdout.getvalue(), b'')
Beispiel #3
0
 def unhandled_exception(self, exc_type, value, tb):
     if exc_type is KeyboardInterrupt:
         return
     import traceback
     try:
         sio = PolyglotBytesIO(errors='replace')
         try:
             from calibre.debug import print_basic_debug_info
             print_basic_debug_info(out=sio)
         except:
             pass
         traceback.print_exception(exc_type, value, tb, file=sio)
         if getattr(value, 'locking_debug_msg', None):
             prints(value.locking_debug_msg, file=sio)
         fe = sio.getvalue()
         prints(fe, file=sys.stderr)
         fe = force_unicode(fe)
         msg = '<b>%s</b>:' % exc_type.__name__ + as_unicode(value)
         error_dialog(self,
                      _('Unhandled exception'),
                      msg,
                      det_msg=fe,
                      show=True)
     except BaseException:
         pass
     except:
         pass
Beispiel #4
0
 def contentxml(self):
     """ Generates the content.xml file
         Always written as a bytestream in UTF-8 encoding
     """
     xml = PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     x = DocumentContent()
     x.write_open_tag(0, xml)
     if self.scripts.hasChildNodes():
         self.scripts.toXml(1, xml)
     if self.fontfacedecls.hasChildNodes():
         self.fontfacedecls.toXml(1, xml)
     a = AutomaticStyles()
     stylelist = self._used_auto_styles(
         [self.styles, self.automaticstyles, self.body])
     if len(stylelist) > 0:
         a.write_open_tag(1, xml)
         for s in stylelist:
             s.toXml(2, xml)
         a.write_close_tag(1, xml)
     else:
         a.toXml(1, xml)
     self.body.toXml(1, xml)
     x.write_close_tag(0, xml)
     return xml.getvalue()
Beispiel #5
0
 def test_email_settings(self, to):
     opts = smtp_prefs().parse()
     from calibre.utils.smtp import sendmail, create_mail
     buf = PolyglotBytesIO()
     debug_out = partial(prints, file=buf)
     oout, oerr = sys.stdout, sys.stderr
     sys.stdout = sys.stderr = buf
     tb = None
     try:
         msg = create_mail(opts.from_, to, 'Test mail from calibre',
                           'Test mail from calibre')
         sendmail(msg,
                  from_=opts.from_,
                  to=[to],
                  verbose=3,
                  timeout=30,
                  relay=opts.relay_host,
                  username=opts.relay_username,
                  debug_output=debug_out,
                  password=from_hex_unicode(opts.relay_password),
                  encryption=opts.encryption,
                  port=opts.relay_port)
     except:
         import traceback
         tb = traceback.format_exc()
         tb += '\n\nLog:\n' + buf.getvalue().decode('utf-8', 'replace')
     finally:
         sys.stdout, sys.stderr = oout, oerr
     return tb
Beispiel #6
0
 def test_prints_nothing_if_no_errors(self):
     stdout = PolyglotBytesIO()
     checker = Checker(dict.fromkeys(self.check))
     _print_check_library_results(checker, self.check, as_csv=False, out=stdout)
     self.assertEqual(stdout.getvalue(), b'')
     _print_check_library_results(checker, self.check, as_csv=True, out=stdout)
     self.assertEqual(stdout.getvalue(), b'')
Beispiel #7
0
 def __manifestxml(self):
     """ Generates the manifest.xml file
         The self.manifest isn't avaible unless the document is being saved
     """
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.manifest.toXml(0,xml)
     return xml.getvalue()
Beispiel #8
0
 def __manifestxml(self):
     """ Generates the manifest.xml file
         The self.manifest isn't avaible unless the document is being saved
     """
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.manifest.toXml(0,xml)
     return xml.getvalue()
Beispiel #9
0
 def xml(self):
     """ Generates the full document as an XML file
         Always written as a bytestream in UTF-8 encoding
     """
     self.__replaceGenerator()
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.topnode.toXml(0, xml)
     return xml.getvalue()
Beispiel #10
0
 def xml(self):
     """ Generates the full document as an XML file
         Always written as a bytestream in UTF-8 encoding
     """
     self.__replaceGenerator()
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.topnode.toXml(0, xml)
     return xml.getvalue()
Beispiel #11
0
 def toXml(self, filename=''):
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.body.toXml(0, xml)
     if not filename:
         return xml.getvalue()
     else:
         f=open(filename,'wb')
         f.write(xml.getvalue())
         f.close()
Beispiel #12
0
    def test_escaped_csv_output(self):
        """
        Test more complex csv output
        """
        data = [['I, Caesar', 'second']]
        checker = Checker(dict.fromkeys(self.check))
        setattr(checker, self.check[0], data)
        stdout = PolyglotBytesIO()
        _print_check_library_results(checker, self.check, as_csv=True, out=stdout)

        result = stdout.getvalue().decode('utf-8', 'replace').split('\n')
        parsed_result = [l for l in csv.reader(result) if l]
        self.assertEqual(parsed_result, [[self.check[1], data[0][0], data[0][1]]])
Beispiel #13
0
    def test_escaped_csv_output(self):
        """
        Test more complex csv output
        """
        data = [['I, Caesar', 'second']]
        checker = Checker(dict.fromkeys(self.check))
        setattr(checker, self.check[0], data)
        stdout = PolyglotBytesIO()
        _print_check_library_results(checker, self.check, as_csv=True, out=stdout)

        result = stdout.getvalue().decode('utf-8', 'replace').split('\n')
        parsed_result = [l for l in csv.reader(result) if l]
        self.assertEqual(parsed_result, [[self.check[1], data[0][0], data[0][1]]])
Beispiel #14
0
 def init_env(self, name=''):
     from calibre.gui2.tweak_book.boss import get_boss
     self.context_name = name or ''
     self.match_index = 0
     self.boss = get_boss()
     self.data = {}
     self.debug_buf = PolyglotBytesIO()
     self.functions = {
         name: func.mod
         for name, func in iteritems(functions()) if func.mod is not None
     }
Beispiel #15
0
    def test_human_readable_output(self):
        """
        Basic check of the human-readable output.

        Does not test: the full line format, truncation
        """
        data = [['first', 'second']]
        checker = Checker(dict.fromkeys(self.check))
        setattr(checker, self.check[0], data)
        stdout = PolyglotBytesIO()
        _print_check_library_results(checker, self.check, out=stdout, as_csv=False)

        result = stdout.getvalue().decode('utf-8', 'replace').split('\n')
        self.assertEqual(len(result), len(data)+2)
        self.assertEqual(result[0], self.check[1])

        result_first = result[1].split('-')[0].strip()
        result_second = result[1].split('-')[1].strip()

        self.assertEqual(result_first, 'first')
        self.assertEqual(result_second, 'second')

        self.assertEqual(result[-1], '')
Beispiel #16
0
 def test_email_settings(self, to):
     opts = smtp_prefs().parse()
     from calibre.utils.smtp import sendmail, create_mail
     buf = PolyglotBytesIO()
     debug_out = partial(prints, file=buf)
     oout, oerr = sys.stdout, sys.stderr
     sys.stdout = sys.stderr = buf
     tb = None
     try:
         msg = create_mail(opts.from_, to, 'Test mail from calibre',
                 'Test mail from calibre')
         sendmail(msg, from_=opts.from_, to=[to],
             verbose=3, timeout=30, relay=opts.relay_host,
             username=opts.relay_username, debug_output=debug_out,
             password=from_hex_unicode(opts.relay_password),
             encryption=opts.encryption, port=opts.relay_port)
     except:
         import traceback
         tb = traceback.format_exc()
         tb += '\n\nLog:\n' + buf.getvalue().decode('utf-8', 'replace')
     finally:
         sys.stdout, sys.stderr = oout, oerr
     return tb
Beispiel #17
0
 def contentxml(self):
     """ Generates the content.xml file
         Always written as a bytestream in UTF-8 encoding
     """
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     x = DocumentContent()
     x.write_open_tag(0, xml)
     if self.scripts.hasChildNodes():
         self.scripts.toXml(1, xml)
     if self.fontfacedecls.hasChildNodes():
         self.fontfacedecls.toXml(1, xml)
     a = AutomaticStyles()
     stylelist = self._used_auto_styles([self.styles, self.automaticstyles, self.body])
     if len(stylelist) > 0:
         a.write_open_tag(1, xml)
         for s in stylelist:
             s.toXml(2, xml)
         a.write_close_tag(1, xml)
     else:
         a.toXml(1, xml)
     self.body.toXml(1, xml)
     x.write_close_tag(0, xml)
     return xml.getvalue()
Beispiel #18
0
 def unhandled_exception(self, exc_type, value, tb):
     if exc_type is KeyboardInterrupt:
         return
     import traceback
     try:
         sio = PolyglotBytesIO(errors='replace')
         try:
             from calibre.debug import print_basic_debug_info
             print_basic_debug_info(out=sio)
         except:
             pass
         traceback.print_exception(exc_type, value, tb, file=sio)
         if getattr(value, 'locking_debug_msg', None):
             prints(value.locking_debug_msg, file=sio)
         fe = sio.getvalue()
         prints(fe, file=sys.stderr)
         fe = force_unicode(fe)
         msg = '<b>%s</b>:'%exc_type.__name__ + as_unicode(value)
         error_dialog(self, _('Unhandled exception'), msg, det_msg=fe,
                 show=True)
     except BaseException:
         pass
     except:
         pass
Beispiel #19
0
 def toXml(self, filename=''):
     xml=PolyglotBytesIO()
     xml.write(_XMLPROLOGUE)
     self.body.toXml(0, xml)
     if not filename:
         return xml.getvalue()
     else:
         f=file(filename,'wb')
         f.write(xml.getvalue())
         f.close()
Beispiel #20
0
def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
    def col_split(l, cols):  # split list l into columns
        rows = len(l) / cols
        if len(l) % cols:
            rows += 1
        m = []
        for i in range(rows):
            m.append(l[i::rows])
        return m

    def row_widths(table):  # Calculate widths for each column in the row-wise table
        tcols = len(table[0])
        rowwidths = [0 for i in range(tcols)]
        for row in table:
            c = 0
            for item in row:
                rowwidths[c] = len(item) if len(item) > rowwidths[c] else rowwidths[c]
                c += 1
        return rowwidths

    output = PolyglotBytesIO()
    if path.endswith("/") and len(path) > 1:
        path = path[:-1]
    dirs = dev.list(path, recurse)
    for dir in dirs:
        if recurse:
            prints(dir[0] + ":", file=output)
        lsoutput, lscoloutput = [], []
        files = dir[1]
        maxlen = 0
        if ll:  # Calculate column width for size column
            for file in files:
                size = len(str(file.size))
                if human_readable_size:
                    file = FileFormatter(file)
                    size = len(file.human_readable_size)
                if size > maxlen:
                    maxlen = size
        for file in files:
            file = FileFormatter(file)
            name = file.name if ll else file.isdir_name
            lsoutput.append(name)
            lscoloutput.append(name)
            if ll:
                size = str(file.size)
                if human_readable_size:
                    size = file.human_readable_size
                prints(file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name, file=output)
        if not ll and len(lsoutput) > 0:
            trytable = []
            for colwidth in range(MINIMUM_COL_WIDTH, cols):
                trycols = int(cols/colwidth)
                trytable = col_split(lsoutput, trycols)
                works = True
                for row in trytable:
                    row_break = False
                    for item in row:
                        if len(item) > colwidth - 1:
                            works, row_break = False, True
                            break
                    if row_break:
                        break
                if works:
                    break
            rowwidths = row_widths(trytable)
            trytablecol = col_split(lscoloutput, len(trytable[0]))
            for r in range(len(trytable)):
                for c in range(len(trytable[r])):
                    padding = rowwidths[c] - len(trytable[r][c])
                    prints(trytablecol[r][c], "".ljust(padding), end=' ', file=output)
                prints(file=output)
        prints(file=output)
    listing = output.getvalue().rstrip().decode('utf-8') + "\n"
    output.close()
    return listing
Beispiel #21
0
def debug(ioreg_to_tmp=False, buf=None, plugins=None,
        disabled_plugins=None):
    '''
    If plugins is None, then this method calls startup and shutdown on the
    device plugins. So if you are using it in a context where startup could
    already have been called (for example in the main GUI), pass in the list of
    device plugins as the plugins parameter.
    '''
    import textwrap
    from calibre.customize.ui import device_plugins, disabled_device_plugins
    from calibre.debug import print_basic_debug_info
    from calibre.devices.scanner import DeviceScanner
    from calibre.constants import iswindows, isosx
    from calibre import prints
    from polyglot.io import PolyglotBytesIO
    oldo, olde = sys.stdout, sys.stderr

    if buf is None:
        buf = PolyglotBytesIO()
    sys.stdout = sys.stderr = buf
    out = partial(prints, file=buf)

    devplugins = device_plugins() if plugins is None else plugins
    devplugins = list(sorted(devplugins, key=lambda x: x.__class__.__name__))
    if plugins is None:
        for d in devplugins:
            try:
                d.startup()
            except:
                out('Startup failed for device plugin: %s'%d)

    if disabled_plugins is None:
        disabled_plugins = list(disabled_device_plugins())

    try:
        print_basic_debug_info(out=buf)
        s = DeviceScanner()
        s.scan()
        devices = (s.devices)
        if not iswindows:
            devices = [list(x) for x in devices]
            for d in devices:
                for i in range(3):
                    d[i] = hex(d[i])
        out('USB devices on system:')
        out(pprint.pformat(devices))

        ioreg = None
        if isosx:
            from calibre.devices.usbms.device import Device
            mount = '\n'.join(repr(x) for x in Device.osx_run_mount().splitlines())
            drives = pprint.pformat(Device.osx_get_usb_drives())
            ioreg = 'Output from mount:\n'+mount+'\n\n'
            ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n'
            ioreg += Device.run_ioreg()
        connected_devices = []
        if disabled_plugins:
            out('\nDisabled plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in
                disabled_plugins])))
            out(' ')
        else:
            out('\nNo disabled plugins')
        found_dev = False
        for dev in devplugins:
            if not dev.MANAGES_DEVICE_PRESENCE:
                continue
            out('Looking for devices of type:', dev.__class__.__name__)
            if dev.debug_managed_device_detection(s.devices, buf):
                found_dev = True
                break
            out(' ')

        if not found_dev:
            out('Looking for devices...')
            for dev in devplugins:
                if dev.MANAGES_DEVICE_PRESENCE:
                    continue
                connected, det = s.is_device_connected(dev, debug=True)
                if connected:
                    out('\t\tDetected possible device', dev.__class__.__name__)
                    connected_devices.append((dev, det))

            out(' ')
            errors = {}
            success = False
            out('Devices possibly connected:', end=' ')
            for dev, det in connected_devices:
                out(dev.name, end=', ')
            if not connected_devices:
                out('None', end='')
            out(' ')
            for dev, det in connected_devices:
                out('Trying to open', dev.name, '...', end=' ')
                dev.do_device_debug = True
                try:
                    dev.reset(detected_device=det)
                    dev.open(det, None)
                    out('OK')
                except:
                    import traceback
                    errors[dev] = traceback.format_exc()
                    out('failed')
                    continue
                dev.do_device_debug = False
                success = True
                if hasattr(dev, '_main_prefix'):
                    out('Main memory:', repr(dev._main_prefix))
                out('Total space:', dev.total_space())
                break
            if not success and errors:
                out('Opening of the following devices failed')
                for dev,msg in errors.items():
                    out(dev)
                    out(msg)
                    out(' ')

            if ioreg is not None:
                ioreg = 'IOREG Output\n'+ioreg
                out(' ')
                if ioreg_to_tmp:
                    lopen('/tmp/ioreg.txt', 'wb').write(ioreg)
                    out('Dont forget to send the contents of /tmp/ioreg.txt')
                    out('You can open it with the command: open /tmp/ioreg.txt')
                else:
                    out(ioreg)

        if hasattr(buf, 'getvalue'):
            return buf.getvalue().decode('utf-8', 'replace')
    finally:
        sys.stdout = oldo
        sys.stderr = olde
        if plugins is None:
            for d in devplugins:
                try:
                    d.shutdown()
                except:
                    pass
Beispiel #22
0
def debug(ioreg_to_tmp=False, buf=None, plugins=None, disabled_plugins=None):
    '''
    If plugins is None, then this method calls startup and shutdown on the
    device plugins. So if you are using it in a context where startup could
    already have been called (for example in the main GUI), pass in the list of
    device plugins as the plugins parameter.
    '''
    import textwrap
    from calibre.customize.ui import device_plugins, disabled_device_plugins
    from calibre.debug import print_basic_debug_info
    from calibre.devices.scanner import DeviceScanner
    from calibre.constants import iswindows, isosx
    from calibre import prints
    from polyglot.io import PolyglotBytesIO
    oldo, olde = sys.stdout, sys.stderr

    if buf is None:
        buf = PolyglotBytesIO()
    sys.stdout = sys.stderr = buf
    out = partial(prints, file=buf)

    devplugins = device_plugins() if plugins is None else plugins
    devplugins = list(sorted(devplugins, key=lambda x: x.__class__.__name__))
    if plugins is None:
        for d in devplugins:
            try:
                d.startup()
            except:
                out('Startup failed for device plugin: %s' % d)

    if disabled_plugins is None:
        disabled_plugins = list(disabled_device_plugins())

    try:
        print_basic_debug_info(out=buf)
        s = DeviceScanner()
        s.scan()
        devices = (s.devices)
        if not iswindows:
            devices = [list(x) for x in devices]
            for d in devices:
                for i in range(3):
                    d[i] = hex(d[i])
        out('USB devices on system:')
        out(pprint.pformat(devices))

        ioreg = None
        if isosx:
            from calibre.devices.usbms.device import Device
            mount = '\n'.join(
                repr(x) for x in Device.osx_run_mount().splitlines())
            drives = pprint.pformat(Device.osx_get_usb_drives())
            ioreg = 'Output from mount:\n' + mount + '\n\n'
            ioreg += 'Output from osx_get_usb_drives:\n' + drives + '\n\n'
            ioreg += Device.run_ioreg()
        connected_devices = []
        if disabled_plugins:
            out(
                '\nDisabled plugins:',
                textwrap.fill(' '.join(
                    [x.__class__.__name__ for x in disabled_plugins])))
            out(' ')
        else:
            out('\nNo disabled plugins')
        found_dev = False
        for dev in devplugins:
            if not dev.MANAGES_DEVICE_PRESENCE:
                continue
            out('Looking for devices of type:', dev.__class__.__name__)
            if dev.debug_managed_device_detection(s.devices, buf):
                found_dev = True
                break
            out(' ')

        if not found_dev:
            out('Looking for devices...')
            for dev in devplugins:
                if dev.MANAGES_DEVICE_PRESENCE:
                    continue
                connected, det = s.is_device_connected(dev, debug=True)
                if connected:
                    out('\t\tDetected possible device', dev.__class__.__name__)
                    connected_devices.append((dev, det))

            out(' ')
            errors = {}
            success = False
            out('Devices possibly connected:', end=' ')
            for dev, det in connected_devices:
                out(dev.name, end=', ')
            if not connected_devices:
                out('None', end='')
            out(' ')
            for dev, det in connected_devices:
                out('Trying to open', dev.name, '...', end=' ')
                dev.do_device_debug = True
                try:
                    dev.reset(detected_device=det)
                    dev.open(det, None)
                    out('OK')
                except:
                    import traceback
                    errors[dev] = traceback.format_exc()
                    out('failed')
                    continue
                dev.do_device_debug = False
                success = True
                if hasattr(dev, '_main_prefix'):
                    out('Main memory:', repr(dev._main_prefix))
                out('Total space:', dev.total_space())
                break
            if not success and errors:
                out('Opening of the following devices failed')
                for dev, msg in errors.items():
                    out(dev)
                    out(msg)
                    out(' ')

            if ioreg is not None:
                ioreg = 'IOREG Output\n' + ioreg
                out(' ')
                if ioreg_to_tmp:
                    lopen('/tmp/ioreg.txt', 'wb').write(ioreg)
                    out('Dont forget to send the contents of /tmp/ioreg.txt')
                    out('You can open it with the command: open /tmp/ioreg.txt'
                        )
                else:
                    out(ioreg)

        if hasattr(buf, 'getvalue'):
            return buf.getvalue().decode('utf-8', 'replace')
    finally:
        sys.stdout = oldo
        sys.stderr = olde
        if plugins is None:
            for d in devplugins:
                try:
                    d.shutdown()
                except:
                    pass
Beispiel #23
0
def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
    def col_split(l, cols):  # split list l into columns
        rows = len(l) / cols
        if len(l) % cols:
            rows += 1
        m = []
        for i in range(rows):
            m.append(l[i::rows])
        return m

    def row_widths(
            table):  # Calculate widths for each column in the row-wise table
        tcols = len(table[0])
        rowwidths = [0 for i in range(tcols)]
        for row in table:
            c = 0
            for item in row:
                rowwidths[c] = len(
                    item) if len(item) > rowwidths[c] else rowwidths[c]
                c += 1
        return rowwidths

    output = PolyglotBytesIO()
    if path.endswith("/") and len(path) > 1:
        path = path[:-1]
    dirs = dev.list(path, recurse)
    for dir in dirs:
        if recurse:
            prints(dir[0] + ":", file=output)
        lsoutput, lscoloutput = [], []
        files = dir[1]
        maxlen = 0
        if ll:  # Calculate column width for size column
            for file in files:
                size = len(str(file.size))
                if human_readable_size:
                    file = FileFormatter(file)
                    size = len(file.human_readable_size)
                if size > maxlen:
                    maxlen = size
        for file in files:
            file = FileFormatter(file)
            name = file.name if ll else file.isdir_name
            lsoutput.append(name)
            lscoloutput.append(name)
            if ll:
                size = str(file.size)
                if human_readable_size:
                    size = file.human_readable_size
                prints(file.mode_string, ("%" + str(maxlen) + "s") % size,
                       file.modification_time,
                       name,
                       file=output)
        if not ll and len(lsoutput) > 0:
            trytable = []
            for colwidth in range(MINIMUM_COL_WIDTH, cols):
                trycols = int(cols / colwidth)
                trytable = col_split(lsoutput, trycols)
                works = True
                for row in trytable:
                    row_break = False
                    for item in row:
                        if len(item) > colwidth - 1:
                            works, row_break = False, True
                            break
                    if row_break:
                        break
                if works:
                    break
            rowwidths = row_widths(trytable)
            trytablecol = col_split(lscoloutput, len(trytable[0]))
            for r in range(len(trytable)):
                for c in range(len(trytable[r])):
                    padding = rowwidths[c] - len(trytable[r][c])
                    prints(trytablecol[r][c],
                           "".ljust(padding),
                           end=' ',
                           file=output)
                prints(file=output)
        prints(file=output)
    listing = output.getvalue().rstrip().decode('utf-8') + "\n"
    output.close()
    return listing