diff --git a/superset/db_engine_specs.py b/superset/db_engine_specs.py index edbd1b224a..97b6439a36 100644 --- a/superset/db_engine_specs.py +++ b/superset/db_engine_specs.py @@ -1541,16 +1541,16 @@ class TeradataEngineSpec(BaseEngineSpec): engine = 'teradata' limit_method = LimitMethod.WRAP_SQL - time_grains = ( - Grain('Time Column', _('Time Column'), '{col}', None), - Grain('minute', _('minute'), "TRUNC(CAST({col} as DATE), 'MI')", 'PT1M'), - Grain('hour', _('hour'), "TRUNC(CAST({col} as DATE), 'HH')", 'PT1H'), - Grain('day', _('day'), "TRUNC(CAST({col} as DATE), 'DDD')", 'P1D'), - Grain('week', _('week'), "TRUNC(CAST({col} as DATE), 'WW')", 'P1W'), - Grain('month', _('month'), "TRUNC(CAST({col} as DATE), 'MONTH')", 'P1M'), - Grain('quarter', _('quarter'), "TRUNC(CAST({col} as DATE), 'Q')", 'P0.25Y'), - Grain('year', _('year'), "TRUNC(CAST({col} as DATE), 'YEAR')", 'P1Y'), - ) + time_grain_functions = { + None: '{col}', + 'PT1M': "TRUNC(CAST({col} as DATE), 'MI')", + 'PT1H': "TRUNC(CAST({col} as DATE), 'HH')", + 'P1D': "TRUNC(CAST({col} as DATE), 'DDD')", + 'P1W': "TRUNC(CAST({col} as DATE), 'WW')", + 'P1M': "TRUNC(CAST({col} as DATE), 'MONTH')", + 'P0.25Y': "TRUNC(CAST({col} as DATE), 'Q')", + 'P1Y': "TRUNC(CAST({col} as DATE), 'YEAR')", + } engines = { diff --git a/tests/db_engine_specs_test.py b/tests/db_engine_specs_test.py index bdee22aa36..cc2ae707e9 100644 --- a/tests/db_engine_specs_test.py +++ b/tests/db_engine_specs_test.py @@ -281,7 +281,10 @@ class DbEngineSpecsTestCase(SupersetTestCase): time_grains = set(db_engine_specs.builtin_time_grains.keys()) # loop over all subclasses of BaseEngineSpec for cls_name, cls in inspect.getmembers(db_engine_specs): - if inspect.isclass(cls) and issubclass(cls, BaseEngineSpec): + if inspect.isclass(cls) and issubclass(cls, BaseEngineSpec) \ + and cls is not BaseEngineSpec: + # make sure time grain functions have been defined + self.assertGreater(len(cls.time_grain_functions), 0) # make sure that all defined time grains are supported defined_time_grains = {grain.duration for grain in cls.get_time_grains()} intersection = time_grains.intersection(defined_time_grains)