docstr: Ensure that time_offsets can generate the correct query
docstr_tok: ["Ensure","that","time_offsets","can","generate","the","correct","query"]
code: def test_processing_time_offsets_cache(self):
      """
      Ensure that time_offsets can generate the correct query
      """
      self.login(username="admin")
      payload = get_query_context("birth_names")
      payload["queries"][0]["metrics"] = ["sum__num"]
      # should process empty dateframe correctly
      # due to "name" is random generated, each time_offset slice will be empty
      payload["queries"][0]["groupby"] = ["name"]
      payload["queries"][0]["is_timeseries"] = True
      payload["queries"][0]["timeseries_limit"] = 5
      payload["queries"][0]["time_offsets"] = []
      payload["queries"][0]["time_range"] = "1990 : 1991"
      payload["queries"][0]["granularity"] = "ds"
      payload["queries"][0]["extras"]["time_grain_sqla"] = "P1Y"
      query_context = ChartDataQueryContextSchema().load(payload)
      query_object = query_context.queries[0]
      query_result = query_context.get_query_result(query_object)
      # get main query dataframe
      df = query_result.df
  
      payload["queries"][0]["time_offsets"] = [
          "1 year ago",
          "1 year later",
      ]
      query_context = ChartDataQueryContextSchema().load(payload)
      query_object = query_context.queries[0]
      # query without cache
      query_context.processing_time_offsets(df, query_object)
      # query with cache
      rv = query_context.processing_time_offsets(df, query_object)
      cache_keys = rv["cache_keys"]
      cache_keys__1_year_ago = cache_keys[0]
      cache_keys__1_year_later = cache_keys[1]
      self.assertIsNotNone(cache_keys__1_year_ago)
      self.assertIsNotNone(cache_keys__1_year_later)
      self.assertNotEqual(
          cache_keys__1_year_ago, cache_keys__1_year_later
      )
  
      # swap offsets
      payload["queries"][0]["time_offsets"] = [
          "1 year later",
          "1 year ago",
      ]
      query_context = ChartDataQueryContextSchema().load(payload)
      query_object = query_context.queries[0]
      rv = query_context.processing_time_offsets(df, query_object)
      cache_keys = rv["cache_keys"]
      self.assertEqual(cache_keys__1_year_ago, cache_keys[1])
      self.assertEqual(cache_keys__1_year_later, cache_keys[0])
  
      # remove all offsets
      payload["queries"][0]["time_offsets"] = []
      query_context = ChartDataQueryContextSchema().load(payload)
      query_object = query_context.queries[0]
      rv = query_context.processing_time_offsets(
          df,
          query_object,
      )
      self.assertIs(rv["df"], df)
      self.assertEqual(rv["queries"], [])
      self.assertEqual(rv["cache_keys"], [])
  
imports: import re
  import time
  from typing import Any
  import numpy
  import pandas
  import pytest
  from pandas import DateOffset
  from superset import db
  from superset.charts.schemas import ChartDataQueryContextSchema
  from superset.common.chart_data import ChartDataResultFormat, ChartDataResultType
  from superset.common.query_context import QueryContext
  from superset.common.query_context_factory import QueryContextFactory
  from superset.common.query_object import QueryObject
  from superset.connectors.sqla.models import SqlMetric
  from superset.daos.datasource import DatasourceDAO
  from superset.extensions import cache_manager
  from superset.superset_typing import AdhocColumn
  from superset.utils.core import AdhocMetricExpressionType, backend, DatasourceType, QueryStatus
  from superset.utils.pandas_postprocessing.utils import FLAT_COLUMN_SEPARATOR
  from tests.integration_tests.base_tests import SupersetTestCase
  from tests.integration_tests.conftest import only_postgresql, only_sqlite
  from tests.integration_tests.fixtures.birth_names_dashboard import load_birth_names_dashboard_with_slices, load_birth_names_data
  from tests.integration_tests.fixtures.query_context import get_query_context
label_desc: Use image node_id 20 for calling the TestQueryContext obj's underlying member method code with example usage: obj.test_processing_time_offsets_cache() without return types