Python traceback.format_exception() Examples

The following are 30 code examples of traceback.format_exception(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module traceback , or try the search function .
Example #1
Source File: celerytasks.py    From coursys with GNU General Public License v3.0 7 votes vote down vote up
def task(*d_args, **d_kwargs):
    # behaves like @task, but emails about exceptions.
    def real_decorator(f):
        @shared_task(*d_args, **d_kwargs)
        @wraps(f)
        def wrapper(*f_args, **f_kwargs):
            # try the task; email any exceptions we get
            try:
                res = f(*f_args, **f_kwargs)
            except Exception as e:
                # email admins and re-raise
                exc_type, exc_value, exc_traceback = sys.exc_info()
                subject = 'task failure in %s.%s' % (f.__module__, f.__name__)
                msg = 'The task %s.%s failed:\n\n%s' % (f.__module__, f.__name__,
                        '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
                mail_admins(subject=subject, message=msg, fail_silently=True)
                raise

            return res
        return wrapper
    return real_decorator 
Example #2
Source File: __init__.py    From nose-htmloutput with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def addFailure(self, test, err, capt=None):
        """Add failure output to Xunit report.
        """
        exc_type, exc_val, tb = err
        tb = ''.join(traceback.format_exception(
            exc_type,
            exc_val if isinstance(exc_val, exc_type) else exc_type(exc_val),
            tb
        ))
        name = id_split(test.id())
        group = self.report_data[name[0]]
        self.stats['failures'] += 1
        group.stats['failures'] += 1
        group.tests.append({
            'name': name[-1],
            'failed': True,
            'errtype': nice_classname(err[0]),
            'message': exc_message(err),
            'tb': tb,
        }) 
Example #3
Source File: main.py    From kivy-smoothie-host with GNU General Public License v3.0 6 votes vote down vote up
def handle_exception(exc_type, exc_value, exc_traceback):
    """ handle all exceptions """

    # KeyboardInterrupt is a special case.
    # We don't raise the error dialog when it occurs.
    if issubclass(exc_type, KeyboardInterrupt):
        return

    Logger.error("Unhandled Exception:")
    Logger.error("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
    try:
        App.get_running_app().stop()
    except Exception:
        pass


# we want to handle TERM signal cleanly (sent by sv down) 
Example #4
Source File: t_random.py    From trelby with GNU General Public License v2.0 6 votes vote down vote up
def save(ops, cnt):
    f = open("%d.ops" % cnt, "w")

    tbLines = traceback.format_exception(*sys.exc_info())

    for l in tbLines:
        # traceback lines contain embedded newlines so it gets a bit
        # complex escaping every line with # and keeping the formatting
        # correct.
        f.write("#" + l.rstrip().replace("\n", "\n#") + "\n")

    f.write(ops.save())
    f.close()

    f = open("%d.trelby" % cnt, "w")
    f.write(ops.sp.save())
    f.close() 
Example #5
Source File: easygui_qt.py    From easygui_qt with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def handle_exception(title="Exception raised!"):
    '''Displays a traceback in a window if an exception is raised.
       If the user clicks on "abort", sys.exit() is called and the
       program ends.  If the user clicks on "ignore", the program
       resumes its execution.

       :param title: the window title

       .. image:: ../docs/images/handle_exception.png
    '''
    try:
        message = "\n".join(traceback.format_exception(sys.exc_info()[0],
                        sys.exc_info()[1] , sys.exc_info()[2]))
    except AttributeError:
        return "No exception was raised"

    get_abort(title=title, message=message) 
Example #6
Source File: web.py    From tornado-zh with MIT License 6 votes vote down vote up
def write_error(self, status_code, **kwargs):
        """复写这个方法来实现自定义错误页.

        ``write_error`` 可能调用 `write`, `render`, `set_header`,等
        来产生一般的输出.

        如果错误是由未捕获的异常造成的(包括HTTPError), 三个一组的
        ``exc_info`` 将变成可用的通过 ``kwargs["exc_info"]``.
        注意这个异常可能不是"当前(current)" 目的或方法的异常就像
        ``sys.exc_info()`` 或 ``traceback.format_exc``.
        """
        if self.settings.get("serve_traceback") and "exc_info" in kwargs:
            # in debug mode, try to send a traceback
            self.set_header('Content-Type', 'text/plain')
            for line in traceback.format_exception(*kwargs["exc_info"]):
                self.write(line)
            self.finish()
        else:
            self.finish("<html><title>%(code)d: %(message)s</title>"
                        "<body>%(code)d: %(message)s</body></html>" % {
                            "code": status_code,
                            "message": self._reason,
                        }) 
Example #7
Source File: web.py    From tornado-zh with MIT License 6 votes vote down vote up
def write_error(self, status_code, **kwargs):
        """复写这个方法来实现自定义错误页.

        ``write_error`` 可能调用 `write`, `render`, `set_header`,等
        来产生一般的输出.

        如果错误是由未捕获的异常造成的(包括HTTPError), 三个一组的
        ``exc_info`` 将变成可用的通过 ``kwargs["exc_info"]``.
        注意这个异常可能不是"当前(current)" 目的或方法的异常就像
        ``sys.exc_info()`` 或 ``traceback.format_exc``.
        """
        if self.settings.get("serve_traceback") and "exc_info" in kwargs:
            # in debug mode, try to send a traceback
            self.set_header('Content-Type', 'text/plain')
            for line in traceback.format_exception(*kwargs["exc_info"]):
                self.write(line)
            self.finish()
        else:
            self.finish("<html><title>%(code)d: %(message)s</title>"
                        "<body>%(code)d: %(message)s</body></html>" % {
                            "code": status_code,
                            "message": self._reason,
                        }) 
Example #8
Source File: code.py    From py with MIT License 6 votes vote down vote up
def getrepr(self, showlocals=False, style="long",
                abspath=False, tbfilter=True, funcargs=False):
        """ return str()able representation of this exception info.
            showlocals: show locals per traceback entry
            style: long|short|no|native traceback style
            tbfilter: hide entries (where __tracebackhide__ is true)

            in case of style==native, tbfilter and showlocals is ignored.
        """
        if style == 'native':
            return ReprExceptionInfo(ReprTracebackNative(
                traceback.format_exception(
                    self.type,
                    self.value,
                    self.traceback[0]._rawentry,
                )), self._getreprcrash())

        fmt = FormattedExcinfo(
            showlocals=showlocals, style=style,
            abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
        return fmt.repr_excinfo(self) 
Example #9
Source File: test_framework.py    From python-test-framework with MIT License 6 votes vote down vote up
def _timed_block_factory(opening_text):
    from timeit import default_timer as timer
    from traceback import format_exception
    from sys import exc_info

    def _timed_block_decorator(s, before=None, after=None):
        display(opening_text, s)

        def wrapper(func):
            if callable(before):
                before()
            time = timer()
            try:
                func()
            except AssertionError as e:
                display('FAILED', str(e))
            except Exception:
                fail('Unexpected exception raised')
                tb_str = ''.join(format_exception(*exc_info()))
                display('ERROR', tb_str)
            display('COMPLETEDIN', '{:.2f}'.format((timer() - time) * 1000))
            if callable(after):
                after()
        return wrapper
    return _timed_block_decorator 
Example #10
Source File: crashdialog.py    From qutebrowser with GNU General Public License v3.0 6 votes vote down vote up
def _gather_crash_info(self):
        self._crash_info += [
            ("Exception", ''.join(traceback.format_exception(*self._exc))),
        ]
        super()._gather_crash_info()
        if self._chk_log.isChecked():
            self._crash_info += [
                ("Commandline args", ' '.join(sys.argv[1:])),
                ("Open Pages", '\n\n'.join('\n'.join(e) for e in self._pages)),
                ("Command history", '\n'.join(self._cmdhist)),
                ("Objects", self._qobjects),
            ]
            try:
                text = "Log output was disabled."
                if log.ram_handler is not None:
                    text = log.ram_handler.dump_log()
                self._crash_info.append(("Debug log", text))
            except Exception:
                self._crash_info.append(("Debug log", traceback.format_exc())) 
Example #11
Source File: utils.py    From pyeclib with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def import_class(import_str):
    """
    Returns a class from a string that specifies a module and/or class

    :param import_str: import path, e.g. 'httplib.HTTPConnection'
    :returns imported object
    :raises: ImportedError if the class does not exist or the path is invalid
    """
    (mod_str, separator, class_str) = import_str.rpartition('.')
    try:
        __import__(mod_str)
        return getattr(sys.modules[mod_str], class_str)
    except (ValueError, AttributeError):
        raise ImportError('Class %s cannot be found (%)' %
                          (class_str,
                           traceback.format_exception(*sys.exc_info()))) 
Example #12
Source File: slogging.py    From modelforge with Apache License 2.0 6 votes vote down vote up
def emit(self, record: logging.LogRecord):
        """Print the log record formatted as JSON to stdout."""
        created = datetime.datetime.fromtimestamp(record.created, timezone)
        obj = {
            "level": record.levelname.lower(),
            "msg": record.msg % record.args,
            "source": "%s:%d" % (record.filename, record.lineno),
            "time": format_datetime(created),
            "thread": reduce_thread_id(record.thread),
        }
        if record.exc_info is not None:
            obj["error"] = traceback.format_exception(*record.exc_info)[1:]
        try:
            obj["context"] = self.local.context
        except AttributeError:
            pass
        json.dump(obj, sys.stdout, sort_keys=True)
        sys.stdout.write("\n")
        sys.stdout.flush() 
Example #13
Source File: celerytasks.py    From coursys with GNU General Public License v3.0 6 votes vote down vote up
def periodic_task(*d_args, **d_kwargs):
    # behaves like @periodic_task, but emails about exceptions.
    def real_decorator(f):
        @celery_periodic_task(*d_args, **d_kwargs)
        @wraps(f)
        def wrapper(*f_args, **f_kwargs):
            # try the task; email any exceptions we get
            try:
                res = f(*f_args, **f_kwargs)
            except Exception as e:
                # email admins and re-raise
                exc_type, exc_value, exc_traceback = sys.exc_info()
                subject = 'task failure in %s.%s' % (f.__module__, f.__name__)
                msg = 'The periodic task %s.%s failed:\n\n%s' % (f.__module__, f.__name__,
                        '\n'.join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
                mail_admins(subject=subject, message=msg, fail_silently=True)
                raise

            return res
        return wrapper
    return real_decorator 
Example #14
Source File: helpers.py    From avrae with GNU General Public License v3.0 6 votes vote down vote up
def handle_alias_exception(ctx, err):
    e = err.original
    location = ''
    if isinstance(e, AvraeException):
        return await ctx.channel.send(err)
    elif isinstance(e, draconic.InvalidExpression):
        try:
            location = f" on line {e.node.lineno}, col {e.node.col_offset}"
        except AttributeError:
            pass
    elif isinstance(e, draconic.DraconicSyntaxError):
        location = f" on line {e.lineno}, col {e.offset}"
    tb = ''.join(traceback.format_exception(type(e), e, e.__traceback__, limit=0, chain=False))
    try:
        await ctx.author.send(
            f"```py\n"
            f"Error{location} when parsing expression {err.expression}:\n"
            f"{tb}\n"
            f"```")
    except:
        pass
    return await ctx.channel.send(err) 
Example #15
Source File: __main__.py    From resolwe with Apache License 2.0 6 votes vote down vote up
def handle_exception(exc_type, exc_value, exc_traceback):
    """Log unhandled exceptions."""
    message = "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
    logger.error("Unhandled exception in executor: {}".format(message))

    loop.run_until_complete(
        asyncio.gather(
            *logging_future_list,
            manager_commands.send_manager_command(
                ExecutorProtocol.UPDATE,
                extra_fields={
                    ExecutorProtocol.UPDATE_CHANGESET: {
                        "process_error": ["Unhandled exception in executor."],
                        "status": DATA_META["STATUS_ERROR"],
                    }
                },
            ),
            manager_commands.send_manager_command(
                ExecutorProtocol.ABORT, expect_reply=False
            ),
        )
    ) 
Example #16
Source File: transmogrifier.py    From rucio with Apache License 2.0 6 votes vote down vote up
def _retrial(func, *args, **kwargs):
    """
    Retrial method
    """
    delay = 0
    while True:
        try:
            return func(*args, **kwargs)
        except DataIdentifierNotFound as error:
            logging.warning(error)
            return 1
        except DatabaseException as error:
            logging.error(error)
            if exp(delay) > 600:
                logging.error('Cannot execute %s after %i attempt. Failing the job.' % (func.__name__, delay))
                raise
            else:
                logging.error('Failure to execute %s. Retrial will be done in %d seconds ' % (func.__name__, exp(delay)))
            time.sleep(exp(delay))
            delay += 1
        except Exception:
            exc_type, exc_value, exc_traceback = exc_info()
            logging.critical(''.join(format_exception(exc_type, exc_value, exc_traceback)).strip())
            raise 
Example #17
Source File: pdbpp.py    From pdbpp with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def error(self, msg):
        """Override/enhance default error method to display tracebacks."""
        self._seen_error = msg
        print("***", msg, file=self.stdout)

        if not self.config.show_traceback_on_error:
            return

        etype, evalue, tb = sys.exc_info()
        if tb and tb.tb_frame.f_code.co_name == "default":
            tb = tb.tb_next
            if tb and tb.tb_frame.f_code.co_filename == "<stdin>":
                tb = tb.tb_next
                if tb:  # only display with actual traceback.
                    self._remove_bdb_context(evalue)
                    tb_limit = self.config.show_traceback_on_error_limit
                    fmt_exc = traceback.format_exception(
                        etype, evalue, tb, limit=tb_limit
                    )

                    # Remove last line (exception string again).
                    if len(fmt_exc) > 1 and fmt_exc[-1][0] != " ":
                        fmt_exc.pop()

                    print("".join(fmt_exc).rstrip(), file=self.stdout) 
Example #18
Source File: code.py    From python-netsurv with MIT License 6 votes vote down vote up
def getrepr(self, showlocals=False, style="long",
                abspath=False, tbfilter=True, funcargs=False):
        """ return str()able representation of this exception info.
            showlocals: show locals per traceback entry
            style: long|short|no|native traceback style
            tbfilter: hide entries (where __tracebackhide__ is true)

            in case of style==native, tbfilter and showlocals is ignored.
        """
        if style == 'native':
            return ReprExceptionInfo(ReprTracebackNative(
                traceback.format_exception(
                    self.type,
                    self.value,
                    self.traceback[0]._rawentry,
                )), self._getreprcrash())

        fmt = FormattedExcinfo(
            showlocals=showlocals, style=style,
            abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
        return fmt.repr_excinfo(self) 
Example #19
Source File: code.py    From python-netsurv with MIT License 6 votes vote down vote up
def getrepr(self, showlocals=False, style="long",
                abspath=False, tbfilter=True, funcargs=False):
        """ return str()able representation of this exception info.
            showlocals: show locals per traceback entry
            style: long|short|no|native traceback style
            tbfilter: hide entries (where __tracebackhide__ is true)

            in case of style==native, tbfilter and showlocals is ignored.
        """
        if style == 'native':
            return ReprExceptionInfo(ReprTracebackNative(
                traceback.format_exception(
                    self.type,
                    self.value,
                    self.traceback[0]._rawentry,
                )), self._getreprcrash())

        fmt = FormattedExcinfo(
            showlocals=showlocals, style=style,
            abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
        return fmt.repr_excinfo(self) 
Example #20
Source File: _cperror.py    From cherrypy with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def format_exc(exc=None):
    """Return exc (or sys.exc_info if None), formatted."""
    try:
        if exc is None:
            exc = _exc_info()
        if exc == (None, None, None):
            return ''
        import traceback
        return ''.join(traceback.format_exception(*exc))
    finally:
        del exc 
Example #21
Source File: wspbus.py    From cherrypy with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def log(self, msg='', level=20, traceback=False):
        """Log the given message. Append the last traceback if requested."""
        if traceback:
            msg += '\n' + ''.join(_traceback.format_exception(*sys.exc_info()))
        self.publish('log', msg, level) 
Example #22
Source File: cloud_client.py    From neural-fingerprinting with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def __exit__(self, exc_type, exc_value, traceback):
    if exc_type is None:
      self.commit()
    else:
      err = tb.format_exception(exc_type, exc_value, traceback)
      logging.error('Exception occurred during write:\n%s', err)
      self.rollback() 
Example #23
Source File: anim.py    From CAMISIM with Apache License 2.0 5 votes vote down vote up
def last_exception():
		"""
		Returns last exception as a string, or use in logging.

		@rtype: str|unicode
		"""
		exc_type, exc_value, exc_traceback = sys.exc_info()
		return ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))

	# Parse NUCmer delta output to store alignment total length, sim_error,
	# and percentage identity, for each pairwise comparison 
Example #24
Source File: python.py    From friendly-telegram with GNU Affero General Public License v3.0 5 votes vote down vote up
def evalcmd(self, message):
        """.eval <expression>
           Evaluates python code"""
        ret = self.strings["evaluated"]
        try:
            it = await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message))
        except Exception:
            exc = sys.exc_info()
            exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
            await utils.answer(message, self.strings["evaluate_fail"]
                               .format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc)))
            return
        ret = ret.format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(it))
        await utils.answer(message, ret) 
Example #25
Source File: python.py    From friendly-telegram with GNU Affero General Public License v3.0 5 votes vote down vote up
def execcmd(self, message):
        """.exec <expression>
           Executes python code"""
        try:
            await meval(utils.get_args_raw(message), globals(), **await self.getattrs(message))
        except Exception:
            exc = sys.exc_info()
            exc = "".join(traceback.format_exception(exc[0], exc[1], exc[2].tb_next.tb_next.tb_next))
            await utils.answer(message, self.strings["execute_fail"]
                               .format(utils.escape_html(utils.get_args_raw(message)), utils.escape_html(exc)))
            return 
Example #26
Source File: wrappers.py    From soccer-matlab with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def _worker(self, constructor, conn):
    """The process waits for actions and sends back environment results.

    Args:
      constructor: Constructor for the OpenAI Gym environment.
      conn: Connection for communication to the main process.
    """
    try:
      env = constructor()
      while True:
        try:
          # Only block for short times to have keyboard exceptions be raised.
          if not conn.poll(0.1):
            continue
          message, payload = conn.recv()
        except (EOFError, KeyboardInterrupt):
          break
        if message == self._ACTION:
          action = payload
          conn.send((self._TRANSITION, env.step(action)))
          continue
        if message == self._RESET:
          assert payload is None
          conn.send((self._OBSERV, env.reset()))
          continue
        if message == self._ATTRIBUTE:
          name = payload
          conn.send((self._VALUE, getattr(env, name)))
          continue
        if message == self._CLOSE:
          assert payload is None
          break
        raise KeyError('Received message of unknown type {}'.format(message))
    except Exception:  # pylint: disable=broad-except
      stacktrace = ''.join(traceback.format_exception(*sys.exc_info()))
      conn.send((self._EXCEPTION, stacktrace))
      tf.logging.error('Error in environment process: {}'.format(stacktrace))
    conn.close() 
Example #27
Source File: wrappers.py    From soccer-matlab with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def _worker(self, constructor, conn):
    """The process waits for actions and sends back environment results.

    Args:
      constructor: Constructor for the OpenAI Gym environment.
      conn: Connection for communication to the main process.
    """
    try:
      env = constructor()
      while True:
        try:
          # Only block for short times to have keyboard exceptions be raised.
          if not conn.poll(0.1):
            continue
          message, payload = conn.recv()
        except (EOFError, KeyboardInterrupt):
          break
        if message == self._ACCESS:
          name = payload
          result = getattr(env, name)
          conn.send((self._RESULT, result))
          continue
        if message == self._CALL:
          name, args, kwargs = payload
          result = getattr(env, name)(*args, **kwargs)
          conn.send((self._RESULT, result))
          continue
        if message == self._CLOSE:
          assert payload is None
          break
        raise KeyError('Received message of unknown type {}'.format(message))
    except Exception:  # pylint: disable=broad-except
      stacktrace = ''.join(traceback.format_exception(*sys.exc_info()))
      tf.logging.error('Error in environment process: {}'.format(stacktrace))
      conn.send((self._EXCEPTION, stacktrace))
    conn.close() 
Example #28
Source File: batch_env_factory.py    From fine-lm with MIT License 5 votes vote down vote up
def _worker(self, constructor, conn):
    """The process waits for actions and sends back environment results.

    Args:
      constructor: Constructor for the OpenAI Gym environment.
      conn: Connection for communication to the main process.
    """
    try:
      env = constructor()
      while True:
        try:
          # Only block for short times to have keyboard exceptions be raised.
          if not conn.poll(0.1):
            continue
          message, payload = conn.recv()
        except (EOFError, KeyboardInterrupt):
          break
        if message == self._ACCESS:
          name = payload
          result = getattr(env, name)
          conn.send((self._RESULT, result))
          continue
        if message == self._CALL:
          name, args, kwargs = payload
          result = getattr(env, name)(*args, **kwargs)
          conn.send((self._RESULT, result))
          continue
        if message == self._CLOSE:
          assert payload is None
          env.close()
          break
        raise KeyError("Received message of unknown type {}".format(message))
    except Exception:  # pylint: disable=broad-except
      stacktrace = "".join(traceback.format_exception(*sys.exc_info()))  # pylint: disable=no-value-for-parameter
      tf.logging.error("Error in environment process: {}".format(stacktrace))
      conn.send((self._EXCEPTION, stacktrace))
    conn.close() 
Example #29
Source File: result.py    From jawfish with MIT License 5 votes vote down vote up
def _exc_info_to_string(self, err, test):
        """Converts a sys.exc_info()-style tuple of values into a string."""
        exctype, value, tb = err
        # Skip test runner traceback levels
        while tb and self._is_relevant_tb_level(tb):
            tb = tb.tb_next

        if exctype is test.failureException:
            # Skip assert*() traceback levels
            length = self._count_relevant_tb_levels(tb)
            msgLines = traceback.format_exception(exctype, value, tb, length)
        else:
            msgLines = traceback.format_exception(exctype, value, tb)

        if self.buffer:
            output = sys.stdout.getvalue()
            error = sys.stderr.getvalue()
            if output:
                if not output.endswith('\n'):
                    output += '\n'
                msgLines.append(STDOUT_LINE % output)
            if error:
                if not error.endswith('\n'):
                    error += '\n'
                msgLines.append(STDERR_LINE % error)
        return ''.join(msgLines) 
Example #30
Source File: __init__.py    From nose-htmloutput with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def addError(self, test, err, capt=None):
        """Add error output to Xunit report.
        """
        exc_type, exc_val, tb = err
        tb = ''.join(traceback.format_exception(
            exc_type,
            exc_val if isinstance(exc_val, exc_type) else exc_type(exc_val),
            tb
        ))
        name = id_split(test.id())
        group = self.report_data[name[0]]
        if issubclass(err[0], SkipTest):
            type = 'skipped'
            self.stats['skipped'] += 1
            group.stats['skipped'] += 1
        else:
            type = 'error'
            self.stats['errors'] += 1
            group.stats['errors'] += 1
        group.tests.append({
            'name': name[-1],
            'failed': True,
            'type': type,
            'errtype': nice_classname(err[0]),
            'message': exc_message(err),
            'tb': tb,
        })