You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by vi...@apache.org on 2019/05/31 13:55:45 UTC
[incubator-superset] branch master updated: Add relative start
param for time filters (#7525)
This is an automated email from the ASF dual-hosted git repository.
villebro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new c1712e5 Add relative start param for time filters (#7525)
c1712e5 is described below
commit c1712e5d1080c2ca4d80cf581256fd1b9e23e59c
Author: Ville Brofeldt <33...@users.noreply.github.com>
AuthorDate: Fri May 31 16:55:26 2019 +0300
Add relative start param for time filters (#7525)
* Add relative start param for time filters
* Fix typo and add types to parse_human_datetime
* Add relative start/end to query_object
* Fix linting error
---
superset/common/query_object.py | 9 ++++++++-
superset/config.py | 7 ++++++-
superset/utils/core.py | 22 ++++++++++++----------
superset/viz.py | 7 +++++--
tests/utils_tests.py | 22 +++++++++++++++++++---
5 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/superset/common/query_object.py b/superset/common/query_object.py
index 47abbf2..553c0b9 100644
--- a/superset/common/query_object.py
+++ b/superset/common/query_object.py
@@ -51,9 +51,16 @@ class QueryObject:
is_prequery: bool = False,
columns: List[str] = None,
orderby: List[List] = None,
+ relative_start: str = app.config.get('DEFAULT_RELATIVE_START_TIME', 'today'),
+ relative_end: str = app.config.get('DEFAULT_RELATIVE_END_TIME', 'today'),
):
self.granularity = granularity
- self.from_dttm, self.to_dttm = utils.get_since_until(time_range, time_shift)
+ self.from_dttm, self.to_dttm = utils.get_since_until(
+ relative_start=relative_start,
+ relative_end=relative_end,
+ time_range=time_range,
+ time_shift=time_shift,
+ )
self.is_timeseries = is_timeseries
self.time_range = time_range
self.time_shift = utils.parse_human_timedelta(time_shift)
diff --git a/superset/config.py b/superset/config.py
index fc287b7..7d6ca33 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -599,8 +599,13 @@ BUG_REPORT_URL = None
DOCUMENTATION_URL = None
# What is the Last N days relative in the time selector to:
-# 'today' means it is midnight (00:00:00) of today in the local timezone
+# 'today' means it is midnight (00:00:00) in the local timezone
# 'now' means it is relative to the query issue time
+# If both start and end time is set to now, this will make the time
+# filter a moving window. By only setting the end time to now,
+# start time will be set to midnight, while end will be relative to
+# the query issue time.
+DEFAULT_RELATIVE_START_TIME = 'today'
DEFAULT_RELATIVE_END_TIME = 'today'
# Is epoch_s/epoch_ms datetime format supposed to be considered since UTC ?
diff --git a/superset/utils/core.py b/superset/utils/core.py
index 2defa70..df25500 100644
--- a/superset/utils/core.py
+++ b/superset/utils/core.py
@@ -237,14 +237,14 @@ def parse_human_datetime(s):
# when time is not extracted, we 'reset to midnight'
if parsed_flags & 2 == 0:
parsed_dttm = parsed_dttm.replace(hour=0, minute=0, second=0)
- dttm = dttm_from_timtuple(parsed_dttm.utctimetuple())
+ dttm = dttm_from_timetuple(parsed_dttm.utctimetuple())
except Exception as e:
logging.exception(e)
raise ValueError("Couldn't parse date string [{}]".format(s))
return dttm
-def dttm_from_timtuple(d: struct_time) -> datetime:
+def dttm_from_timetuple(d: struct_time) -> datetime:
return datetime(
d.tm_year, d.tm_mon, d.tm_mday, d.tm_hour, d.tm_min, d.tm_sec)
@@ -306,7 +306,7 @@ def parse_human_timedelta(s: str):
True
"""
cal = parsedatetime.Calendar()
- dttm = dttm_from_timtuple(datetime.now().timetuple())
+ dttm = dttm_from_timetuple(datetime.now().timetuple())
d = cal.parse(s or '', dttm)[0]
d = datetime(d.tm_year, d.tm_mon, d.tm_mday, d.tm_hour, d.tm_min, d.tm_sec)
return d - dttm
@@ -939,6 +939,7 @@ def get_since_until(time_range: Optional[str] = None,
since: Optional[str] = None,
until: Optional[str] = None,
time_shift: Optional[str] = None,
+ relative_start: Optional[str] = None,
relative_end: Optional[str] = None) -> Tuple[datetime, datetime]:
"""Return `since` and `until` date time tuple from string representations of
time_range, since, until and time_shift.
@@ -965,13 +966,14 @@ def get_since_until(time_range: Optional[str] = None,
"""
separator = ' : '
+ relative_start = parse_human_datetime(relative_start if relative_start else 'today')
relative_end = parse_human_datetime(relative_end if relative_end else 'today')
common_time_frames = {
- 'Last day': (relative_end - relativedelta(days=1), relative_end), # noqa: T400
- 'Last week': (relative_end - relativedelta(weeks=1), relative_end), # noqa: T400
- 'Last month': (relative_end - relativedelta(months=1), relative_end), # noqa: E501, T400
- 'Last quarter': (relative_end - relativedelta(months=3), relative_end), # noqa: E501, T400
- 'Last year': (relative_end - relativedelta(years=1), relative_end), # noqa: T400
+ 'Last day': (relative_start - relativedelta(days=1), relative_end), # noqa: T400
+ 'Last week': (relative_start - relativedelta(weeks=1), relative_end), # noqa: E501, T400
+ 'Last month': (relative_start - relativedelta(months=1), relative_end), # noqa: E501, T400
+ 'Last quarter': (relative_start - relativedelta(months=3), relative_end), # noqa: E501, T400
+ 'Last year': (relative_start - relativedelta(years=1), relative_end), # noqa: E501, T400
}
if time_range:
@@ -988,10 +990,10 @@ def get_since_until(time_range: Optional[str] = None,
else:
rel, num, grain = time_range.split()
if rel == 'Last':
- since = relative_end - relativedelta(**{grain: int(num)}) # noqa: T400
+ since = relative_start - relativedelta(**{grain: int(num)}) # noqa: T400
until = relative_end
else: # rel == 'Next'
- since = relative_end
+ since = relative_start
until = relative_end + relativedelta(**{grain: int(num)}) # noqa: T400
else:
since = since or ''
diff --git a/superset/viz.py b/superset/viz.py
index 8eb0620..a6864d3 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -59,6 +59,7 @@ from superset.utils.core import (
config = app.config
stats_logger = config.get('STATS_LOGGER')
+relative_start = config.get('DEFAULT_RELATIVE_START_TIME', 'today')
relative_end = config.get('DEFAULT_RELATIVE_END_TIME', 'today')
METRIC_KEYS = [
@@ -274,7 +275,8 @@ class BaseViz(object):
# default order direction
order_desc = form_data.get('order_desc', True)
- since, until = utils.get_since_until(relative_end=relative_end,
+ since, until = utils.get_since_until(relative_start=relative_start,
+ relative_end=relative_end,
time_range=form_data.get('time_range'),
since=form_data.get('since'),
until=form_data.get('until'))
@@ -800,7 +802,8 @@ class CalHeatmapViz(BaseViz):
values[str(v / 10**9)] = obj.get(metric)
data[metric] = values
- start, end = utils.get_since_until(relative_end=relative_end,
+ start, end = utils.get_since_until(relative_start=relative_start,
+ relative_end=relative_end,
time_range=form_data.get('time_range'),
since=form_data.get('since'),
until=form_data.get('until'))
diff --git a/tests/utils_tests.py b/tests/utils_tests.py
index 40dedaf..a39631b 100644
--- a/tests/utils_tests.py
+++ b/tests/utils_tests.py
@@ -43,7 +43,9 @@ from superset.utils.core import (
def mock_parse_human_datetime(s):
- if s in ['now', 'today']:
+ if s == 'now':
+ return datetime(2016, 11, 7, 9, 30, 10)
+ elif s == 'today':
return datetime(2016, 11, 7)
elif s == 'yesterday':
return datetime(2016, 11, 6)
@@ -51,6 +53,8 @@ def mock_parse_human_datetime(s):
return datetime(2016, 11, 8)
elif s == 'Last year':
return datetime(2015, 11, 7)
+ elif s == 'Last week':
+ return datetime(2015, 10, 31)
elif s == 'Last 5 months':
return datetime(2016, 6, 7)
elif s == 'Next 5 months':
@@ -600,7 +604,7 @@ class UtilsTestCase(unittest.TestCase):
self.assertEqual(result, expected)
result = get_since_until(' : now')
- expected = None, datetime(2016, 11, 7)
+ expected = None, datetime(2016, 11, 7, 9, 30, 10)
self.assertEqual(result, expected)
result = get_since_until('yesterday : tomorrow')
@@ -636,7 +640,19 @@ class UtilsTestCase(unittest.TestCase):
self.assertEqual(result, expected)
result = get_since_until(time_range='5 days : now')
- expected = datetime(2016, 11, 2), datetime(2016, 11, 7)
+ expected = datetime(2016, 11, 2), datetime(2016, 11, 7, 9, 30, 10)
+ self.assertEqual(result, expected)
+
+ result = get_since_until('Last week', relative_end='now')
+ expected = datetime(2016, 10, 31), datetime(2016, 11, 7, 9, 30, 10)
+ self.assertEqual(result, expected)
+
+ result = get_since_until('Last week', relative_start='now')
+ expected = datetime(2016, 10, 31, 9, 30, 10), datetime(2016, 11, 7)
+ self.assertEqual(result, expected)
+
+ result = get_since_until('Last week', relative_start='now', relative_end='now')
+ expected = datetime(2016, 10, 31, 9, 30, 10), datetime(2016, 11, 7, 9, 30, 10)
self.assertEqual(result, expected)
with self.assertRaises(ValueError):