From 419e44b178cfa0f1af64769ffbd7dfa73f19a85b Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 16 May 2016 11:43:17 -0400 Subject: [PATCH] Fix date format for agg_count and get_test_counts_in_date_range() This commit fixes an issue with the date formatting on the agg_count subunit2sql-graph command to be consistent with the other commands and actually use the ISO8601 format like the docs say it does. However, because the actual str parsing and format were in the DB API (and for several releases) we need to gracefully handle the switchover to anything else. So this commit updates get_test_counts_in_date_range() to also take in a datetime object and updates the docs to indicate the previous str parameters are deprecated. It then updates the agg_count command to own it's own string parsing and just pass a datetime object to the DB api. Change-Id: Ie7c67941e59c70285263611803f73b23b69ee06b Story: #2000581 --- ...counts_in_date_range-b16d285cab135d52.yaml | 10 +++++++ subunit2sql/analysis/agg_count.py | 9 +++++- subunit2sql/db/api.py | 14 +++++++-- subunit2sql/tests/db/test_api.py | 29 ++++++++++++++++++- 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/deprecate-str-dates-on-get_test_counts_in_date_range-b16d285cab135d52.yaml diff --git a/releasenotes/notes/deprecate-str-dates-on-get_test_counts_in_date_range-b16d285cab135d52.yaml b/releasenotes/notes/deprecate-str-dates-on-get_test_counts_in_date_range-b16d285cab135d52.yaml new file mode 100644 index 0000000..146c33d --- /dev/null +++ b/releasenotes/notes/deprecate-str-dates-on-get_test_counts_in_date_range-b16d285cab135d52.yaml @@ -0,0 +1,10 @@ +--- +deprecations: + - Passing in the date as a string in the format "%b %d %Y" to the function + get_test_counts_in_date_rage() in the DB API. Instead pass the date in + as a datetime object. +fixes: + - Setting the date as an ISO8601, as indicated by the docs and --help, for + the subunit2sql-graph command agg_count will now work correctly. It would + previously stack trace. (Story 2000581) + diff --git a/subunit2sql/analysis/agg_count.py b/subunit2sql/analysis/agg_count.py index 7e3806c..49da590 100644 --- a/subunit2sql/analysis/agg_count.py +++ b/subunit2sql/analysis/agg_count.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from dateutil import parser as date_parser from oslo_config import cfg import pandas as pd @@ -48,13 +49,19 @@ def generate_series(): 'failure': int(test.failure), } else: + start_date = None + stop_date = None + if CONF.start_date: + start_date = date_parser.parse(CONF.start_date) + if CONF.stop_date: + stop_date = date_parser.parse(CONF.stop_date) if CONF.command.test_ids: ids = [api.get_id_from_test_id(x) for x in CONF.command.test_ids] else: ids = api.get_ids_for_all_tests(session) for test in ids: test_dict[test] = api.get_test_counts_in_date_range( - test, CONF.start_date, CONF.stop_date, session) + test, start_date, stop_date, session) if CONF.command.no_success_graph: for test in test_dict: test_dict[test].pop('success') diff --git a/subunit2sql/db/api.py b/subunit2sql/db/api.py index 4532c90..2356616 100644 --- a/subunit2sql/db/api.py +++ b/subunit2sql/db/api.py @@ -1209,14 +1209,22 @@ def get_test_counts_in_date_range(test_id, start_date=None, stop_date=None, certain date range :param str test_id: The test_id's ID(big integer) to identify the test - :param str start_date: The date to use as the start for counting - :param str stop_date: The date to use as the cutoff for counting + :param datetime start_date: The date to use as the start for counting. A + str in the datetime str format "%b %d %Y" was + the previous format here and will still work + but is deprecated in favor of passing in a + datetime object. + :param datetime stop_date: The date to use as the cutoff for counting. A + str in the datetime str format "%b %d %Y" was + the previous format here and will still work but + is deprecated in favor of passing in a datetime. :param session: Optional session object if one isn't provided a new session will be acquired for the duration of this operation :return: A dict containing the number of successes, failures, and skips :rtype: dict """ - start_date = datetime.datetime.strptime(start_date, '%b %d %Y') + if isinstance(start_date, str): + start_date = datetime.datetime.strptime(start_date, '%b %d %Y') if isinstance(stop_date, str): stop_date = datetime.datetime.strptime(stop_date, '%b %d %Y') session = session or get_session() diff --git a/subunit2sql/tests/db/test_api.py b/subunit2sql/tests/db/test_api.py index 7c76aee..8dfb17b 100644 --- a/subunit2sql/tests/db/test_api.py +++ b/subunit2sql/tests/db/test_api.py @@ -949,7 +949,7 @@ class TestDatabaseAPI(base.TestCase): self.assertIn(run_b.uuid, res) self.assertIn(run_c.uuid, res) - def test_get_test_counts_in_date_range(self): + def test_get_test_counts_in_date_range_as_str(self): timestamp_str_a = 'Dec 01 2015' timestamp_str_b = 'Dec 20 2015' timestamp_a = datetime.datetime(2015, 12, 2, 10, 00, 00) @@ -976,6 +976,33 @@ class TestDatabaseAPI(base.TestCase): self.assertEqual(1, res['failure']) self.assertEqual(0, res['skips']) + def test_get_test_counts_in_date_range(self): + timestamp_a = datetime.datetime(2015, 12, 2, 10, 00, 00) + timestamp_b = timestamp_a + datetime.timedelta(minutes=10) + timestamp_c = timestamp_a + datetime.timedelta(minutes=20) + timestamp_d = datetime.datetime(2015, 12, 22, 10, 00, 00) + timerange_a = datetime.datetime(2015, 12, 1) + timerange_b = datetime.datetime(2015, 12, 20) + run_a = api.create_run() + run_b = api.create_run() + run_c = api.create_run() + run_d = api.create_run() + test = api.create_test('fake_test') + api.create_test_run(test.id, run_a.id, 'success', + timestamp_a, timestamp_b) + api.create_test_run(test.id, run_b.id, 'fail', + timestamp_a, timestamp_c) + api.create_test_run(test.id, run_c.id, 'success', + timestamp_a, timestamp_d) + api.create_test_run(test.id, run_d.id, 'skip', + timestamp_c, timestamp_d) + res = api.get_test_counts_in_date_range(test.id, + timerange_a, + timerange_b) + self.assertEqual(1, res['success']) + self.assertEqual(1, res['failure']) + self.assertEqual(0, res['skips']) + def test_get_failing_test_ids_from_runs_by_key_value(self): test_a = api.create_test('fake_test') test_b = api.create_test('fake_test1')