示例#1
0
文件: api.py 项目: retellhq/superset
    def get_data_response(self,
                          command: ChartDataCommand,
                          force_cached: bool = False) -> Response:
        try:
            result = command.run(force_cached=force_cached)
        except ChartDataCacheLoadError as exc:
            return self.response_422(message=exc.message)
        except ChartDataQueryFailedError as exc:
            return self.response_400(message=exc.message)

        result_format = result["query_context"].result_format
        if result_format == ChartDataResultFormat.CSV:
            # Verify user has permission to export CSV file
            if not security_manager.can_access("can_csv", "Superset"):
                return self.response_403()

            # return the first result
            data = result["queries"][0]["data"]
            return CsvResponse(data, headers=generate_download_headers("csv"))

        if result_format == ChartDataResultFormat.JSON:
            response_data = simplejson.dumps(
                {"result": result["queries"]},
                default=json_int_dttm_ser,
                ignore_nan=True,
            )
            resp = make_response(response_data, 200)
            resp.headers["Content-Type"] = "application/json; charset=utf-8"
            return resp

        return self.response_400(
            message=f"Unsupported result_format: {result_format}")
示例#2
0
def load_chart_data_into_cache(
    job_metadata: Dict[str, Any],
    form_data: Dict[str, Any],
) -> None:
    from superset.charts.commands.data import (
        ChartDataCommand, )  # load here due to circular imports

    with app.app_context():  # type: ignore
        try:
            ensure_user_is_set(job_metadata.get("user_id"))
            command = ChartDataCommand()
            command.set_query_context(form_data)
            result = command.run(cache=True)
            cache_key = result["cache_key"]
            result_url = f"/api/v1/chart/data/{cache_key}"
            async_query_manager.update_job(
                job_metadata,
                async_query_manager.STATUS_DONE,
                result_url=result_url,
            )
        except Exception as exc:
            # TODO: QueryContext should support SIP-40 style errors
            error = exc.message if hasattr(exc, "message") else str(exc)  # type: ignore # pylint: disable=no-member
            errors = [{"message": error}]
            async_query_manager.update_job(job_metadata,
                                           async_query_manager.STATUS_ERROR,
                                           errors=errors)
            raise exc

        return None
示例#3
0
文件: api.py 项目: seldinet/superset
    def _run_async(self, command: ChartDataCommand) -> Response:
        """
        Execute command as an async query.
        """
        # First, look for the chart query results in the cache.
        try:
            result = command.run(force_cached=True)
        except ChartDataCacheLoadError:
            result = None  # type: ignore

        already_cached_result = result is not None

        # If the chart query has already been cached, return it immediately.
        if already_cached_result:
            return self.send_chart_response(result)

        # Otherwise, kick off a background job to run the chart query.
        # Clients will either poll or be notified of query completion,
        # at which point they will call the /data/<cache_key> endpoint
        # to retrieve the results.
        try:
            command.validate_async_request(request)
        except AsyncQueryTokenException:
            return self.response_401()

        result = command.run_async(g.user.get_id())
        return self.response(202, **result)
示例#4
0
def load_chart_data_into_cache(
    job_metadata: Dict[str, Any],
    form_data: Dict[str, Any],
) -> None:
    # pylint: disable=import-outside-toplevel
    from superset.charts.commands.data import ChartDataCommand

    try:
        ensure_user_is_set(job_metadata.get("user_id"))
        set_form_data(form_data)
        command = ChartDataCommand()
        command.set_query_context(form_data)
        result = command.run(cache=True)
        cache_key = result["cache_key"]
        result_url = f"/api/v1/chart/data/{cache_key}"
        async_query_manager.update_job(
            job_metadata,
            async_query_manager.STATUS_DONE,
            result_url=result_url,
        )
    except SoftTimeLimitExceeded as ex:
        logger.warning(
            "A timeout occurred while loading chart data, error: %s", ex)
        raise ex
    except Exception as ex:
        # TODO: QueryContext should support SIP-40 style errors
        error = ex.message if hasattr(ex, "message") else str(ex)  # type: ignore # pylint: disable=no-member
        errors = [{"message": error}]
        async_query_manager.update_job(job_metadata,
                                       async_query_manager.STATUS_ERROR,
                                       errors=errors)
        raise ex
示例#5
0
文件: api.py 项目: swaitw/superset
    def get_data_response(self,
                          command: ChartDataCommand,
                          force_cached: bool = False) -> Response:
        try:
            result = command.run(force_cached=force_cached)
        except ChartDataCacheLoadError as exc:
            return self.response_422(message=exc.message)
        except ChartDataQueryFailedError as exc:
            return self.response_400(message=exc.message)

        return self.send_chart_response(result)
示例#6
0
    def get_data_response(self,
                          command: ChartDataCommand,
                          force_cached: bool = False) -> Response:
        try:
            result = command.run(force_cached=force_cached)
        except ChartDataCacheLoadError as exc:
            return self.response_422(message=exc.message)
        except ChartDataQueryFailedError as exc:
            return self.response_400(message=exc.message)

        result_format = result["query_context"].result_format
        if result_format == ChartDataResultFormat.CSV:
            # return the first result
            data = result["queries"][0]["data"]
            return CsvResponse(data, headers=generate_download_headers("csv"))

        if result_format == ChartDataResultFormat.JSON:
            response_data = simplejson.dumps(
                {"result": result["queries"]},
                default=json_int_dttm_ser,
                ignore_nan=True,
            )
            resp = make_response(response_data, 200)
            resp.headers["Content-Type"] = "application/json; charset=utf-8"
            return resp

        if result_format == ChartDataResultFormat.XLSX:

            sio = BytesIO()
            df = pandas.DataFrame(result["queries"][0]["data"])
            writer = pandas.ExcelWriter(sio, engine='xlsxwriter')
            df.to_excel(writer, sheet_name="Лист 1", index=None)
            writer.save()

            sio.seek(0)
            workbook = sio.getvalue()

            return CsvResponse(workbook,
                               headers=generate_download_headers("xlsx"))

        return self.response_400(
            message=f"Unsupported result_format: {result_format}")
示例#7
0
文件: api.py 项目: swaitw/superset
    def data(self) -> Response:
        """
        Takes a query context constructed in the client and returns payload
        data response for the given query.
        ---
        post:
          description: >-
            Takes a query context constructed in the client and returns payload data
            response for the given query.
          requestBody:
            description: >-
              A query context consists of a datasource from which to fetch data
              and one or many query objects.
            required: true
            content:
              application/json:
                schema:
                  $ref: "#/components/schemas/ChartDataQueryContextSchema"
          responses:
            200:
              description: Query result
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ChartDataResponseSchema"
            202:
              description: Async job details
              content:
                application/json:
                  schema:
                    $ref: "#/components/schemas/ChartDataAsyncResponseSchema"
            400:
              $ref: '#/components/responses/400'
            401:
              $ref: '#/components/responses/401'
            500:
              $ref: '#/components/responses/500'
        """
        json_body = None
        if request.is_json:
            json_body = request.json
        elif request.form.get("form_data"):
            # CSV export submits regular form data
            try:
                json_body = json.loads(request.form["form_data"])
            except (TypeError, json.JSONDecodeError):
                pass

        if json_body is None:
            return self.response_400(message=_("Request is not JSON"))

        try:
            command = ChartDataCommand()
            query_context = command.set_query_context(json_body)
            command.validate()
        except QueryObjectValidationError as error:
            return self.response_400(message=error.message)
        except ValidationError as error:
            return self.response_400(
                message=_("Request is incorrect: %(error)s",
                          error=error.normalized_messages()))

        # TODO: support CSV, SQL query and other non-JSON types
        if (is_feature_enabled("GLOBAL_ASYNC_QUERIES")
                and query_context.result_format == ChartDataResultFormat.JSON
                and query_context.result_type == ChartDataResultType.FULL):
            # First, look for the chart query results in the cache.
            try:
                result = command.run(force_cached=True)
            except ChartDataCacheLoadError:
                result = None  # type: ignore

            already_cached_result = result is not None

            # If the chart query has already been cached, return it immediately.
            if already_cached_result:
                return self.send_chart_response(result)

            # Otherwise, kick off a background job to run the chart query.
            # Clients will either poll or be notified of query completion,
            # at which point they will call the /data/<cache_key> endpoint
            # to retrieve the results.
            try:
                command.validate_async_request(request)
            except AsyncQueryTokenException:
                return self.response_401()

            result = command.run_async(g.user.get_id())
            return self.response(202, **result)

        return self.get_data_response(command)