Esempio n. 1
0
async def do_exec(
        db_session,
        action,
        form,
        arguments=None,
        modal_guid=None,
        current_user=None):
    """ Executes python commands form AxAction.code

    Args:
        action (AxAction): Current action that is performed
        form (AxForm): Tobe form. Its same as action.form, but it contains
            values from vue form
        arguments(**kargs): Custom dict that can be used in code
        modal_guid (str): AxForm modal guid for wss console subscribtion

    Returns:
        Dict: Its custom Dict containing:
            info (str): Message that must be displayed to user
            error (str): Error that must be displayed to user
            item (DotMap): Javascript style dictionary of field and values.
                example- item.guid -> guid of current row
            exception (Dict): Info on exception that accured
            abort (Bool): If set to True - the action will be aborted and row
                state will not be changed
    """
    import backend.schema as ax_schema

    host = await ax_misc.get_ax_host()
    localz = dict()
    ax = DotMap()  # javascript style dicts item['guid'] == item.guid
    ax.row.guid = form.row_guid
    ax.arguments = arguments
    ax.stripe = stripe
    ax.user_email = None
    ax.user_guid = None
    if current_user:
        ax.user_email = current_user.get("email", None)
        ax.user_guid = current_user.get("user_id", None)
    ax.tom_label = await ax_misc.get_tom_label(form)
    ax.host = host
    ax.form_url = f'{host}/form/{form.db_name}/{form.row_guid}'
    ax.form = form
    ax.action = action
    ax.schema = ax_schema.schema
    ax.sql = ax_dialects.dialect.custom_query
    ax.print = ConsoleSender(modal_guid=modal_guid)
    ax.email = ax_emails.email_sender
    ax.paths.uploads = ax_misc.uploads_root_dir
    ax.paths.tmp = ax_misc.tmp_root_dir
    ax.add_action_job = ax_scheduler.add_action_job
    ax.do_action = ActionExecuter(
        db_session=db_session, current_user=current_user)
    ax.modal_guid = modal_guid
    for field in form.db_fields:
        ax.row[field.db_name] = field.value
    localz['ax'] = ax
    line_number = None

    try:
        await ax_exec.aexec(code=str(action.code), localz=localz, ax=ax)
        ret_ax = localz['ax']

        ret_data = {
            "info": ret_ax.message if 'message' in ret_ax else None,
            "error": ret_ax.error if 'error' in ret_ax else None,
            "item": ret_ax.row,
            "exception": None,
            "abort": ret_ax.abort if 'abort' in ret_ax else None
        }
        return ret_data
    except SyntaxError as err:
        logger.error(err)
        error_class = err.__class__.__name__
        detail = err.args[0]
        line_number = err.lineno
        ret_data = {
            "info": None,
            "item": None,
            "error": None,
            "exception": {
                "error_class": error_class,
                "line_number": line_number,
                "action_name": action.name,
                "detail": detail
            },
            "abort": True
        }
        if ax.print.check_was_used():
            err = json.dumps(ret_data, indent=4, sort_keys=True)
            ax.print('\n\n----- SYNTAX ERROR ------\n\n' + err)
        return ret_data
    except Exception as err:    # pylint: disable=broad-except
        logger.error(err)
        error_class = err.__class__.__name__
        detail = err.args[0]
        cl, exc, tb = sys.exc_info()
        del cl, exc
        # line_number = traceback.extract_tb(tb)[-1][1]
        line_number = 0
        traces = traceback.extract_tb(tb)
        for idx, trace in enumerate(traces):
            if trace.filename == '<string>':
                line_number = traceback.extract_tb(tb)[idx].lineno
        del tb

        ret_data = {
            "info": None,
            "item": None,
            "error": None,
            "exception": {
                "error_class": error_class,
                "line_number": line_number,
                "action_name": action.name,
                "detail": detail
            },
            "abort": True
        }
        if ax.print.check_was_used():
            err = json.dumps(ret_data, indent=4, sort_keys=True)
            ax.print('\n\n----- EXCEPTION ------\n\n' + err)
        return ret_data