From e2d6fd5cc63eee5cd2c715a1db02e8b4780e0c8c Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Mon, 6 Jan 2020 18:15:35 +0100 Subject: [PATCH 1/6] Fixed issues with deepcopy so that Fields are cached when a deepcopy is triggered via @immutable function in an instance of DataSet or Widget. Fixed some issues where the ability to use "is" comparison on fields made things a lot cleaner. Got rid of some field copying in some tests. --- fireant/dataset/data_blending.py | 2 +- fireant/dataset/fields.py | 22 +- fireant/dataset/klass.py | 17 +- fireant/dataset/modifiers.py | 18 +- fireant/dataset/references.py | 2 +- .../builder/dataset_blender_query_builder.py | 6 +- .../queries/builder/dataset_query_builder.py | 6 +- fireant/queries/builder/query_builder.py | 43 +- fireant/queries/finders.py | 25 +- fireant/queries/reference_helper.py | 52 +- fireant/queries/sql_transformer.py | 19 +- fireant/tests/dataset/mocks.py | 49 +- fireant/tests/dataset/test_execution.py | 305 +- .../tests/queries/test_build_data_blending.py | 94 +- .../tests/queries/test_build_references.py | 1465 +++-- fireant/tests/queries/test_pagination.py | 238 +- fireant/tests/widgets/test_highcharts.py | 5023 ++++++++++------- fireant/tests/widgets/test_reacttable.py | 2978 +++++----- fireant/utils.py | 57 +- fireant/widgets/base.py | 15 + fireant/widgets/chart_base.py | 45 +- 21 files changed, 6080 insertions(+), 4401 deletions(-) diff --git a/fireant/dataset/data_blending.py b/fireant/dataset/data_blending.py index 99891a9a..cb91b4b9 100644 --- a/fireant/dataset/data_blending.py +++ b/fireant/dataset/data_blending.py @@ -1,7 +1,7 @@ from fireant.dataset.fields import Field from fireant.dataset.klass import DataSet -from fireant.queries.builder import DataSetBlenderQueryBuilder from fireant.utils import immutable +from fireant.queries.builder import DataSetBlenderQueryBuilder class DataSetBlender: diff --git a/fireant/dataset/fields.py b/fireant/dataset/fields.py index 7210c80b..81e5a86b 100644 --- a/fireant/dataset/fields.py +++ b/fireant/dataset/fields.py @@ -2,7 +2,6 @@ from enum import Enum from functools import wraps -from fireant.utils import immutable from pypika.enums import Arithmetic from pypika.terms import ( ArithmeticExpression, @@ -20,6 +19,7 @@ RangeFilter, VoidFilter, ) +from ..utils import immutable class DataType(Enum): @@ -115,6 +115,22 @@ def __init__( self.precision = precision self.hyperlink_template = hyperlink_template + def __copy__(self): + cls = self.__class__ + result = cls.__new__(cls) + result.__dict__.update(self.__dict__) + return result + + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + from copy import deepcopy + + for k, v in self.__dict__.items(): + setattr(result, k, deepcopy(v, memo)) + return result + @property def is_aggregate(self): return self.definition.is_aggregate @@ -177,7 +193,8 @@ def notin(self, values): An iterable of value to constrain the dataset query results by. :return: - A dataset query filter used to filter a dataset query to results where this dimension is *not* one of a set of + A dataset query filter used to filter a dataset query to results where this dimension is *not* one of a + set of values. Opposite of #isin. """ return ExcludesFilter(self, values) @@ -284,3 +301,4 @@ def get_sql(self, **kwargs): @immutable def share(self): self._share = True + return self diff --git a/fireant/dataset/klass.py b/fireant/dataset/klass.py index 9fbee890..89e4e825 100644 --- a/fireant/dataset/klass.py +++ b/fireant/dataset/klass.py @@ -1,11 +1,11 @@ import itertools +from fireant.utils import immutable from fireant.queries.builder import ( DataSetQueryBuilder, DimensionChoicesQueryBuilder, DimensionLatestQueryBuilder, ) -from fireant.utils import immutable class _Container(object): @@ -29,6 +29,14 @@ def __init__(self, items=()): for item in items: setattr(self, item.alias, item) + def __copy__(self): + return type(self)(self._items) + + def __deepcopy__(self, memodict): + for field in self: + memodict[id(field)] = field + return type(self)(self._items) + def __iter__(self): return iter(self._items) @@ -45,10 +53,7 @@ def __contains__(self, item): return False self_item = getattr(self, item.alias, None) - if self_item is None: - return False - - return str(item.definition) == str(self_item.definition) + return item is self_item def __hash__(self): return hash((item for item in self._items)) @@ -71,7 +76,7 @@ def append(self, item): setattr(self, item.alias, item) -class DataSet(object): +class DataSet: """ The DataSet class abstracts the query generation, given the fields and what not that were provided, and the fetching of the aforementioned query's data. diff --git a/fireant/dataset/modifiers.py b/fireant/dataset/modifiers.py index 478659a4..4156d436 100644 --- a/fireant/dataset/modifiers.py +++ b/fireant/dataset/modifiers.py @@ -1,3 +1,5 @@ +from copy import deepcopy + from fireant.utils import immutable from pypika import NullValue @@ -9,6 +11,20 @@ def __init__(self, wrapped): wrapped_key = super().__getattribute__("wrapped_key") setattr(self, wrapped_key, wrapped) + def __copy__(self): + cls = self.__class__ + result = cls.__new__(cls) + result.__dict__.update(self.__dict__) + return result + + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + setattr(result, k, deepcopy(v, memo)) + return result + def __getattr__(self, attr): if attr in self.__dict__: return super().__getattribute__(attr) @@ -41,7 +57,7 @@ def __repr__(self): @immutable def for_(self, wrapped): - wrapped_key = super().__getattribute__("wrapped_key") + wrapped_key = super(type(self), self).__getattribute__("wrapped_key") setattr(self, wrapped_key, wrapped) diff --git a/fireant/dataset/references.py b/fireant/dataset/references.py index 607c1605..270fef73 100644 --- a/fireant/dataset/references.py +++ b/fireant/dataset/references.py @@ -36,7 +36,7 @@ def __init__(self, field, reference_type, delta=False, delta_percent=False): def __eq__(self, other): return ( isinstance(self, Reference) - and self.field == other.field + and self.field is other.field and self.alias == other.alias ) diff --git a/fireant/queries/builder/dataset_blender_query_builder.py b/fireant/queries/builder/dataset_blender_query_builder.py index cffe70ab..96e7181d 100644 --- a/fireant/queries/builder/dataset_blender_query_builder.py +++ b/fireant/queries/builder/dataset_blender_query_builder.py @@ -11,6 +11,7 @@ from fireant.queries.finders import ( find_dataset_metrics, find_metrics_for_widgets, + find_field_in_modified_field, ) from fireant.reference_helpers import reference_alias from fireant.utils import alias_selector @@ -38,9 +39,10 @@ def _flatten_blend_datasets(dataset) -> List: def _replace_field(dimension, field_map, omit_umapped=False): - if hasattr(dimension, "dimension"): + root_dimension = find_field_in_modified_field(dimension) + if root_dimension is not dimension: # Handle modified dimensions - wrapped_dimension = _replace_field(dimension.dimension, field_map) + wrapped_dimension = _replace_field(root_dimension, field_map) return dimension.for_(wrapped_dimension) if field_map is None: diff --git a/fireant/queries/builder/dataset_query_builder.py b/fireant/queries/builder/dataset_query_builder.py index f926d55e..55ba595d 100644 --- a/fireant/queries/builder/dataset_query_builder.py +++ b/fireant/queries/builder/dataset_query_builder.py @@ -21,7 +21,6 @@ from ..field_helper import initialize_orders from ..finders import ( find_and_group_references_for_dimensions, - find_and_replace_reference_dimensions, find_metrics_for_widgets, find_operations_for_widgets, find_share_dimensions, @@ -87,9 +86,6 @@ def sql(self): metrics = find_metrics_for_widgets(self._widgets) operations = find_operations_for_widgets(self._widgets) share_dimensions = find_share_dimensions(self._dimensions, operations) - references = find_and_replace_reference_dimensions( - self._references, self._dimensions - ) orders = initialize_orders(self._orders, self._dimensions) return make_slicer_query_with_totals_and_references( @@ -101,7 +97,7 @@ def sql(self): metrics, operations, self._filters, - references, + self._references, orders, share_dimensions=share_dimensions, ) diff --git a/fireant/queries/builder/query_builder.py b/fireant/queries/builder/query_builder.py index 67e4322b..58c48c05 100644 --- a/fireant/queries/builder/query_builder.py +++ b/fireant/queries/builder/query_builder.py @@ -1,11 +1,9 @@ from fireant.dataset.fields import Field from fireant.exceptions import DataSetException -from fireant.utils import ( - alias_selector, - immutable, -) +from fireant.utils import immutable from pypika import Order from ..execution import fetch_data +from ..finders import find_fields_in_modified_fields class QueryException(DataSetException): @@ -29,6 +27,28 @@ def get_column_names(database, table): return {column_definition[0] for column_definition in column_definitions} +def _strip_modifiers(fields): + for field in fields: + next = field + while hasattr(next, "dimension"): + next = next.dimension + yield next + + +def _validate_fields(fields, dataset): + fields = find_fields_in_modified_fields(fields) + invalid = [field.alias for field in fields if field not in dataset.fields] + + if not invalid: + return + + raise DataSetException( + "Only fields from dataset can be used in a dataset query. Found invalid fields: {}.".format( + ", ".join(invalid) + ) + ) + + class QueryBuilder(object): """ This is the base class for building dataset queries. This class provides an interface for building dataset queries @@ -54,6 +74,7 @@ def dimension(self, *dimensions): :return: A copy of the query with the dimensions added. """ + _validate_fields(dimensions, self.dataset) aliases = {dimension.alias for dimension in self._dimensions} self._dimensions += [ dimension for dimension in dimensions if dimension.alias not in aliases @@ -69,6 +90,7 @@ def filter(self, *filters): :return: A copy of the query with the filters added. """ + _validate_fields([fltr.field for fltr in filters], self.dataset) self._filters += [f for f in filters] @immutable @@ -81,6 +103,8 @@ def orderby(self, field: Field, orientation: Order = None): :return: A copy of the query with the order by added. """ + _validate_fields([field], self.dataset) + if self._orders is None: self._orders = [] @@ -131,7 +155,7 @@ def fetch(self, hint=None): Fetches the data for this query instance and returns it in an instance of `pd.DataFrame` :param hint: - For database vendors that support it, add a query hint to collect analytics on the queries triggerd by + For database vendors that support it, add a query hint to collect analytics on the queries triggered by fireant. """ queries = add_hints(self.sql, hint) @@ -139,7 +163,7 @@ def fetch(self, hint=None): return fetch_data(self.dataset.database, queries, self._dimensions) -class ReferenceQueryBuilderMixin(object): +class ReferenceQueryBuilderMixin: """ This is a mixin class for building dataset queries that allow references. This class provides an interface for building dataset queries via a set of functions which can be chained together. @@ -159,10 +183,11 @@ def reference(self, *references): :return: A copy of the query with the references added. """ + _validate_fields([reference.field for reference in references], self.dataset) self._references += references -class WidgetQueryBuilderMixin(object): +class WidgetQueryBuilderMixin: """ This is a mixin class for building dataset queries that allow widgets. This class provides an interface for building dataset queries via a set of functions which can be chained together. @@ -187,4 +212,8 @@ def widget(self, *widgets): :return: A copy of the query with the widgets added. """ + _validate_fields( + [field for widget in widgets for field in widget.metrics], self.dataset + ) + self._widgets += widgets diff --git a/fireant/queries/finders.py b/fireant/queries/finders.py index 2bd5ebcd..58ac7fc4 100644 --- a/fireant/queries/finders.py +++ b/fireant/queries/finders.py @@ -1,4 +1,3 @@ -import copy from collections import ( defaultdict, namedtuple, @@ -186,24 +185,18 @@ def find_filters_for_totals(filters): return [fltr for fltr in filters if not isinstance(fltr, OmitFromRollup)] -def find_and_replace_reference_dimensions(references, dimensions): +def find_field_in_modified_field(field): """ - Finds the dimension for a reference in the query if there is one and replaces it. This is to force the reference to - use the same modifiers with a dimension if it is selected in the query. - - :param references: - :param dimensions: - :return: + Returns the field from a modified field argument (or just the field argument if it is not modified). """ - dimensions_by_key = {dimension.alias: dimension for dimension in dimensions} + root = field + while hasattr(root, "dimension"): + root = root.dimension + return root + - reference_copies = [] - for reference in map(copy.deepcopy, references): - dimension = dimensions_by_key.get(reference.field.alias) - if dimension is not None: - reference.field = dimension - reference_copies.append(reference) - return reference_copies +def find_fields_in_modified_fields(fields): + return [find_field_in_modified_field(field) for field in fields] interval_weekdays = { diff --git a/fireant/queries/reference_helper.py b/fireant/queries/reference_helper.py index 703f6056..4d62f6c1 100644 --- a/fireant/queries/reference_helper.py +++ b/fireant/queries/reference_helper.py @@ -2,54 +2,54 @@ from functools import partial from fireant.dataset.fields import Field -from fireant.dataset.modifiers import Rollup from .field_helper import make_term_for_dimension +from .finders import find_field_in_modified_field def adapt_for_reference_query( - dataset, reference_parts, database, dimensions, metrics, filters, references + reference_parts, database, dimensions, metrics, filters, references ): if reference_parts is None: return dimensions, metrics, filters ref_dimension, time_unit, interval = reference_parts # Unpack rolled up dimensions - ref_dimension = ( - ref_dimension.dimension if isinstance(ref_dimension, Rollup) else ref_dimension - ) + ref_dimension = find_field_in_modified_field(ref_dimension) - ref_metrics = _make_reference_metrics( - dataset, metrics, references[0].reference_type.alias - ) + ref_metrics = _make_reference_metrics(metrics, references[0].reference_type.alias) offset_func = partial(database.date_add, date_part=time_unit, interval=interval) ref_dimensions = _make_reference_dimensions( - database, dimensions, ref_dimension, offset_func + dimensions, ref_dimension, offset_func, database.trunc_date ) ref_filters = _make_reference_filters(filters, ref_dimension, offset_func) return ref_dimensions, ref_metrics, ref_filters -def _make_reference_dimensions(database, dimensions, ref_dimension, offset_func): - def replace_reference_dimension(dimension): - ref_dimension_copy = copy.copy(dimension) - if hasattr(ref_dimension_copy, "dimension"): - ref_dimension_copy.dimension = copy.copy(dimension.dimension) +def _replace_reference_dimension(dimension, offset_func, trunc_date=None): + ref_definition = offset_func(make_term_for_dimension(dimension, trunc_date)) + field = Field( + alias=dimension.alias, + definition=ref_definition, + data_type=dimension.data_type, + label=dimension.label, + ) - ref_definition = make_term_for_dimension( - ref_dimension_copy, database.trunc_date - ) - ref_dimension_copy.definition = offset_func(ref_definition) - return ref_dimension_copy + if hasattr(dimension, "for_"): + return dimension.for_(field) + return field + + +def _make_reference_dimensions(dimensions, ref_dimension, offset_func, trunc_date): return [ - replace_reference_dimension(dimension) - if dimension is ref_dimension + _replace_reference_dimension(dimension, offset_func, trunc_date) + if ref_dimension is find_field_in_modified_field(dimension) else dimension for dimension in dimensions ] -def _make_reference_metrics(dataset, metrics, ref_key): +def _make_reference_metrics(metrics, ref_key): metric_copies = [] for metric in [copy.deepcopy(metric) for metric in metrics]: @@ -63,6 +63,7 @@ def _make_reference_metrics(dataset, metrics, ref_key): Field( "{}_{}".format(metric.alias, ref_key), metric.definition, + data_type=metric.data_type, label=metric.label, prefix=metric.prefix, suffix=metric.suffix, @@ -87,9 +88,10 @@ def _make_reference_filters(filters, ref_dimension, offset_func): reference_filters = [] for ref_filter in filters: - if ref_filter.field.alias == ref_dimension.alias: - ref_filter = copy.deepcopy(ref_filter) - ref_filter.field.definition = offset_ref_dimension_definition + if ref_filter.field is ref_dimension: + offset_ref_field = _replace_reference_dimension(ref_dimension, offset_func) + ref_filter = ref_filter.for_(offset_ref_field) + reference_filters.append(ref_filter) return reference_filters diff --git a/fireant/queries/sql_transformer.py b/fireant/queries/sql_transformer.py index 7ba0a0de..96e9d725 100644 --- a/fireant/queries/sql_transformer.py +++ b/fireant/queries/sql_transformer.py @@ -81,31 +81,30 @@ def make_slicer_query_with_totals_and_references( queries = [] for totals_dimension in totals_dimensions_and_none: - (dimensions_for_totals, filters_for_totals) = adapt_for_totals_query( + (dimensions_with_totals, filters_with_totals) = adapt_for_totals_query( totals_dimension, dimensions, filters ) for reference_parts, references in reference_groups_and_none: ( - dimensions_for_ref, - metrics_for_ref, - filters_for_ref, + dimensions_with_ref, + metrics_with_ref, + filters_with_ref, ) = adapt_for_reference_query( - dataset, reference_parts, database, - dimensions_for_totals, + dimensions_with_totals, metrics, - filters_for_totals, + filters_with_totals, references, ) query = make_slicer_query( database, table, joins, - dimensions_for_ref, - metrics_for_ref, - filters_for_ref, + dimensions_with_ref, + metrics_with_ref, + filters_with_ref, orders, ) diff --git a/fireant/tests/dataset/mocks.py b/fireant/tests/dataset/mocks.py index dceb0000..e2d9bb4c 100644 --- a/fireant/tests/dataset/mocks.py +++ b/fireant/tests/dataset/mocks.py @@ -65,6 +65,7 @@ def __eq__(self, other): label="Party", definition=politicians_table.political_party, data_type=DataType.text, + hyperlink_template="http://example.com/{political_party}", ), Field( "candidate-id", @@ -77,6 +78,7 @@ def __eq__(self, other): label="Candidate Name", definition=politicians_table.candidate_name, data_type=DataType.text, + hyperlink_template="http://example.com/{political_party}/{candidate-name}", ), Field( "election-id", @@ -137,7 +139,7 @@ def __eq__(self, other): definition=fn.Sum(politicians_table.is_winner), prefix="$", thousands="_", - suffix="€", + precision=0, ), ], joins=[ @@ -188,6 +190,12 @@ def __eq__(self, other): definition=politicians_spend_table.election_year, data_type=DataType.number, ), + Field( + "state", + label="State", + definition=politicians_spend_table.state, + data_type=DataType.text, + ), ], ).extra_fields( Field( @@ -455,47 +463,48 @@ def PoliticsRow( ) mock_politics_database = pd.DataFrame.from_records(records, columns=df_columns) +mock_politics_database[f("wins_with_style")] = mock_politics_database[f("wins")] +mock_politics_database[f("turnout")] = 25 * mock_politics_database[f("wins")] dimx0_metricx1_df = pd.DataFrame(mock_politics_database[[f("votes")]].sum()).T -dimx0_metricx2_df = pd.DataFrame( - mock_politics_database[[f("votes"), f("wins")]].sum() -).T +metrics = [f("votes"), f("wins"), f("wins_with_style"), f("turnout")] +dimx0_metricx2_df = pd.DataFrame(mock_politics_database[metrics].sum()).T dimx1_date_df = ( - mock_politics_database[[f("timestamp"), f("votes"), f("wins")]] - .groupby(f("timestamp")) - .sum() + mock_politics_database[[f("timestamp")] + metrics].groupby(f("timestamp")).sum() ) no_index_df = pd.DataFrame(dimx1_date_df.sum()).T dimx1_str_df = ( - mock_politics_database[[f("political_party"), f("votes"), f("wins")]] + mock_politics_database[[f("political_party")] + metrics] .groupby(f("political_party")) .sum() ) -dimx1_none_df = pd.DataFrame(mock_politics_database[[f("votes"), f("wins")]].sum()).T +dimx1_none_df = pd.DataFrame(mock_politics_database[metrics].sum()).T dimx1_num_df = ( - mock_politics_database[[f("candidate-id"), f("votes"), f("wins")]] + mock_politics_database[[f("candidate-id")] + metrics] .groupby(f("candidate-id")) .sum() ) dimx2_str_num_df = ( - mock_politics_database[ - [f("political_party"), f("candidate-id"), f("votes"), f("wins")] - ] + mock_politics_database[[f("political_party"), f("candidate-id")] + metrics] .groupby([f("political_party"), f("candidate-id")]) .sum() ) +dimx2_str_str_df = ( + mock_politics_database[[f("political_party"), f("candidate-name")] + metrics] + .groupby([f("political_party"), f("candidate-name")]) + .sum() +) + dimx2_date_str_df = ( - mock_politics_database[ - [f("timestamp"), f("political_party"), f("votes"), f("wins")] - ] + mock_politics_database[[f("timestamp"), f("political_party")] + metrics] .groupby([f("timestamp"), f("political_party")]) .sum() ) @@ -507,15 +516,13 @@ def PoliticsRow( ) dimx2_date_num_df = ( - mock_politics_database[[f("timestamp"), f("candidate-id"), f("votes"), f("wins")]] + mock_politics_database[[f("timestamp"), f("candidate-id")] + metrics] .groupby([f("timestamp"), f("candidate-id")]) .sum() ) dimx3_date_str_str_df = ( - mock_politics_database[ - [f("timestamp"), f("political_party"), f("state"), f("votes"), f("wins")] - ] + mock_politics_database[[f("timestamp"), f("political_party"), f("state")] + metrics] .groupby([f("timestamp"), f("political_party"), f("state")]) .sum() ) @@ -549,7 +556,7 @@ def ref_delta(ref_data_frame, columns): return ref_data_frame.join(delta_data_frame) -_columns = [f("votes"), f("wins")] +_columns = metrics dimx2_date_str_ref_df = ref(dimx2_date_str_df, _columns) dimx2_date_str_ref_delta_df = ref_delta(dimx2_date_str_ref_df, _columns) diff --git a/fireant/tests/dataset/test_execution.py b/fireant/tests/dataset/test_execution.py index e782a617..4138c1c7 100644 --- a/fireant/tests/dataset/test_execution.py +++ b/fireant/tests/dataset/test_execution.py @@ -12,10 +12,7 @@ import pandas as pd import pandas.testing -from fireant import ( - DayOverDay, - VerticaDatabase, -) +from fireant import DayOverDay from fireant.dataset.modifiers import Rollup from fireant.dataset.totals import get_totals_marker_for_dtype from fireant.queries.execution import ( @@ -39,7 +36,8 @@ politicians_table, ) -pd.set_option('display.expand_frame_repr', False) +pd.set_option("display.expand_frame_repr", False) +metrics = ["$votes", "$wins", "$wins_with_style", "$turnout"] def replace_totals(data_frame): @@ -54,11 +52,10 @@ def replace_totals(data_frame): class TestFetchData(TestCase): - @classmethod def setUpClass(cls): - query_a = Query.from_(politicians_table).select('*') - query_b = Query.from_(politicians_hint_table).select('*') + query_a = Query.from_(politicians_table).select("*") + query_b = Query.from_(politicians_hint_table).select("*") cls.test_dimensions = () cls.test_queries = [query_a, query_b] @@ -70,7 +67,10 @@ def setUpClass(cls): def test_fetch_data(self, reduce_mock): database = MagicMock() database.max_result_set_size = 5 - database.fetch_dataframes.return_value = [self.test_result_a, self.test_result_b] + database.fetch_dataframes.return_value = [ + self.test_result_a, + self.test_result_b, + ] mocked_result = pd.DataFrame([{"a": 1.0}]) reduce_mock.return_value = mocked_result @@ -78,9 +78,13 @@ def test_fetch_data(self, reduce_mock): result = fetch_data(database, self.test_queries, self.test_dimensions) pandas.testing.assert_frame_equal(mocked_result, result) - database.fetch_dataframes.assert_called_with('SELECT * FROM "politics"."politician" LIMIT 5', - 'SELECT * FROM "politics"."hints" LIMIT 5') - reduce_mock.assert_called_once_with([self.test_result_a, self.test_result_b], (), self.test_dimensions, ()) + database.fetch_dataframes.assert_called_with( + 'SELECT * FROM "politics"."politician" LIMIT 5', + 'SELECT * FROM "politics"."hints" LIMIT 5', + ) + reduce_mock.assert_called_once_with( + [self.test_result_a, self.test_result_b], (), self.test_dimensions, () + ) class ReduceResultSetsTests(TestCase): @@ -112,7 +116,10 @@ def test_reduce_single_result_set_with_date_str_dimensions_dates(self): expected = dimx2_date_str_df raw_df = replace_totals(expected) - dimensions = (mock_dataset.fields.timestamp, mock_dataset.fields.political_party) + dimensions = ( + mock_dataset.fields.timestamp, + mock_dataset.fields.political_party, + ) result = reduce_result_set([raw_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) @@ -120,7 +127,10 @@ def test_reduce_single_result_set_with_str_num_dimensions(self): expected = dimx2_str_num_df.sort_index() raw_df = replace_totals(expected) - dimensions = (mock_dataset.fields.political_party, mock_dataset.fields['candidate-id']) + dimensions = ( + mock_dataset.fields.political_party, + mock_dataset.fields["candidate-id"], + ) result = reduce_result_set([raw_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) @@ -128,23 +138,29 @@ def test_reduce_single_result_set_with_date_str_str_dimensions(self): expected = dimx3_date_str_str_df raw_df = replace_totals(expected) - dimensions = (mock_dataset.fields.timestamp, mock_dataset.fields.political_party, mock_dataset.fields.state) + dimensions = ( + mock_dataset.fields.timestamp, + mock_dataset.fields.political_party, + mock_dataset.fields.state, + ) result = reduce_result_set([raw_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) class ReduceResultSetsWithReferencesTests(TestCase): def test_reduce_delta_percent_result_set_with_zeros_in_reference_value(self): - raw_df = pd.DataFrame([[date(2019, 1, 2), 1], - [date(2019, 1, 3), 2]], - columns=['$timestamp', '$metric']) - ref_df = pd.DataFrame([[date(2019, 1, 2), 2], - [date(2019, 1, 3), 0]], - columns=['$timestamp', '$metric_dod']) + raw_df = pd.DataFrame( + [[date(2019, 1, 2), 1], [date(2019, 1, 3), 2]], + columns=["$timestamp", "$metric"], + ) + ref_df = pd.DataFrame( + [[date(2019, 1, 2), 2], [date(2019, 1, 3), 0]], + columns=["$timestamp", "$metric_dod"], + ) expected = raw_df.copy() - expected['$metric_dod_delta_percent'] = [-50, np.nan] - expected.set_index('$timestamp', inplace=True) + expected["$metric_dod_delta_percent"] = [-50, np.nan] + expected.set_index("$timestamp", inplace=True) timestamp = mock_dataset.fields.timestamp reference_groups = ([DayOverDay(timestamp, delta_percent=True)],) @@ -154,15 +170,17 @@ def test_reduce_delta_percent_result_set_with_zeros_in_reference_value(self): pandas.testing.assert_frame_equal(expected, result) def test_reduce_delta_result_with_non_aligned_index(self): - raw_df = pd.DataFrame([[date(2019, 1, 2), 1], - [date(2019, 1, 3), 2]], - columns=['$timestamp', '$metric']) - ref_df = pd.DataFrame([[date(2019, 1, 2), 2]], - columns=['$timestamp', '$metric_dod']) + raw_df = pd.DataFrame( + [[date(2019, 1, 2), 1], [date(2019, 1, 3), 2]], + columns=["$timestamp", "$metric"], + ) + ref_df = pd.DataFrame( + [[date(2019, 1, 2), 2]], columns=["$timestamp", "$metric_dod"] + ) expected = raw_df.copy() - expected['$metric_dod_delta'] = [-1., 2.] - expected.set_index('$timestamp', inplace=True) + expected["$metric_dod_delta"] = [-1.0, 2.0] + expected.set_index("$timestamp", inplace=True) timestamp = mock_dataset.fields.timestamp reference_groups = ([DayOverDay(timestamp, delta=True)],) @@ -176,11 +194,13 @@ class ReduceResultSetsWithTotalsTests(TestCase): def test_reduce_single_result_set_with_str_dimension(self): expected = dimx1_str_totals_df raw_df = replace_totals(dimx1_str_df) - totals_df = pd.merge(pd.DataFrame([None], columns=['$political_party']), - pd.DataFrame([raw_df[['$votes', '$wins']].sum(axis=0)]), - how='outer', - left_index=True, - right_index=True) + totals_df = pd.merge( + pd.DataFrame([None], columns=["$political_party"]), + pd.DataFrame([raw_df[metrics].sum(axis=0)]), + how="outer", + left_index=True, + right_index=True, + ) dimensions = (Rollup(mock_dataset.fields.political_party),) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) @@ -188,17 +208,22 @@ def test_reduce_single_result_set_with_str_dimension(self): pandas.testing.assert_frame_equal(expected, result) def test_reduce_single_result_set_with_dimx2_date_str_totals_date(self): - expected = dimx2_date_str_totalsx2_df.loc[(slice(None), slice('Democrat', 'Republican')), :] \ - .append(dimx2_date_str_totalsx2_df.iloc[-1]) + expected = dimx2_date_str_totalsx2_df.loc[ + (slice(None), slice("Democrat", "Republican")), : + ].append(dimx2_date_str_totalsx2_df.iloc[-1]) raw_df = replace_totals(dimx2_date_str_df) - totals_df = pd.merge(pd.DataFrame([[None, None]], columns=['$timestamp', '$political_party']), - pd.DataFrame([raw_df[['$votes', '$wins']].sum(axis=0)]), - how='outer', - left_index=True, - right_index=True) - - dimensions = (Rollup(mock_dataset.fields.timestamp), - mock_dataset.fields.political_party) + totals_df = pd.merge( + pd.DataFrame([[None, None]], columns=["$timestamp", "$political_party"]), + pd.DataFrame([raw_df[metrics].sum(axis=0)]), + how="outer", + left_index=True, + right_index=True, + ) + + dimensions = ( + Rollup(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) @@ -206,110 +231,152 @@ def test_reduce_single_result_set_with_dimx2_date_str_totals_date(self): def test_reduce_single_result_set_with_date_str_dimensions_str_totals(self): expected = dimx2_date_str_totals_df raw_df = replace_totals(dimx2_date_str_df) - totals_df = raw_df.groupby('$timestamp').sum().reset_index() - totals_df['$political_party'] = None - totals_df = totals_df[['$timestamp', '$political_party', '$votes', '$wins']] - - dimensions = (mock_dataset.fields.timestamp, - Rollup(mock_dataset.fields.political_party)) + totals_df = raw_df.groupby("$timestamp").sum().reset_index() + totals_df["$political_party"] = None + totals_df = totals_df[["$timestamp", "$political_party"] + metrics] + + dimensions = ( + mock_dataset.fields.timestamp, + Rollup(mock_dataset.fields.political_party), + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) def test_reduce_single_result_set_with_dimx2_date_str_str_totals_date(self): - expected = dimx3_date_str_str_totalsx3_df.loc[(slice(None), - slice('Democrat', 'Republican'), - slice('California', 'Texas')), :] \ - .append(dimx3_date_str_str_totalsx3_df.iloc[-1]) + expected = dimx3_date_str_str_totalsx3_df.loc[ + ( + slice(None), + slice("Democrat", "Republican"), + slice("California", "Texas"), + ), + :, + ].append(dimx3_date_str_str_totalsx3_df.iloc[-1]) raw_df = replace_totals(dimx3_date_str_str_df) - totals_df = pd.merge(pd.DataFrame([[None, None, None]], - columns=['$timestamp', '$political_party', '$state']), - pd.DataFrame([raw_df[['$votes', '$wins']].sum(axis=0)]), - how='outer', - left_index=True, - right_index=True) - totals_df = totals_df[['$timestamp', '$political_party', '$state', - '$votes', '$wins']] - - dimensions = (Rollup(mock_dataset.fields.timestamp), - mock_dataset.fields.political_party, - mock_dataset.fields.state) + totals_df = pd.merge( + pd.DataFrame( + [[None, None, None]], + columns=["$timestamp", "$political_party", "$state"], + ), + pd.DataFrame([raw_df[metrics].sum(axis=0)]), + how="outer", + left_index=True, + right_index=True, + ) + totals_df = totals_df[["$timestamp", "$political_party", "$state"] + metrics] + + dimensions = ( + Rollup(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + mock_dataset.fields.state, + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) def test_reduce_single_result_set_with_date_str_str_dimensions_str1_totals(self): - expected = dimx3_date_str_str_totalsx3_df.loc[(slice(None), - slice(None), - slice('California', 'Texas')), :] \ - .append(dimx3_date_str_str_totalsx3_df.loc[(slice(None), '~~totals'), :].iloc[:-1]) \ + expected = ( + dimx3_date_str_str_totalsx3_df.loc[ + (slice(None), slice(None), slice("California", "Texas")), : + ] + .append( + dimx3_date_str_str_totalsx3_df.loc[(slice(None), "~~totals"), :].iloc[ + :-1 + ] + ) .sort_index() + ) raw_df = replace_totals(dimx3_date_str_str_df) - totals_df = raw_df.groupby('$timestamp').sum().reset_index() - totals_df['$political_party'] = None - totals_df['$state'] = None - totals_df = totals_df[['$timestamp', '$political_party', '$state', - '$votes', '$wins']] - - dimensions = (mock_dataset.fields.timestamp, - Rollup(mock_dataset.fields.political_party), - mock_dataset.fields.state) + totals_df = raw_df.groupby("$timestamp").sum().reset_index() + totals_df["$political_party"] = None + totals_df["$state"] = None + totals_df = totals_df[["$timestamp", "$political_party", "$state"] + metrics] + + dimensions = ( + mock_dataset.fields.timestamp, + Rollup(mock_dataset.fields.political_party), + mock_dataset.fields.state, + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) def test_reduce_single_result_set_with_date_str_str_dimensions_str2_totals(self): - expected = dimx3_date_str_str_totalsx3_df.loc[(slice(None), slice('Democrat', 'Republican')), :] + expected = dimx3_date_str_str_totalsx3_df.loc[ + (slice(None), slice("Democrat", "Republican")), : + ] raw_df = replace_totals(dimx3_date_str_str_df) - totals_df = raw_df.groupby(['$timestamp', '$political_party']).sum().reset_index() - totals_df['$state'] = None - totals_df = totals_df[['$timestamp', '$political_party', '$state', - '$votes', '$wins']] - - dimensions = (mock_dataset.fields.timestamp, - mock_dataset.fields.political_party, - Rollup(mock_dataset.fields.state)) + totals_df = ( + raw_df.groupby(["$timestamp", "$political_party"]).sum().reset_index() + ) + totals_df["$state"] = None + totals_df = totals_df[["$timestamp", "$political_party", "$state"] + metrics] + + dimensions = ( + mock_dataset.fields.timestamp, + mock_dataset.fields.political_party, + Rollup(mock_dataset.fields.state), + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) - @skip('BAN-2594') - def test_reduce_single_result_set_with_date_str_str_dimensions_str1_totals_with_null_in_date_dim(self): + @skip("BAN-2594") + def test_reduce_single_result_set_with_date_str_str_dimensions_str1_totals_with_null_in_date_dim( + self, + ): index_names = list(dimx3_date_str_str_totalsx3_df.index.names) - nulls = pd.DataFrame([[np.nan, 'd', '1', 'Texas', 5, 0], [np.nan, 'd', '2', 'California', 2, 0], - [np.nan, 'i', '1', 'Texas', 5, 0], [np.nan, 'i', '2', 'California', 7, 0], - [np.nan, 'r', '1', 'Texas', 11, 0], [np.nan, 'r', '2', 'California', 3, 0]], - columns=index_names + list(dimx3_date_str_str_totalsx3_df.columns)) - nulls_totals = pd.DataFrame([nulls[['$votes', '$wins']].sum()]) + nulls = pd.DataFrame( + [ + [np.nan, "d", "1", "Texas", 5, 0], + [np.nan, "d", "2", "California", 2, 0], + [np.nan, "i", "1", "Texas", 5, 0], + [np.nan, "i", "2", "California", 7, 0], + [np.nan, "r", "1", "Texas", 11, 0], + [np.nan, "r", "2", "California", 3, 0], + ], + columns=index_names + list(dimx3_date_str_str_totalsx3_df.columns), + ) + nulls_totals = pd.DataFrame([nulls[metrics].sum()]) nulls_totals[index_names[0]] = np.nan - nulls_totals[index_names[1]] = '~~totals' - nulls_totals[index_names[2]] = '~~totals' - - expected = dimx3_date_str_str_totalsx3_df.loc[(slice(None), slice(None), slice('1', '2')), :] \ - .append(dimx3_date_str_str_totalsx3_df.loc[(slice(None), '~~totals'), :].iloc[:-1]) \ - .append(nulls.set_index(index_names)) \ - .append(nulls_totals.set_index(index_names)) \ + nulls_totals[index_names[1]] = "~~totals" + nulls_totals[index_names[2]] = "~~totals" + + expected = ( + dimx3_date_str_str_totalsx3_df.loc[ + (slice(None), slice(None), slice("1", "2")), : + ] + .append( + dimx3_date_str_str_totalsx3_df.loc[(slice(None), "~~totals"), :].iloc[ + :-1 + ] + ) + .append(nulls.set_index(index_names)) + .append(nulls_totals.set_index(index_names)) .sort_index() + ) raw_df = replace_totals(dimx3_date_str_str_df) - raw_df = nulls \ - .append(raw_df) \ - .sort_values(['$timestamp', '$political_party', '$state']) - - totals_df = raw_df.groupby('$timestamp').sum().reset_index() - null_totals_df = pd.DataFrame([raw_df[raw_df['$timestamp'].isnull()] - [['$votes', '$wins']].sum()]) - null_totals_df['$timestamp'] = None + raw_df = nulls.append(raw_df).sort_values( + ["$timestamp", "$political_party", "$state"] + ) + + totals_df = raw_df.groupby("$timestamp").sum().reset_index() + null_totals_df = pd.DataFrame( + [raw_df[raw_df["$timestamp"].isnull()][metrics].sum()] + ) + null_totals_df["$timestamp"] = None totals_df = totals_df.append(null_totals_df) - totals_df['$political_party'] = None - totals_df['$state'] = None - totals_df = totals_df[['$timestamp', '$political_party', '$state', - '$votes', '$wins']] - - dimensions = (mock_dataset.fields.timestamp, - Rollup(mock_dataset.fields.political_party), - mock_dataset.fields.state) + totals_df["$political_party"] = None + totals_df["$state"] = None + totals_df = totals_df[["$timestamp", "$political_party", "$state"] + metrics] + + dimensions = ( + mock_dataset.fields.timestamp, + Rollup(mock_dataset.fields.political_party), + mock_dataset.fields.state, + ) result = reduce_result_set([raw_df, totals_df], (), dimensions, ()) pandas.testing.assert_frame_equal(expected, result) diff --git a/fireant/tests/queries/test_build_data_blending.py b/fireant/tests/queries/test_build_data_blending.py index 57c239ce..a0700396 100644 --- a/fireant/tests/queries/test_build_data_blending.py +++ b/fireant/tests/queries/test_build_data_blending.py @@ -2,8 +2,8 @@ import fireant as f from fireant.tests.dataset.mocks import ( - Rollup, DataSetException, + Rollup, mock_dataset_blender, ) @@ -260,6 +260,50 @@ def test_multiple_metrics_with_an_order_by_in_query_applies_order_to_wrapping_qu str(queries[0]), ) + def test_blend_data_set_on_query_using_joins(self): + query = ( + mock_dataset_blender.query() + .widget( + f.ReactTable(mock_dataset_blender.fields["candidate-spend-per-wins"]) + ) + .dimension( + f.day(mock_dataset_blender.fields.timestamp), + mock_dataset_blender.fields.state, + ) + ) + + self.assertEqual( + "SELECT " + '"sq0"."$timestamp" "$timestamp",' + '"sq0"."$state" "$state",' + '"sq1"."$candidate-spend"/"sq0"."$wins" "$candidate-spend-per-wins" ' + "FROM (" + "SELECT " + 'TRUNC("politician"."timestamp",\'DD\') "$timestamp",' + '"state"."state_name" "$state",' + 'SUM("politician"."is_winner") "$wins" ' + 'FROM "politics"."politician" ' + 'FULL OUTER JOIN "locations"."district" ' + 'ON "politician"."district_id"="district"."id" ' + 'JOIN "locations"."state" ' + 'ON "district"."state_id"="state"."id" ' + 'GROUP BY "$timestamp","$state" ORDER BY "$timestamp","$state"' + ') "sq0" ' + "LEFT JOIN (" + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + '"state" "$state",' + 'SUM("candidate_spend") "$candidate-spend" ' + 'FROM "politics"."politician_spend" ' + 'GROUP BY "$timestamp","$state" ORDER BY "$timestamp","$state"' + ') "sq1" ' + "ON " + '"sq0"."$timestamp"="sq1"."$timestamp" ' + 'AND "sq0"."$state"="sq1"."$state" ' + 'ORDER BY "$timestamp","$state"', + str(query.sql[0]), + ) + def test_apply_reference_to_blended_query(self): query = ( mock_dataset_blender.query() @@ -275,30 +319,30 @@ def test_apply_reference_to_blended_query(self): self.assertEqual(len(sql), 2) (base_query, ref_query) = sql - with self.subTest("base query"): - self.assertEqual( - "SELECT " - '"sq0"."$timestamp" "$timestamp",' - '"sq1"."$candidate-spend"/"sq0"."$wins" "$candidate-spend-per-wins" ' - "FROM (" - "SELECT " - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("is_winner") "$wins" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ORDER BY "$timestamp"' - ') "sq0" ' - "LEFT JOIN (" - "SELECT " - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("candidate_spend") "$candidate-spend" ' - 'FROM "politics"."politician_spend" ' - 'GROUP BY "$timestamp" ORDER BY "$timestamp"' - ') "sq1" ' - "ON " - '"sq0"."$timestamp"="sq1"."$timestamp" ' - 'ORDER BY "$timestamp"', - str(base_query), - ) + # with self.subTest("base query"): + self.assertEqual( + "SELECT " + '"sq0"."$timestamp" "$timestamp",' + '"sq1"."$candidate-spend"/"sq0"."$wins" "$candidate-spend-per-wins" ' + "FROM (" + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("is_winner") "$wins" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ORDER BY "$timestamp"' + ') "sq0" ' + "LEFT JOIN (" + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("candidate_spend") "$candidate-spend" ' + 'FROM "politics"."politician_spend" ' + 'GROUP BY "$timestamp" ORDER BY "$timestamp"' + ') "sq1" ' + "ON " + '"sq0"."$timestamp"="sq1"."$timestamp" ' + 'ORDER BY "$timestamp"', + str(base_query), + ) with self.subTest("ref query"): self.assertEqual( "SELECT " diff --git a/fireant/tests/queries/test_build_references.py b/fireant/tests/queries/test_build_references.py index 3217a132..984f26ee 100644 --- a/fireant/tests/queries/test_build_references.py +++ b/fireant/tests/queries/test_build_references.py @@ -16,260 +16,358 @@ class QueryBuilderDatetimeReferenceTests(TestCase): def test_reference_with_no_dimensions_or_filters_creates_same_query(self): # TODO reduce this to a single query - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician"', str(queries[0])) - - with self.subTest('reference query is same as base query'): - self.assertEqual('SELECT ' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician"', str(queries[1])) - - def test_reference_without_selecting_reference_dimension_using_date_range_filter(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(mock_dataset.fields.political_party) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ - .filter(mock_dataset.fields.timestamp.between(date(2000, 1, 1), date(2000, 3, 1))) \ + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " 'SUM("votes") "$votes" ' 'FROM "politics"."politician"', + str(queries[0]), + ) + + with self.subTest("reference query is same as base query"): + self.assertEqual( + "SELECT " 'SUM("votes") "$votes_dod" ' 'FROM "politics"."politician"', + str(queries[1]), + ) + + def test_reference_without_selecting_ref_dimension_using_date_range_filter(self): + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(mock_dataset.fields.political_party) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) + .filter( + mock_dataset.fields.timestamp.between( + date(2000, 1, 1), date(2000, 3, 1) + ) + ) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - '"political_party" "$political_party",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'WHERE "timestamp" BETWEEN \'2000-01-01\' AND \'2000-03-01\' ' - 'GROUP BY "$political_party" ' - 'ORDER BY "$political_party"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - '"political_party" "$political_party",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'WHERE TIMESTAMPADD(\'day\',1,"timestamp") BETWEEN \'2000-01-01\' AND \'2000-03-01\' ' - 'GROUP BY "$political_party" ' - 'ORDER BY "$political_party"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + '"political_party" "$political_party",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + "WHERE \"timestamp\" BETWEEN '2000-01-01' AND '2000-03-01' " + 'GROUP BY "$political_party" ' + 'ORDER BY "$political_party"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + '"political_party" "$political_party",' + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + "WHERE TIMESTAMPADD('day',1,\"timestamp\") BETWEEN '2000-01-01' AND '2000-03-01' " + 'GROUP BY "$political_party" ' + 'ORDER BY "$political_party"', + str(queries[1]), + ) def test_dod(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_wow(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.WeekOverWeek(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.WeekOverWeek(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_wow" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_wow" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_mom(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.MonthOverMonth(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.MonthOverMonth(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',4,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_mom" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',4,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_mom" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_qoq(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.QuarterOverQuarter(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.QuarterOverQuarter(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',12,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_qoq" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',12,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_qoq" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_yoy(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.YearOverYear(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.YearOverYear(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',52,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',52,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_mom_with_monthly_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_monthly) \ - .reference(f.MonthOverMonth(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_monthly) + .reference(f.MonthOverMonth(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'MM\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'month\',1,TRUNC("timestamp",\'MM\')),\'MM\') "$timestamp",' - 'SUM("votes") "$votes_mom" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'MM\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('month',1,TRUNC(\"timestamp\",'MM')),'MM') \"$timestamp\"," + 'SUM("votes") "$votes_mom" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_qoq_with_monthly_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_monthly) \ - .reference(f.QuarterOverQuarter(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_monthly) + .reference(f.QuarterOverQuarter(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'MM\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'quarter\',1,TRUNC("timestamp",\'MM\')),\'MM\') "$timestamp",' - 'SUM("votes") "$votes_qoq" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'MM\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('quarter',1,TRUNC(\"timestamp\",'MM')),'MM') \"$timestamp\"," + 'SUM("votes") "$votes_qoq" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_yoy_with_monthly_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_monthly) \ - .reference(f.YearOverYear(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_monthly) + .reference(f.YearOverYear(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'MM\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'year\',1,TRUNC("timestamp",\'MM\')),\'MM\') "$timestamp",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'MM\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('year',1,TRUNC(\"timestamp\",'MM')),'MM') \"$timestamp\"," + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) # noinspection SqlDialectInspection,SqlNoDataSourceInspection @@ -277,56 +375,76 @@ class QueryBuilderDatetimeReferenceWithDeltaTests(TestCase): maxDiff = None def test_delta(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp, delta=True)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp, delta=True)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_delta_percentage(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp, delta_percent=True)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp, delta_percent=True)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) # noinspection SqlDialectInspection,SqlNoDataSourceInspection @@ -335,134 +453,184 @@ class QueryBuilderDatetimeReferenceIntervalTests(TestCase): def test_date_dim_with_weekly_interval(self): weekly_timestamp = f.week(mock_dataset.fields.timestamp) - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(weekly_timestamp) \ - .reference(f.DayOverDay(weekly_timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(weekly_timestamp) + .reference(f.DayOverDay(weekly_timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'IW\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'IW\')),\'IW\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'IW\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'IW')),'IW') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_date_dim_with_weekly_interval_no_interval_on_reference(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(f.week(mock_dataset.fields.timestamp)) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(f.week(mock_dataset.fields.timestamp)) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'IW\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'IW\')),\'IW\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'IW\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'IW')),'IW') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_date_dim_with_monthly_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(f.month(mock_dataset.fields.timestamp)) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(f.month(mock_dataset.fields.timestamp)) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'MM\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'MM\')),\'MM\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'MM\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'MM')),'MM') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_date_dim_with_quarterly_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(f.quarter(mock_dataset.fields.timestamp)) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(f.quarter(mock_dataset.fields.timestamp)) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'Q\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'Q\')),\'Q\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'Q\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'Q')),'Q') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_date_dim_with_annual_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(f.year(mock_dataset.fields.timestamp)) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(f.year(mock_dataset.fields.timestamp)) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'Y\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'Y\')),\'Y\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'Y\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'Y')),'Y') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) # noinspection SqlDialectInspection,SqlNoDataSourceInspection @@ -470,131 +638,190 @@ class QueryBuilderDatetimeMultipleReferencesTests(TestCase): maxDiff = None def test_dimension_with_multiple_references(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ - .reference(f.YearOverYear(mock_dataset.fields.timestamp, delta_percent=True)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) + .reference( + f.YearOverYear(mock_dataset.fields.timestamp, delta_percent=True) + ) .sql + ) self.assertEqual(3, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',52,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[2])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',52,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[2]), + ) def test_adding_duplicate_reference_does_not_join_more_queries(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp), - f.DayOverDay(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference( + f.DayOverDay(mock_dataset.fields.timestamp), + f.DayOverDay(mock_dataset.fields.timestamp), + ) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) - - def test_use_same_nested_query_for_joining_references_with_same_period_and_dimension(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp), - f.DayOverDay(mock_dataset.fields.timestamp, delta=True), - f.DayOverDay(mock_dataset.fields.timestamp, delta_percent=True)) \ + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) + + def test_use_same_nested_query_for_joining_references_with_same_period_and_dimension( + self, + ): + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference( + f.DayOverDay(mock_dataset.fields.timestamp), + f.DayOverDay(mock_dataset.fields.timestamp, delta=True), + f.DayOverDay(mock_dataset.fields.timestamp, delta_percent=True), + ) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) - - def test_use_same_nested_query_for_joining_references_with_same_period_and_dimension_with_different_periods(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp), - f.DayOverDay(mock_dataset.fields.timestamp, delta=True), - f.YearOverYear(mock_dataset.fields.timestamp), - f.YearOverYear(mock_dataset.fields.timestamp, delta=True)) \ + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) + + def test_use_same_nested_query_for_joining_references_with_same_period_and_dimension_with_different_periods( + self, + ): + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference( + f.DayOverDay(mock_dataset.fields.timestamp), + f.DayOverDay(mock_dataset.fields.timestamp, delta=True), + # also work with modified dimensions + f.YearOverYear(timestamp_daily), + f.YearOverYear(timestamp_daily, delta=True), + ) .sql + ) self.assertEqual(3, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('second query for all DoD references'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) - - with self.subTest('third query for all YoY references'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',52,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[2])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest("second query for all DoD references"): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) + + with self.subTest("third query for all YoY references"): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',52,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[2]), + ) # noinspection SqlDialectInspection,SqlNoDataSourceInspection @@ -602,126 +829,173 @@ class QueryBuilderDatetimeReferenceMiscellaneousTests(TestCase): maxDiff = None def test_reference_queries_with_multiple_dimensions_includes_all_dimensions(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .dimension(mock_dataset.fields.political_party) \ - .reference(f.YearOverYear(mock_dataset.fields.timestamp)) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .dimension(mock_dataset.fields.political_party) + .reference(f.YearOverYear(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - '"political_party" "$political_party",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp","$political_party" ' - 'ORDER BY "$timestamp","$political_party"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',52,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - '"political_party" "$political_party",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp","$political_party" ' - 'ORDER BY "$timestamp","$political_party"', str(queries[1])) - - def test_reference_with_dimension_using_display_definition_includes_it_in_all_queries(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .dimension(mock_dataset.fields['candidate-name']) \ - .reference(f.YearOverYear(mock_dataset.fields.timestamp)) \ + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + '"political_party" "$political_party",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp","$political_party" ' + 'ORDER BY "$timestamp","$political_party"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',52,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + '"political_party" "$political_party",' + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp","$political_party" ' + 'ORDER BY "$timestamp","$political_party"', + str(queries[1]), + ) + + def test_reference_with_dimension_using_display_definition_includes_it_in_all_queries( + self, + ): + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .dimension(mock_dataset.fields["candidate-name"]) + .reference(f.YearOverYear(mock_dataset.fields.timestamp)) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - '"candidate_name" "$candidate-name",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp","$candidate-name" ' - 'ORDER BY "$timestamp","$candidate-name"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',52,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - '"candidate_name" "$candidate-name",' - 'SUM("votes") "$votes_yoy" ' - 'FROM "politics"."politician" ' - 'GROUP BY "$timestamp","$candidate-name" ' - 'ORDER BY "$timestamp","$candidate-name"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + '"candidate_name" "$candidate-name",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp","$candidate-name" ' + 'ORDER BY "$timestamp","$candidate-name"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',52,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + '"candidate_name" "$candidate-name",' + 'SUM("votes") "$votes_yoy" ' + 'FROM "politics"."politician" ' + 'GROUP BY "$timestamp","$candidate-name" ' + 'ORDER BY "$timestamp","$candidate-name"', + str(queries[1]), + ) def test_filters_on_reference_dimension_are_adapted_to_reference_interval(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ - .filter(mock_dataset.fields.timestamp - .between(date(2018, 1, 1), date(2018, 1, 31))) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) + .filter( + mock_dataset.fields.timestamp.between( + date(2018, 1, 1), date(2018, 1, 31) + ) + ) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'WHERE "timestamp" BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'WHERE TIMESTAMPADD(\'day\',1,"timestamp") BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + "WHERE \"timestamp\" BETWEEN '2018-01-01' AND '2018-01-31' " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + "WHERE TIMESTAMPADD('day',1,\"timestamp\") BETWEEN '2018-01-01' AND '2018-01-31' " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) def test_filters_on_other_dimensions_are_not_adapted(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(timestamp_daily) \ - .reference(f.DayOverDay(mock_dataset.fields.timestamp)) \ - .filter(mock_dataset.fields.timestamp - .between(date(2018, 1, 1), date(2018, 1, 31))) \ - .filter(mock_dataset.fields.political_party - .isin(['d'])) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(timestamp_daily) + .reference(f.DayOverDay(mock_dataset.fields.timestamp)) + .filter( + mock_dataset.fields.timestamp.between( + date(2018, 1, 1), date(2018, 1, 31) + ) + ) + .filter(mock_dataset.fields.political_party.isin(["d"])) .sql + ) self.assertEqual(2, len(queries)) - with self.subTest('base query is same as without reference'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'WHERE "timestamp" BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'AND "political_party" IN (\'d\') ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[0])) - - with self.subTest('reference query is same as base query with filter on reference dimension shifted'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'day\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_dod" ' - 'FROM "politics"."politician" ' - 'WHERE TIMESTAMPADD(\'day\',1,"timestamp") BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'AND "political_party" IN (\'d\') ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(queries[1])) + with self.subTest("base query is same as without reference"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + "WHERE \"timestamp\" BETWEEN '2018-01-01' AND '2018-01-31' " + "AND \"political_party\" IN ('d') " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[0]), + ) + + with self.subTest( + "reference query is same as base query with filter on reference dimension shifted" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('day',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_dod" ' + 'FROM "politics"."politician" ' + "WHERE TIMESTAMPADD('day',1,\"timestamp\") BETWEEN '2018-01-01' AND '2018-01-31' " + "AND \"political_party\" IN ('d') " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(queries[1]), + ) # noinspection SqlDialectInspection,SqlNoDataSourceInspection @@ -729,49 +1003,70 @@ class QueryBuilderReferencesWithRollupTests(TestCase): maxDiff = None def test_reference_with_rollup_dimension_and_date_range_filter(self): - queries = mock_dataset.query \ - .widget(f.HighCharts() - .axis(f.HighCharts.LineSeries(mock_dataset.fields.votes))) \ - .dimension(Rollup(timestamp_daily)) \ - .reference(f.WeekOverWeek(mock_dataset.fields.timestamp)) \ - .filter(mock_dataset.fields.timestamp - .between(date(2018, 1, 1), date(2018, 1, 31))) \ + queries = ( + mock_dataset.query.widget( + f.HighCharts().axis(f.HighCharts.LineSeries(mock_dataset.fields.votes)) + ) + .dimension(Rollup(timestamp_daily)) + .reference(f.WeekOverWeek(mock_dataset.fields.timestamp)) + .filter( + mock_dataset.fields.timestamp.between( + date(2018, 1, 1), date(2018, 1, 31) + ) + ) .sql + ) self.assertEqual(4, len(queries)) base, reference, base_rollup, reference_rollup = queries - with self.subTest('base query applies dimensions and date range filter'): - self.assertEqual('SELECT ' - 'TRUNC("timestamp",\'DD\') "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'WHERE "timestamp" BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(base)) - - with self.subTest('reference query shifts timestamp dimension and date range filter by a week'): - self.assertEqual('SELECT ' - 'TRUNC(TIMESTAMPADD(\'week\',1,TRUNC("timestamp",\'DD\')),\'DD\') "$timestamp",' - 'SUM("votes") "$votes_wow" ' - 'FROM "politics"."politician" ' - 'WHERE TIMESTAMPADD(\'week\',1,"timestamp") BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'GROUP BY "$timestamp" ' - 'ORDER BY "$timestamp"', str(reference)) - - with self.subTest('totals query selects NULL for timestamp dimension'): - self.assertEqual('SELECT ' - 'NULL "$timestamp",' - 'SUM("votes") "$votes" ' - 'FROM "politics"."politician" ' - 'WHERE "timestamp" BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'ORDER BY "$timestamp"', str(base_rollup)) - - with self.subTest('reference totals query selects NULL for timestamp dimension and shifts date range filter'): - self.assertEqual('SELECT ' - 'NULL "$timestamp",' - 'SUM("votes") "$votes_wow" ' - 'FROM "politics"."politician" ' - 'WHERE TIMESTAMPADD(\'week\',1,"timestamp") BETWEEN \'2018-01-01\' AND \'2018-01-31\' ' - 'ORDER BY "$timestamp"', str(reference_rollup)) + with self.subTest("base query applies dimensions and date range filter"): + self.assertEqual( + "SELECT " + 'TRUNC("timestamp",\'DD\') "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + "WHERE \"timestamp\" BETWEEN '2018-01-01' AND '2018-01-31' " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(base), + ) + + with self.subTest( + "reference query shifts timestamp dimension and date range filter by a week" + ): + self.assertEqual( + "SELECT " + "TRUNC(TIMESTAMPADD('week',1,TRUNC(\"timestamp\",'DD')),'DD') \"$timestamp\"," + 'SUM("votes") "$votes_wow" ' + 'FROM "politics"."politician" ' + "WHERE TIMESTAMPADD('week',1,\"timestamp\") BETWEEN '2018-01-01' AND '2018-01-31' " + 'GROUP BY "$timestamp" ' + 'ORDER BY "$timestamp"', + str(reference), + ) + + with self.subTest("totals query selects NULL for timestamp dimension"): + self.assertEqual( + "SELECT " + 'NULL "$timestamp",' + 'SUM("votes") "$votes" ' + 'FROM "politics"."politician" ' + "WHERE \"timestamp\" BETWEEN '2018-01-01' AND '2018-01-31' " + 'ORDER BY "$timestamp"', + str(base_rollup), + ) + + with self.subTest( + "reference totals query selects NULL for timestamp dimension and shifts date range filter" + ): + self.assertEqual( + "SELECT " + 'NULL "$timestamp",' + 'SUM("votes") "$votes_wow" ' + 'FROM "politics"."politician" ' + "WHERE TIMESTAMPADD('week',1,\"timestamp\") BETWEEN '2018-01-01' AND '2018-01-31' " + 'ORDER BY "$timestamp"', + str(reference_rollup), + ) diff --git a/fireant/tests/queries/test_pagination.py b/fireant/tests/queries/test_pagination.py index c4beb85e..aabf89f1 100644 --- a/fireant/tests/queries/test_pagination.py +++ b/fireant/tests/queries/test_pagination.py @@ -1,14 +1,14 @@ from unittest import TestCase - -import numpy as np -import pandas as pd -from pandas.testing import assert_frame_equal from unittest.mock import ( ANY, Mock, patch, ) +import numpy as np +import pandas as pd +from pandas.testing import assert_frame_equal + from fireant.queries.pagination import paginate from fireant.tests.dataset.mocks import ( dimx2_date_bool_df, @@ -18,7 +18,7 @@ ) from pypika import Order -TS = '$timestamp' +TS = "$timestamp" mock_table_widget = Mock() mock_table_widget.group_pagination = False @@ -27,21 +27,25 @@ mock_chart_widget.group_pagination = True mock_dimension_definition = Mock() -mock_dimension_definition.alias = '$political_party' +mock_dimension_definition.alias = "$political_party" mock_metric_definition = Mock() -mock_metric_definition.alias = '$votes' +mock_metric_definition.alias = "$votes" class SimplePaginationTests(TestCase): - @patch('fireant.queries.pagination._simple_paginate') - def test_that_with_no_widgets_using_group_pagination_that_simple_pagination_is_applied(self, mock_paginate): + @patch("fireant.queries.pagination._simple_paginate") + def test_that_with_no_widgets_using_group_pagination_that_simple_pagination_is_applied( + self, mock_paginate + ): paginate(dimx2_date_str_df, [mock_table_widget]) mock_paginate.assert_called_once_with(ANY, ANY, ANY, ANY) - @patch('fireant.queries.pagination._simple_paginate') - def test_that_with_group_pagination_and_one_dimension_that_simple_pagination_is_applied(self, mock_paginate): + @patch("fireant.queries.pagination._simple_paginate") + def test_that_with_group_pagination_and_one_dimension_that_simple_pagination_is_applied( + self, mock_paginate + ): paginate(dimx2_str_num_df, [mock_table_widget]) mock_paginate.assert_called_once_with(ANY, ANY, ANY, ANY) @@ -58,56 +62,98 @@ def test_paginate_with_offset_slice_data_frame_from_offset(self): expected = dimx2_date_str_df[5:] assert_frame_equal(expected, paginated) - def test_paginate_with_limit_and_offset_slice_data_frame_from_offset_to_offset_plus_limit(self): + def test_paginate_with_limit_and_offset_slice_data_frame_from_offset_to_offset_plus_limit( + self, + ): paginated = paginate(dimx2_date_str_df, [mock_table_widget], limit=5, offset=5) expected = dimx2_date_str_df[5:10] assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_dimension_asc(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], orders=[(mock_dimension_definition, Order.asc)]) - - expected = dimx2_date_str_df.sort_values(by=[mock_dimension_definition.alias], ascending=True) + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[(mock_dimension_definition, Order.asc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_dimension_definition.alias], ascending=True + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_dimension_desc(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], orders=[(mock_dimension_definition, Order.desc)]) - - expected = dimx2_date_str_df.sort_values(by=[mock_dimension_definition.alias], ascending=False) + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[(mock_dimension_definition, Order.desc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_dimension_definition.alias], ascending=False + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_metric_asc(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], orders=[(mock_metric_definition, Order.asc)]) - - expected = dimx2_date_str_df.sort_values(by=[mock_metric_definition.alias], ascending=True) + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[(mock_metric_definition, Order.asc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_metric_definition.alias], ascending=True + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_metric_desc(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], orders=[(mock_metric_definition, Order.desc)]) - - expected = dimx2_date_str_df.sort_values(by=[mock_metric_definition.alias], ascending=False) + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[(mock_metric_definition, Order.desc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_metric_definition.alias], ascending=False + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_multiple_orders(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], orders=[(mock_dimension_definition, Order.asc), - (mock_metric_definition, Order.desc)]) - - expected = dimx2_date_str_df.sort_values(by=[mock_dimension_definition.alias, mock_metric_definition.alias], - ascending=[True, False]) + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[ + (mock_dimension_definition, Order.asc), + (mock_metric_definition, Order.desc), + ], + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_dimension_definition.alias, mock_metric_definition.alias], + ascending=[True, False], + ) assert_frame_equal(expected, paginated) def test_apply_sort_before_slice(self): - paginated = paginate(dimx2_date_str_df, [mock_table_widget], - orders=[(mock_metric_definition, Order.asc)], - limit=5, offset=5) - - expected = dimx2_date_str_df.sort_values(by=[mock_metric_definition.alias], ascending=True)[5:10] + paginated = paginate( + dimx2_date_str_df, + [mock_table_widget], + orders=[(mock_metric_definition, Order.asc)], + limit=5, + offset=5, + ) + + expected = dimx2_date_str_df.sort_values( + by=[mock_metric_definition.alias], ascending=True + )[5:10] assert_frame_equal(expected, paginated) class GroupPaginationTests(TestCase): - @patch('fireant.queries.pagination._group_paginate') - def test_with_one_widget_using_group_pagination_that_group_pagination_is_applied(self, mock_paginate): + @patch("fireant.queries.pagination._group_paginate") + def test_with_one_widget_using_group_pagination_that_group_pagination_is_applied( + self, mock_paginate + ): paginate(dimx2_date_str_df, [mock_chart_widget, mock_table_widget]) mock_paginate.assert_called_once_with(ANY, ANY, ANY, ANY) @@ -116,84 +162,124 @@ def test_paginate_with_limit_slice_data_frame_to_limit_in_each_group(self): paginated = paginate(dimx2_date_str_df, [mock_chart_widget], limit=2) index = dimx2_date_str_df.index - reindex = pd.MultiIndex.from_product([index.levels[0], - index.levels[1][:2]], - names=index.names) - expected = dimx2_date_str_df.reindex(reindex) \ - .dropna() \ - .astype(np.int64) + reindex = pd.MultiIndex.from_product( + [index.levels[0], index.levels[1][:2]], names=index.names + ) + expected = dimx2_date_str_df.reindex(reindex).dropna().astype(np.int64) assert_frame_equal(expected, paginated) def test_paginate_with_offset_slice_data_frame_from_offset_in_each_group(self): paginated = paginate(dimx2_date_str_df, [mock_chart_widget], offset=2) index = dimx2_date_str_df.index - reindex = pd.MultiIndex.from_product([index.levels[0], - index.levels[1][2:]], - names=index.names) + reindex = pd.MultiIndex.from_product( + [index.levels[0], index.levels[1][2:]], names=index.names + ) expected = dimx2_date_str_df.reindex(reindex) assert_frame_equal(expected, paginated) - def test_paginate_with_limit_and_offset_slice_data_frame_from_offset_to_offset_plus_limit_in_each_group(self): + def test_paginate_with_limit_and_offset_slice_data_frame_from_offset_to_offset_plus_limit_in_each_group( + self, + ): paginated = paginate(dimx2_date_str_df, [mock_chart_widget], limit=1, offset=1) index = dimx2_date_str_df.index - reindex = pd.MultiIndex.from_product([index.levels[0], - index.levels[1][1:2]], - names=index.names) - expected = dimx2_date_str_df.reindex(reindex) \ - .dropna() \ - .astype(np.int64) + reindex = pd.MultiIndex.from_product( + [index.levels[0], index.levels[1][1:2]], names=index.names + ) + expected = dimx2_date_str_df.reindex(reindex).dropna().astype(np.int64) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_dimension_asc(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], orders=[(mock_dimension_definition, Order.asc)]) - - expected = dimx2_date_str_df.sort_values(by=[TS, mock_dimension_definition.alias], - ascending=True) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + orders=[(mock_dimension_definition, Order.asc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[TS, mock_dimension_definition.alias], ascending=True + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_dimension_desc(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], orders=[(mock_dimension_definition, Order.desc)]) - - expected = dimx2_date_str_df.sort_values(by=[TS, mock_dimension_definition.alias], - ascending=(True, False)) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + orders=[(mock_dimension_definition, Order.desc)], + ) + + expected = dimx2_date_str_df.sort_values( + by=[TS, mock_dimension_definition.alias], ascending=(True, False) + ) assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_metric_asc(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], orders=[(mock_metric_definition, Order.asc)]) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + orders=[(mock_metric_definition, Order.asc)], + ) expected = dimx2_date_str_df.iloc[[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]] assert_frame_equal(expected, paginated) def test_apply_sort_with_one_order_metric_desc(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], orders=[(mock_metric_definition, Order.desc)]) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + orders=[(mock_metric_definition, Order.desc)], + ) expected = dimx2_date_str_df.iloc[[2, 0, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11]] assert_frame_equal(expected, paginated) def test_apply_sort_multiple_levels_df(self): - paginated = paginate(dimx3_date_str_str_df, [mock_chart_widget], orders=[(mock_metric_definition, Order.asc)]) - - sorted_groups = dimx3_date_str_str_df.groupby(level=[1, 2]).sum().sort_values(by='$votes', ascending=True).index - expected = dimx3_date_str_str_df \ - .groupby(level=0) \ - .apply(lambda df: df.reset_index(level=0, drop=True).reindex(sorted_groups)) \ + paginated = paginate( + dimx3_date_str_str_df, + [mock_chart_widget], + orders=[(mock_metric_definition, Order.asc)], + ) + + sorted_groups = ( + dimx3_date_str_str_df.groupby(level=[1, 2]) + .sum() + .sort_values(by="$votes", ascending=True) + .index + ) + expected = ( + dimx3_date_str_str_df.groupby(level=0) + .apply(lambda df: df.reset_index(level=0, drop=True).reindex(sorted_groups)) .dropna() - expected[['$votes', '$wins']] = expected[['$votes', '$wins']].astype(np.int64) + ) + metrics = ["$votes", "$wins", "$wins_with_style", "$turnout"] + expected[metrics] = expected[metrics].astype(np.int64) assert_frame_equal(expected, paginated) def test_apply_sort_with_multiple_orders(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], orders=[(mock_dimension_definition, Order.asc), - (mock_metric_definition, Order.desc)]) - - expected = dimx2_date_str_df.sort_values(by=[TS, mock_dimension_definition.alias, mock_metric_definition.alias], - ascending=[True, True, False]) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + orders=[ + (mock_dimension_definition, Order.asc), + (mock_metric_definition, Order.desc), + ], + ) + + expected = dimx2_date_str_df.sort_values( + by=[TS, mock_dimension_definition.alias, mock_metric_definition.alias], + ascending=[True, True, False], + ) assert_frame_equal(expected, paginated) def test_apply_sort_before_slice(self): - paginated = paginate(dimx2_date_str_df, [mock_chart_widget], - limit=1, offset=1, orders=[(mock_metric_definition, Order.asc)]) + paginated = paginate( + dimx2_date_str_df, + [mock_chart_widget], + limit=1, + offset=1, + orders=[(mock_metric_definition, Order.asc)], + ) expected = dimx2_date_str_df.iloc[[0, 3, 5, 7, 9, 11]] assert_frame_equal(expected, paginated) diff --git a/fireant/tests/widgets/test_highcharts.py b/fireant/tests/widgets/test_highcharts.py index 71715a64..38110921 100644 --- a/fireant/tests/widgets/test_highcharts.py +++ b/fireant/tests/widgets/test_highcharts.py @@ -1,7 +1,4 @@ -import copy -from unittest import ( - TestCase, -) +from unittest import TestCase from fireant import ( CumSum, @@ -37,2353 +34,3003 @@ class HighChartsLineChartTransformerTests(TestCase): maxDiff = None chart_class = HighCharts.LineSeries - chart_type = 'line' + chart_type = "line" stacking = None def test_dimx1_metricx1(self): - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [ + (820454400000, 15220449), + (946684800000, 16662017), + (1072915200000, 19614932), + (1199145600000, 21294215), + (1325376000000, 20572210), + (1451606400000, 18310513), + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_dimx1_year(self): - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_date_df, mock_dataset, [year(mock_dataset.fields.timestamp)], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, - }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) - - def test_dimx1_metricx1_prefix(self): - votes = copy.copy(mock_dataset.fields.votes) - votes.prefix = '$' - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(votes)) \ - .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_date_df, mock_dataset, [year(mock_dataset.fields.timestamp)], [] + ) + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [ + (820454400000, 15220449), + (946684800000, 16662017), + (1072915200000, 19614932), + (1199145600000, 21294215), + (1325376000000, 20572210), + (1451606400000, 18310513), + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': '$', - 'valueSuffix': None, - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_dimx1_metricx1_suffix(self): - votes = copy.copy(mock_dataset.fields.votes) - votes.suffix = '%' - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(votes)) \ + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(mock_dataset.fields.turnout)) .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Turnout", + "yAxis": "0", + "data": [ + (820454400000, 50), + (946684800000, 50), + (1072915200000, 50), + (1199145600000, 50), + (1325376000000, 50), + (1451606400000, 50), + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": "%", + "valueDecimals": 2, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': '%', - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) - - def test_dimx1_metricx1_precision(self): - votes = copy.copy(mock_dataset.fields.votes) - votes.precision = 2 - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(votes)) \ - .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) + result, + ) - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + def test_dimx1_metricx1_prefix_precision(self): + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(mock_dataset.fields.wins_with_style)) + .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Wins", + "yAxis": "0", + "data": [ + (820454400000, 2), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 2), + ], + "tooltip": { + "valuePrefix": "$", + "valueSuffix": None, + "valueDecimals": 0, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': 2, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_single_operation_line_chart(self): - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(CumSum(mock_dataset.fields.votes))) \ - .transform(dimx1_date_operation_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(CumSum(mock_dataset.fields.votes))) + .transform( + dimx1_date_operation_df, + mock_dataset, + [mock_dataset.fields.timestamp], + [], + ) + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "CumSum(Votes)", + "yAxis": "0", + "data": [ + (820454400000, 15220449), + (946684800000, 31882466), + (1072915200000, 51497398), + (1199145600000, 72791613), + (1325376000000, 93363823), + (1451606400000, 111674336), + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "CumSum(Votes)", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 31882466), - (1072915200000, 51497398), - (1199145600000, 72791613), - (1325376000000, 93363823), - (1451606400000, 111674336)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_single_metric_with_uni_dim_line_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] - result = HighCharts(title="Time Series with Unique Dimension and Single Metric") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts(title="Time Series with Unique Dimension and Single Metric") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, - }, - "yAxis": [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Single Metric" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [(820454400000, 1076384)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "colors": DEFAULT_COLORS, }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(820454400000, 1076384)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_multi_metrics_single_axis_line_chart(self): - result = HighCharts(title="Time Series with Unique Dimension and Multiple Metrics") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ - .transform(dimx2_date_str_df, mock_dataset, [mock_dataset.fields.timestamp, - mock_dataset.fields.state], []) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Multiple Metrics"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series with Unique Dimension and Multiple Metrics") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) + .transform( + dimx2_date_str_df, + mock_dataset, + [mock_dataset.fields.timestamp, mock_dataset.fields.state], + [], + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Multiple Metrics" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [(820454400000, 1076384)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#7798BF", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#AAEEEE", + "dashStyle": "Solid", + "data": [(820454400000, 0)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#FF0066", + "dashStyle": "Solid", + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(820454400000, 1076384)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#7798BF', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#AAEEEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#FF0066', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_multi_metrics_multi_axis_line_chart(self): - result = HighCharts(title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .axis(self.chart_class(mock_dataset.fields.wins)) \ - .transform(dimx2_date_str_df, mock_dataset, [mock_dataset.fields.timestamp, - mock_dataset.fields.state], []) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts( + title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + ) + .axis(self.chart_class(mock_dataset.fields.votes)) + .axis(self.chart_class(mock_dataset.fields.wins)) + .transform( + dimx2_date_str_df, + mock_dataset, + [mock_dataset.fields.timestamp, mock_dataset.fields.state], + [], + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "1", + "labels": {"style": {"color": "#7798BF"}}, + "title": {"text": None}, + "visible": True, + }, + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [(820454400000, 1076384)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#7798BF", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {"fillColor": "#7798BF", "symbol": "circle"}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#AAEEEE", + "dashStyle": "Solid", + "data": [(820454400000, 0)], + "marker": {"fillColor": "#7798BF", "symbol": "square"}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#FF0066", + "dashStyle": "Solid", + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {"fillColor": "#7798BF", "symbol": "diamond"}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '1', - 'labels': {'style': {'color': '#7798BF'}}, - 'title': {'text': None}, - 'visible': True - }, - { - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(820454400000, 1076384)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#7798BF', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {'fillColor': '#7798BF', 'symbol': 'circle'}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#AAEEEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0)], - 'marker': {'fillColor': '#7798BF', 'symbol': 'square'}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#FF0066', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {'fillColor': '#7798BF', 'symbol': 'diamond'}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_multi_dim_with_totals_line_chart(self): - result = HighCharts(title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .axis(self.chart_class(mock_dataset.fields.wins)) \ - .transform(dimx2_date_str_totals_df, mock_dataset, [mock_dataset.fields.timestamp, - Rollup(mock_dataset.fields.state)], []) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts( + title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + ) + .axis(self.chart_class(mock_dataset.fields.votes)) + .axis(self.chart_class(mock_dataset.fields.wins)) + .transform( + dimx2_date_str_totals_df, + mock_dataset, + [mock_dataset.fields.timestamp, Rollup(mock_dataset.fields.state)], + [], + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "1", + "labels": {"style": {"color": "#AAEEEE"}}, + "title": {"text": None}, + "visible": True, + }, + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [(820454400000, 1076384)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#7798BF", + "dashStyle": "Solid", + "data": [ + (820454400000, 15220449), + (946684800000, 16662017), + (1072915200000, 19614932), + (1199145600000, 21294215), + (1325376000000, 20572210), + (1451606400000, 18310513), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "triangle"}, + "name": "Votes (Totals)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#AAEEEE", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "circle"}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#FF0066", + "dashStyle": "Solid", + "data": [(820454400000, 0)], + "marker": {"fillColor": "#AAEEEE", "symbol": "square"}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#EEAAEE", + "dashStyle": "Solid", + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "diamond"}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 2), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "triangle"}, + "name": "Wins (Totals)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '1', - 'labels': {'style': {'color': '#AAEEEE'}}, - 'title': {'text': None}, - 'visible': True - }, - { - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(820454400000, 1076384)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#7798BF', - 'dashStyle': 'Solid', - 'data': [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'triangle'}, - 'name': 'Votes (Totals)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#AAEEEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'circle'}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#FF0066', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'square'}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#EEAAEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'diamond'}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 2)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'triangle'}, - 'name': 'Wins (Totals)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_multi_dim_with_totals_on_first_dim_line_chart(self): - result = HighCharts(title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .axis(self.chart_class(mock_dataset.fields.wins)) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, [Rollup(mock_dataset.fields.timestamp), - Rollup(mock_dataset.fields.state)], []) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts( + title="Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + ) + .axis(self.chart_class(mock_dataset.fields.votes)) + .axis(self.chart_class(mock_dataset.fields.wins)) + .transform( + dimx2_date_str_totalsx2_df, + mock_dataset, + [ + Rollup(mock_dataset.fields.timestamp), + Rollup(mock_dataset.fields.state), + ], + [], + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Multiple Metrics, Multi-Axis" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "1", + "labels": {"style": {"color": "#AAEEEE"}}, + "title": {"text": None}, + "visible": True, + }, + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [(820454400000, 1076384)], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "diamond"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#7798BF", + "dashStyle": "Solid", + "data": [ + (820454400000, 15220449), + (946684800000, 16662017), + (1072915200000, 19614932), + (1199145600000, 21294215), + (1325376000000, 20572210), + (1451606400000, 18310513), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "triangle"}, + "name": "Votes (Totals)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#AAEEEE", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "circle"}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#FF0066", + "dashStyle": "Solid", + "data": [(820454400000, 0)], + "marker": {"fillColor": "#AAEEEE", "symbol": "square"}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#EEAAEE", + "dashStyle": "Solid", + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "diamond"}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "color": "#DF5353", + "dashStyle": "Solid", + "data": [ + (820454400000, 2), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 2), + ], + "marker": {"fillColor": "#AAEEEE", "symbol": "triangle"}, + "name": "Wins (Totals)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '1', - 'labels': {'style': {'color': '#AAEEEE'}}, - 'title': {'text': None}, - 'visible': True - }, - { - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(820454400000, 1076384)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'diamond'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#7798BF', - 'dashStyle': 'Solid', - 'data': [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'triangle'}, - 'name': 'Votes (Totals)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#AAEEEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'circle'}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#FF0066', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'square'}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#EEAAEE', - 'dashStyle': 'Solid', - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'diamond'}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'color': '#DF5353', - 'dashStyle': 'Solid', - 'data': [(820454400000, 2), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 2)], - 'marker': {'fillColor': '#AAEEEE', 'symbol': 'triangle'}, - 'name': 'Wins (Totals)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_uni_dim_with_ref_line_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] references = [ElectionOverElection(mock_dataset.fields.timestamp)] - result = HighCharts(title="Time Series with Unique Dimension and Reference") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx2_date_str_ref_df, - mock_dataset, - dimensions, references) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Reference"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series with Unique Dimension and Reference") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) + ) + + self.assertEqual( + { + "title": {"text": "Time Series with Unique Dimension and Reference"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DDDF0D", + "dashStyle": "Dash", + "data": [ + (820454400000, 7579518.0), + (946684800000, 6564547.0), + (1072915200000, 8367068.0), + (1199145600000, 10036743.0), + (1325376000000, 9491109.0), + (1451606400000, 8148082.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes EoE (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [ + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Dash", + "data": [ + (946684800000, 1076384.0), + (1072915200000, 8294949.0), + (1199145600000, 9578189.0), + (1325376000000, 11803106.0), + (1451606400000, 12424128.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes EoE (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DDDF0D', - 'dashStyle': 'Dash', - 'data': [(820454400000, 7579518.0), - (946684800000, 6564547.0), - (1072915200000, 8367068.0), - (1199145600000, 10036743.0), - (1325376000000, 9491109.0), - (1451606400000, 8148082.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes EoE (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Dash', - 'data': [(946684800000, 1076384.0), - (1072915200000, 8294949.0), - (1199145600000, 9578189.0), - (1325376000000, 11803106.0), - (1451606400000, 12424128.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes EoE (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_uni_dim_with_ref_delta_line_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] references = [ElectionOverElection(mock_dataset.fields.timestamp, delta=True)] - result = HighCharts(title="Time Series with Unique Dimension and Delta Reference") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx2_date_str_ref_delta_df, mock_dataset, dimensions, references) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Delta Reference"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series with Unique Dimension and Delta Reference") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx2_date_str_ref_delta_df, mock_dataset, dimensions, references + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Delta Reference" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + }, + { + "id": "0_eoe_delta", + "labels": {"style": {"color": None}}, + "opposite": True, + "title": {"text": "EoE Δ"}, + "visible": True, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DDDF0D", + "dashStyle": "Dash", + "data": [ + (820454400000, 1014971.0), + (946684800000, -1802521.0), + (1072915200000, -1669675.0), + (1199145600000, 545634.0), + (1325376000000, 1343027.0), + (1451606400000, -5290753.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes EoE Δ (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0_eoe_delta", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [ + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Dash", + "data": [ + (946684800000, -7218565.0), + (1072915200000, -1283240.0), + (1199145600000, -2224917.0), + (1325376000000, -621022.0), + (1451606400000, 7552450.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes EoE Δ (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0_eoe_delta", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }, - { - 'id': '0_eoe_delta', - 'labels': {'style': {'color': None}}, - 'opposite': True, - 'title': {'text': 'EoE Δ'}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DDDF0D', - 'dashStyle': 'Dash', - 'data': [(820454400000, 1014971.0), - (946684800000, -1802521.0), - (1072915200000, -1669675.0), - (1199145600000, 545634.0), - (1325376000000, 1343027.0), - (1451606400000, -5290753.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes EoE Δ (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0_eoe_delta' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Dash', - 'data': [(946684800000, -7218565.0), - (1072915200000, -1283240.0), - (1199145600000, -2224917.0), - (1325376000000, -621022.0), - (1451606400000, 7552450.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes EoE Δ (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0_eoe_delta' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_invisible_y_axis(self): - result = HighCharts(title="Time Series, Single Metric") \ - .axis(self.chart_class(mock_dataset.fields.votes), y_axis_visible=False) \ + result = ( + HighCharts(title="Time Series, Single Metric") + .axis(self.chart_class(mock_dataset.fields.votes), y_axis_visible=False) .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - "title": {"text": "Time Series, Single Metric"}, - "xAxis": { - "type": "datetime", - "visible": True, + ) + + self.assertEqual( + { + "title": {"text": "Time Series, Single Metric"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": False, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [ + (820454400000, 15220449), + (946684800000, 16662017), + (1072915200000, 19614932), + (1199145600000, 21294215), + (1325376000000, 20572210), + (1451606400000, 18310513), + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "color": "#DDDF0D", + "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, + "dashStyle": "Solid", + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": False, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [(820454400000, 15220449), - (946684800000, 16662017), - (1072915200000, 19614932), - (1199145600000, 21294215), - (1325376000000, 20572210), - (1451606400000, 18310513)], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "color": "#DDDF0D", - "marker": {"symbol": "circle", "fillColor": "#DDDF0D"}, - "dashStyle": "Solid", - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_ref_axes_set_to_same_visibility_as_parent_axis(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] references = [ElectionOverElection(mock_dataset.fields.timestamp, delta=True)] - result = HighCharts(title="Time Series with Unique Dimension and Delta Reference") \ - .axis(self.chart_class(mock_dataset.fields.votes), y_axis_visible=False) \ - .transform(dimx2_date_str_ref_delta_df, mock_dataset, dimensions, references) - - self.assertEqual({ - "title": {"text": "Time Series with Unique Dimension and Delta Reference"}, - "xAxis": { - "type": "datetime", - "visible": True, + result = ( + HighCharts(title="Time Series with Unique Dimension and Delta Reference") + .axis(self.chart_class(mock_dataset.fields.votes), y_axis_visible=False) + .transform( + dimx2_date_str_ref_delta_df, mock_dataset, dimensions, references + ) + ) + + self.assertEqual( + { + "title": { + "text": "Time Series with Unique Dimension and Delta Reference" + }, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": False, + }, + { + "id": "0_eoe_delta", + "labels": {"style": {"color": None}}, + "opposite": True, + "title": {"text": "EoE Δ"}, + "visible": False, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "color": "#DDDF0D", + "dashStyle": "Solid", + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#DDDF0D", + "dashStyle": "Dash", + "data": [ + (820454400000, 1014971.0), + (946684800000, -1802521.0), + (1072915200000, -1669675.0), + (1199145600000, 545634.0), + (1325376000000, 1343027.0), + (1451606400000, -5290753.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "circle"}, + "name": "Votes EoE Δ (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0_eoe_delta", + }, + { + "color": "#55BF3B", + "dashStyle": "Solid", + "data": [ + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "color": "#55BF3B", + "dashStyle": "Dash", + "data": [ + (946684800000, -7218565.0), + (1072915200000, -1283240.0), + (1199145600000, -2224917.0), + (1325376000000, -621022.0), + (1451606400000, 7552450.0), + ], + "marker": {"fillColor": "#DDDF0D", "symbol": "square"}, + "name": "Votes EoE Δ (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0_eoe_delta", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [ - { - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': False - }, - { - 'id': '0_eoe_delta', - 'labels': {'style': {'color': None}}, - 'opposite': True, - 'title': {'text': 'EoE Δ'}, - 'visible': False - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'color': '#DDDF0D', - 'dashStyle': 'Solid', - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#DDDF0D', - 'dashStyle': 'Dash', - 'data': [(820454400000, 1014971.0), - (946684800000, -1802521.0), - (1072915200000, -1669675.0), - (1199145600000, 545634.0), - (1325376000000, 1343027.0), - (1451606400000, -5290753.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'circle'}, - 'name': 'Votes EoE Δ (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0_eoe_delta' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Solid', - 'data': [(946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'color': '#55BF3B', - 'dashStyle': 'Dash', - 'data': [(946684800000, -7218565.0), - (1072915200000, -1283240.0), - (1199145600000, -2224917.0), - (1325376000000, -621022.0), - (1451606400000, 7552450.0)], - 'marker': {'fillColor': '#DDDF0D', 'symbol': 'square'}, - 'name': 'Votes EoE Δ (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0_eoe_delta' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) class HighChartsBarChartTransformerTests(TestCase): maxDiff = None chart_class = HighCharts.BarSeries - chart_type = 'bar' + chart_type = "bar" stacking = None def test_single_metric_bar_chart(self): - result = HighCharts(title="All Votes") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts(title="All Votes") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx0_metricx1_df, mock_dataset, [], []) - - self.assertEqual({ - "title": {"text": "All Votes"}, - "xAxis": { - "type": "category", - "categories": ["All"], - 'visible': True, + ) + + self.assertEqual( + { + "title": {"text": "All Votes"}, + "xAxis": {"type": "category", "categories": ["All"], "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [{"x": 0, "y": 111674336}], + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "marker": {}, + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [{'x': 0, 'y': 111674336}], - 'tooltip': { - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - "marker": {}, - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_multi_metric_bar_chart(self): - result = HighCharts(title="Votes and Wins") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ + result = ( + HighCharts(title="Votes and Wins") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) .transform(dimx0_metricx2_df, mock_dataset, [], []) - - self.assertEqual({ - "title": {"text": "Votes and Wins"}, - "xAxis": { - "type": "category", - "categories": ["All"], - 'visible': True, + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins"}, + "xAxis": {"type": "category", "categories": ["All"], "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": "#DDDF0D"}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [{"x": 0, "y": 111674336}], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "marker": {}, + "stacking": self.stacking, + }, + { + "type": self.chart_type, + "name": "Wins", + "yAxis": "0", + "data": [{"x": 0, "y": 12}], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "marker": {}, + "stacking": self.stacking, + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": "#DDDF0D"}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [{'x': 0, 'y': 111674336}], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "marker": {}, - "stacking": self.stacking, - }, { - "type": self.chart_type, - "name": "Wins", - "yAxis": "0", - "data": [{'x': 0, 'y': 12}], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "marker": {}, - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cat_dim_single_metric_bar_chart(self): - result = HighCharts("Votes and Wins") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], []) - - self.assertEqual({ - "title": {"text": "Votes and Wins"}, - "xAxis": { - "type": "category", - "categories": ["Democrat", "Independent", "Republican"], - 'visible': True, + result = ( + HighCharts("Votes and Wins") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], [] + ) + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins"}, + "xAxis": { + "type": "category", + "categories": ["Democrat", "Independent", "Republican"], + "visible": True, + }, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [ + {"x": 0, "y": 54551568}, + {"x": 1, "y": 1076384}, + {"x": 2, "y": 56046384}, + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "marker": {}, + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [{'x': 0, 'y': 54551568}, - {'x': 1, 'y': 1076384}, - {'x': 2, 'y': 56046384}], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "marker": {}, - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cat_dim_multi_metric_bar_chart(self): - result = HighCharts("Votes and Wins") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ - .transform(dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], []) - - self.assertEqual({ - "title": {"text": "Votes and Wins"}, - "xAxis": { - "type": "category", - "categories": ["Democrat", "Independent", "Republican"], - 'visible': True, + result = ( + HighCharts("Votes and Wins") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) + .transform( + dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], [] + ) + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins"}, + "xAxis": { + "type": "category", + "categories": ["Democrat", "Independent", "Republican"], + "visible": True, + }, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": "#DDDF0D"}}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [ + {"x": 0, "y": 54551568}, + {"x": 1, "y": 1076384}, + {"x": 2, "y": 56046384}, + ], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "marker": {}, + "stacking": self.stacking, + }, + { + "type": self.chart_type, + "name": "Wins", + "yAxis": "0", + "data": [{"x": 0, "y": 6}, {"x": 1, "y": 0}, {"x": 2, "y": 6}], + "tooltip": { + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + "marker": {}, + "stacking": self.stacking, + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": "#DDDF0D"}}, - "visible": True, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [{'x': 0, 'y': 54551568}, - {'x': 1, 'y': 1076384}, - {'x': 2, 'y': 56046384}], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "marker": {}, - "stacking": self.stacking, - }, { - "type": self.chart_type, - "name": "Wins", - "yAxis": "0", - "data": [{'x': 0, 'y': 6}, - {'x': 1, 'y': 0}, - {'x': 2, 'y': 6}], - 'tooltip': { - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, - }, - "marker": {}, - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cont_uni_dims_single_metric_bar_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] - result = HighCharts("Election Votes by State") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts("Election Votes by State") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Election Votes by State"}, - "xAxis": { - "type": "datetime", - "visible": True, + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by State"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [(820454400000, 1076384)], + "marker": {}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 1076384)], - 'marker': {}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cont_uni_dims_multi_metric_single_axis_bar_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] - result = HighCharts(title="Election Votes by State") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ + result = ( + HighCharts(title="Election Votes by State") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Election Votes by State"}, - "xAxis": { - "type": "datetime", - "visible": True, + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by State"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [(820454400000, 1076384)], + "marker": {}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [(820454400000, 0)], + "marker": {}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [ - { - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 1076384)], - 'marker': {}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 0)], - 'marker': {}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cont_uni_dims_multi_metric_multi_axis_bar_chart(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] - result = HighCharts(title="Election Votes by State") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .axis(self.chart_class(mock_dataset.fields.wins)) \ + result = ( + HighCharts(title="Election Votes by State") + .axis(self.chart_class(mock_dataset.fields.votes)) + .axis(self.chart_class(mock_dataset.fields.wins)) .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Election Votes by State"}, - "xAxis": { - "type": "datetime", - "visible": True, - }, - "yAxis": [ - { - 'id': '1', - 'labels': {'style': {'color': '#7798BF'}}, - 'title': {'text': None}, - 'visible': True - }, - { - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - } - ], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - 'data': [(820454400000, 7579518), - (946684800000, 8294949), - (1072915200000, 9578189), - (1199145600000, 11803106), - (1325376000000, 12424128), - (1451606400000, 4871678)], - 'marker': {}, - 'name': 'Votes (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by State"}, + "xAxis": {"type": "datetime", "visible": True,}, + "yAxis": [ + { + "id": "1", + "labels": {"style": {"color": "#7798BF"}}, + "title": {"text": None}, + "visible": True, + }, + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "data": [ + (820454400000, 7579518), + (946684800000, 8294949), + (1072915200000, 9578189), + (1199145600000, 11803106), + (1325376000000, 12424128), + (1451606400000, 4871678), + ], + "marker": {}, + "name": "Votes (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [(820454400000, 1076384)], + "marker": {}, + "name": "Votes (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 6564547), + (946684800000, 8367068), + (1072915200000, 10036743), + (1199145600000, 9491109), + (1325376000000, 8148082), + (1451606400000, 13438835), + ], + "marker": {}, + "name": "Votes (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [ + (820454400000, 2), + (946684800000, 0), + (1072915200000, 0), + (1199145600000, 2), + (1325376000000, 2), + (1451606400000, 0), + ], + "marker": {}, + "name": "Wins (Democrat)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "data": [(820454400000, 0)], + "marker": {}, + "name": "Wins (Independent)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + { + "data": [ + (820454400000, 0), + (946684800000, 2), + (1072915200000, 2), + (1199145600000, 0), + (1325376000000, 0), + (1451606400000, 2), + ], + "marker": {}, + "name": "Wins (Republican)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "1", + }, + ], + "colors": DEFAULT_COLORS, }, - { - 'data': [(820454400000, 1076384)], - 'marker': {}, - 'name': 'Votes (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 6564547), - (946684800000, 8367068), - (1072915200000, 10036743), - (1199145600000, 9491109), - (1325376000000, 8148082), - (1451606400000, 13438835)], - 'marker': {}, - 'name': 'Votes (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [(820454400000, 2), - (946684800000, 0), - (1072915200000, 0), - (1199145600000, 2), - (1325376000000, 2), - (1451606400000, 0)], - 'marker': {}, - 'name': 'Wins (Democrat)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'data': [(820454400000, 0)], - 'marker': {}, - 'name': 'Wins (Independent)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - }, - { - 'data': [(820454400000, 0), - (946684800000, 2), - (1072915200000, 2), - (1199145600000, 0), - (1325376000000, 0), - (1451606400000, 2)], - 'marker': {}, - 'name': 'Wins (Republican)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '1' - } - ], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cat_dim_with_totals_chart(self): - result = HighCharts(title="Categorical Dimension with Totals") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_str_totals_df, mock_dataset, [Rollup(mock_dataset.fields.political_party)], []) - - self.assertEqual({ - 'title': {'text': 'Categorical Dimension with Totals'}, - 'xAxis': { - 'categories': ['Democrat', 'Independent', 'Republican', 'Totals'], - 'type': 'category', - 'visible': True + result = ( + HighCharts(title="Categorical Dimension with Totals") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_str_totals_df, + mock_dataset, + [Rollup(mock_dataset.fields.political_party)], + [], + ) + ) + + self.assertEqual( + { + "title": {"text": "Categorical Dimension with Totals"}, + "xAxis": { + "categories": ["Democrat", "Independent", "Republican", "Totals"], + "type": "category", + "visible": True, + }, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "legend": {"useHTML": True}, + "series": [ + { + "name": "Votes", + "yAxis": "0", + "data": [ + {"x": 0, "y": 54551568}, + {"x": 1, "y": 1076384}, + {"x": 2, "y": 56046384}, + {"x": 3, "y": 111674336}, + ], + "marker": {}, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "stacking": self.stacking, + } + ], + "tooltip": {"enabled": True, "shared": True, "useHTML": True}, + "colors": DEFAULT_COLORS, }, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - 'legend': {'useHTML': True}, - 'series': [{ - 'name': 'Votes', - 'yAxis': '0', - 'data': [{'x': 0, 'y': 54551568}, - {'x': 1, 'y': 1076384}, - {'x': 2, 'y': 56046384}, - {'x': 3, 'y': 111674336}], - 'marker': {}, - 'tooltip': { - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - 'type': self.chart_type, - 'stacking': self.stacking, - }], - 'tooltip': {'enabled': True, 'shared': True, 'useHTML': True}, - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_cat_uni_dim_with_missing_values(self): - df = dimx2_str_num_df \ - .drop(('Democrat', 1)) \ - .drop(('Republican', 2)) \ - .drop(('Republican', 10)) - - dimensions = [mock_dataset.fields.political_party, mock_dataset.fields['candidate-id']] - result = HighCharts(title="Categorical Dimension with Totals") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + df = ( + dimx2_str_num_df.drop(("Democrat", 1)) + .drop(("Republican", 2)) + .drop(("Republican", 10)) + ) + + dimensions = [ + mock_dataset.fields.political_party, + mock_dataset.fields["candidate-id"], + ] + result = ( + HighCharts(title="Categorical Dimension with Totals") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(df, mock_dataset, dimensions, []) - - self.assertEqual({ - 'title': {'text': 'Categorical Dimension with Totals'}, - 'xAxis': { - 'categories': ['Democrat', 'Independent', 'Republican'], - 'type': 'category', - 'visible': True + ) + + self.assertEqual( + { + "title": {"text": "Categorical Dimension with Totals"}, + "xAxis": { + "categories": ["Democrat", "Independent", "Republican"], + "type": "category", + "visible": True, + }, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "legend": {"useHTML": True}, + "series": [ + { + "data": [{"x": 0, "y": 8294949}], + "marker": {}, + "name": "Votes (5)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 0, "y": 9578189}], + "marker": {}, + "name": "Votes (6)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 0, "y": 24227234}], + "marker": {}, + "name": "Votes (7)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 0, "y": 4871678}], + "marker": {}, + "name": "Votes (11)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 1, "y": 1076384}], + "marker": {}, + "name": "Votes (3)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 2, "y": 18403811}], + "marker": {}, + "name": "Votes (4)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 2, "y": 9491109}], + "marker": {}, + "name": "Votes (8)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + { + "data": [{"x": 2, "y": 8148082}], + "marker": {}, + "name": "Votes (9)", + "stacking": self.stacking, + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": self.chart_type, + "yAxis": "0", + }, + ], + "tooltip": {"enabled": True, "shared": True, "useHTML": True}, + "colors": DEFAULT_COLORS, }, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - 'legend': {'useHTML': True}, - 'series': [ - { - 'data': [{'x': 0, 'y': 8294949}], - 'marker': {}, - 'name': 'Votes (5)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 0, 'y': 9578189}], - 'marker': {}, - 'name': 'Votes (6)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 0, 'y': 24227234}], - 'marker': {}, - 'name': 'Votes (7)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 0, 'y': 4871678}], - 'marker': {}, - 'name': 'Votes (11)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 1, 'y': 1076384}], - 'marker': {}, - 'name': 'Votes (3)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 2, 'y': 18403811}], - 'marker': {}, - 'name': 'Votes (4)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 2, 'y': 9491109}], - 'marker': {}, - 'name': 'Votes (8)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - }, - { - 'data': [{'x': 2, 'y': 8148082}], - 'marker': {}, - 'name': 'Votes (9)', - 'stacking': self.stacking, - 'tooltip': {'valueDecimals': None, 'valuePrefix': None, 'valueSuffix': None}, - 'type': self.chart_type, - 'yAxis': '0' - } - ], - 'tooltip': {'enabled': True, 'shared': True, 'useHTML': True}, - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_invisible_y_axis(self): - result = HighCharts(title="All Votes") \ - .axis(self.chart_class(mock_dataset.fields.votes), - y_axis_visible=False) \ + result = ( + HighCharts(title="All Votes") + .axis(self.chart_class(mock_dataset.fields.votes), y_axis_visible=False) .transform(dimx0_metricx1_df, mock_dataset, [], []) - - self.assertEqual({ - "title": {"text": "All Votes"}, - "xAxis": { - "type": "category", - "categories": ["All"], - 'visible': True, + ) + + self.assertEqual( + { + "title": {"text": "All Votes"}, + "xAxis": {"type": "category", "categories": ["All"], "visible": True,}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": False, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "type": self.chart_type, + "name": "Votes", + "yAxis": "0", + "data": [{"x": 0, "y": 111674336}], + "tooltip": { + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "marker": {}, + "stacking": self.stacking, + } + ], + "colors": DEFAULT_COLORS, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": False, - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "type": self.chart_type, - "name": "Votes", - "yAxis": "0", - "data": [{'x': 0, 'y': 111674336}], - 'tooltip': { - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - "marker": {}, - "stacking": self.stacking, - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) class HighChartsColumnChartTransformerTests(HighChartsBarChartTransformerTests): chart_class = HighCharts.ColumnSeries - chart_type = 'column' + chart_type = "column" class HighChartsStackedBarChartTransformerTests(HighChartsBarChartTransformerTests): maxDiff = None chart_class = HighCharts.StackedBarSeries - chart_type = 'bar' - stacking = 'normal' + chart_type = "bar" + stacking = "normal" class HighChartsStackedColumnChartTransformerTests(HighChartsBarChartTransformerTests): chart_class = HighCharts.StackedColumnSeries - chart_type = 'column' - stacking = 'normal' + chart_type = "column" + stacking = "normal" class HighChartsAreaChartTransformerTests(HighChartsLineChartTransformerTests): chart_class = HighCharts.AreaSeries - chart_type = 'area' + chart_type = "area" class HighChartsAreaStackedChartTransformerTests(HighChartsAreaChartTransformerTests): chart_class = HighCharts.AreaStackedSeries - stacking = 'normal' + stacking = "normal" class HighChartsAreaPercentChartTransformerTests(HighChartsAreaChartTransformerTests): chart_class = HighCharts.AreaPercentageSeries - stacking = 'percent' + stacking = "percent" class HighChartsPieChartTransformerTests(TestCase): maxDiff = None chart_class = HighCharts.PieSeries - chart_type = 'pie' + chart_type = "pie" def test_pie_chart_metricx1(self): - result = HighCharts(title="All Votes") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts(title="All Votes") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx0_metricx1_df, mock_dataset, [], []) - - self.assertEqual({ - "title": {"text": "All Votes"}, - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{ - "name": "Votes", - "y": 111674336, - }], - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ({point.percentage:.1f}%)
', - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - }], - 'xAxis': { - 'type': 'category', - 'categories': ['All'], - 'visible': True, + ) + + self.assertEqual( + { + "title": {"text": "All Votes"}, + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [{"name": "Votes", "y": 111674336,}], + "tooltip": { + "pointFormat": ' ' + "{series.name}: {point.y} ({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + } + ], + "xAxis": {"type": "category", "categories": ["All"], "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, }, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_pie_chart_metricx2(self): - result = HighCharts(title="Votes and Wins") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ + result = ( + HighCharts(title="Votes and Wins") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) .transform(dimx0_metricx2_df, mock_dataset, [], []) - - self.assertEqual({ - "title": {"text": "Votes and Wins"}, - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True}, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{ - "name": "Votes", - "y": 111674336, - }], - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ({point.percentage:.1f}%)
', - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - }, { - "name": "Wins", - "type": "pie", - "data": [{ - "name": "Wins", - "y": 12, - }], - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ({point.percentage:.1f}%)
', - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - }], - 'xAxis': { - 'type': 'category', - 'categories': ['All'], - 'visible': True, + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins"}, + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [{"name": "Votes", "y": 111674336,}], + "tooltip": { + "pointFormat": ' ' + "{series.name}: {point.y} ({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + { + "name": "Wins", + "type": "pie", + "data": [{"name": "Wins", "y": 12,}], + "tooltip": { + "pointFormat": ' ' + "{series.name}: {point.y} ({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + ], + "xAxis": {"type": "category", "categories": ["All"], "visible": True,}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": "#DDDF0D"}}, + "title": {"text": None}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, }, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': '#DDDF0D'}}, - 'title': {'text': None}, - 'visible': True - }], - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_pie_chart_dimx1_date(self): - result = HighCharts("Votes and Wins By Day") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + result = ( + HighCharts("Votes and Wins By Day") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx1_date_df, mock_dataset, [mock_dataset.fields.timestamp], []) - - self.assertEqual({ - 'colors': DEFAULT_COLORS, - 'legend': {'useHTML': True}, - 'series': [{ - 'data': [{'name': '1996-01-01', 'y': 15220449}, - {'name': '2000-01-01', 'y': 16662017}, - {'name': '2004-01-01', 'y': 19614932}, - {'name': '2008-01-01', 'y': 21294215}, - {'name': '2012-01-01', 'y': 20572210}, - {'name': '2016-01-01', 'y': 18310513}], - 'name': 'Votes', - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ' - '({point.percentage:.1f}%)
', - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - 'type': 'pie' - }], - 'title': {'text': 'Votes and Wins By Day'}, - 'tooltip': {'enabled': True, 'shared': True, 'useHTML': True}, - 'xAxis': {'type': 'datetime', 'visible': True}, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }] - }, result) + ) + + self.assertEqual( + { + "colors": DEFAULT_COLORS, + "legend": {"useHTML": True}, + "series": [ + { + "data": [ + {"name": "1996-01-01", "y": 15220449}, + {"name": "2000-01-01", "y": 16662017}, + {"name": "2004-01-01", "y": 19614932}, + {"name": "2008-01-01", "y": 21294215}, + {"name": "2012-01-01", "y": 20572210}, + {"name": "2016-01-01", "y": 18310513}, + ], + "name": "Votes", + "tooltip": { + "pointFormat": " ' + "{series.name}: {point.y} " + "({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": "pie", + } + ], + "title": {"text": "Votes and Wins By Day"}, + "tooltip": {"enabled": True, "shared": True, "useHTML": True}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + }, + result, + ) def test_pie_chart_dimx1_date_year(self): - result = HighCharts("Votes and Wins By Day") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_date_df, mock_dataset, [year(mock_dataset.fields.timestamp)], []) - - self.assertEqual({ - 'colors': DEFAULT_COLORS, - 'legend': {'useHTML': True}, - 'series': [{ - 'data': [{'name': '1996', 'y': 15220449}, - {'name': '2000', 'y': 16662017}, - {'name': '2004', 'y': 19614932}, - {'name': '2008', 'y': 21294215}, - {'name': '2012', 'y': 20572210}, - {'name': '2016', 'y': 18310513}], - 'name': 'Votes', - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ' - '({point.percentage:.1f}%)
', - 'valueDecimals': None, - 'valuePrefix': None, - 'valueSuffix': None - }, - 'type': 'pie' - }], - 'title': {'text': 'Votes and Wins By Day'}, - 'tooltip': {'enabled': True, 'shared': True, 'useHTML': True}, - 'xAxis': {'type': 'datetime', 'visible': True}, - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }] - }, result) + result = ( + HighCharts("Votes and Wins By Day") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_date_df, mock_dataset, [year(mock_dataset.fields.timestamp)], [] + ) + ) + + self.assertEqual( + { + "colors": DEFAULT_COLORS, + "legend": {"useHTML": True}, + "series": [ + { + "data": [ + {"name": "1996", "y": 15220449}, + {"name": "2000", "y": 16662017}, + {"name": "2004", "y": 19614932}, + {"name": "2008", "y": 21294215}, + {"name": "2012", "y": 20572210}, + {"name": "2016", "y": 18310513}, + ], + "name": "Votes", + "tooltip": { + "pointFormat": " ' + "{series.name}: {point.y} " + "({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + "type": "pie", + } + ], + "title": {"text": "Votes and Wins By Day"}, + "tooltip": {"enabled": True, "shared": True, "useHTML": True}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + }, + result, + ) def test_pie_chart_dimx1_str(self): - result = HighCharts("Votes and Wins By Party") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], []) - - self.assertEqual({ - 'title': {'text': 'Votes and Wins By Party'}, - 'tooltip': {'useHTML': True, 'shared': True, 'enabled': True}, - 'legend': {'useHTML': True}, - 'series': [{ - 'name': 'Votes', - 'type': 'pie', - 'data': [ - {'y': 54551568, 'name': 'Democrat'}, - {'y': 1076384, 'name': 'Independent'}, - {'y': 56046384, 'name': 'Republican'}, - ], - 'tooltip': { - 'pointFormat': ' ' - '{series.name}: {point.y} ({point.percentage:.1f}%)
', - 'valuePrefix': None, - 'valueSuffix': None, - 'valueDecimals': None, + result = ( + HighCharts("Votes and Wins By Party") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], [] + ) + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins By Party"}, + "tooltip": {"useHTML": True, "shared": True, "enabled": True}, + "legend": {"useHTML": True}, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"y": 54551568, "name": "Democrat"}, + {"y": 1076384, "name": "Independent"}, + {"y": 56046384, "name": "Republican"}, + ], + "tooltip": { + "pointFormat": ' ' + "{series.name}: {point.y} ({point.percentage:.1f}%)
", + "valuePrefix": None, + "valueSuffix": None, + "valueDecimals": None, + }, + } + ], + "yAxis": [ + { + "id": "0", + "labels": {"style": {"color": None}}, + "title": {"text": None}, + "visible": True, + } + ], + "xAxis": { + "type": "category", + "categories": ["Democrat", "Independent", "Republican"], + "visible": True, }, - }], - 'yAxis': [{ - 'id': '0', - 'labels': {'style': {'color': None}}, - 'title': {'text': None}, - 'visible': True - }], - 'xAxis': { - 'type': 'category', - 'categories': ['Democrat', 'Independent', 'Republican'], - 'visible': True, + "colors": DEFAULT_COLORS, }, - "colors": DEFAULT_COLORS, - }, result) + result, + ) def test_pie_chart_dimx1_num(self): - result = HighCharts(title="Votes and Wins By Election") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ - .transform(dimx1_num_df, mock_dataset, [mock_dataset.fields['candidate-id']], []) - - self.assertEqual({ - "title": {"text": "Votes and Wins By Election"}, - "xAxis": { - "type": "category", - "categories": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"], - "visible": True + result = ( + HighCharts(title="Votes and Wins By Election") + .axis(self.chart_class(mock_dataset.fields.votes)) + .transform( + dimx1_num_df, mock_dataset, [mock_dataset.fields["candidate-id"]], [] + ) + ) + + self.assertEqual( + { + "title": {"text": "Votes and Wins By Election"}, + "xAxis": { + "type": "category", + "categories": [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + ], + "visible": True, + }, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"name": "1", "y": 7579518}, + {"name": "2", "y": 6564547}, + {"name": "3", "y": 1076384}, + {"name": "4", "y": 18403811}, + {"name": "5", "y": 8294949}, + {"name": "6", "y": 9578189}, + {"name": "7", "y": 24227234}, + {"name": "8", "y": 9491109}, + {"name": "9", "y": 8148082}, + {"name": "10", "y": 13438835}, + {"name": "11", "y": 4871678}, + ], + "tooltip": { + "pointFormat": '\u25cf {' + "series.name}: {point.y} ({" + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, }, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True - }], - "colors": DEFAULT_COLORS, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{"name": "1", "y": 7579518}, {"name": "2", "y": 6564547}, - {"name": "3", "y": 1076384}, {"name": "4", "y": 18403811}, - {"name": "5", "y": 8294949}, {"name": "6", "y": 9578189}, - {"name": "7", "y": 24227234}, {"name": "8", "y": 9491109}, - {"name": "9", "y": 8148082}, {"name": "10", "y": 13438835}, - {"name": "11", "y": 4871678}], - "tooltip": { - "pointFormat": "\u25cf {" - "series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True} - }, result) + result, + ) def test_pie_chart_dimx2_date_str(self): - dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.political_party] - result = HighCharts(title="Votes by Date, Party") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + dimensions = [ + mock_dataset.fields.timestamp, + mock_dataset.fields.political_party, + ] + result = ( + HighCharts(title="Votes by Date, Party") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Votes by Date, Party"}, - "xAxis": {"type": "datetime", "visible": True}, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": None}}, - "visible": True - }], - "colors": DEFAULT_COLORS, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{"name": "1996-01-01, Democrat", "y": 7579518}, - {"name": "1996-01-01, Independent", "y": 1076384}, - {"name": "1996-01-01, Republican", "y": 6564547}, - {"name": "2000-01-01, Democrat", "y": 8294949}, - {"name": "2000-01-01, Republican", "y": 8367068}, - {"name": "2004-01-01, Democrat", "y": 9578189}, - {"name": "2004-01-01, Republican", "y": 10036743}, - {"name": "2008-01-01, Democrat", "y": 11803106}, - {"name": "2008-01-01, Republican", "y": 9491109}, - {"name": "2012-01-01, Democrat", "y": 12424128}, - {"name": "2012-01-01, Republican", "y": 8148082}, - {"name": "2016-01-01, Democrat", "y": 4871678}, - {"name": "2016-01-01, Republican", "y": 13438835}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True} - }, result) + ) + + self.assertEqual( + { + "title": {"text": "Votes by Date, Party"}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"name": "1996-01-01, Democrat", "y": 7579518}, + {"name": "1996-01-01, Independent", "y": 1076384}, + {"name": "1996-01-01, Republican", "y": 6564547}, + {"name": "2000-01-01, Democrat", "y": 8294949}, + {"name": "2000-01-01, Republican", "y": 8367068}, + {"name": "2004-01-01, Democrat", "y": 9578189}, + {"name": "2004-01-01, Republican", "y": 10036743}, + {"name": "2008-01-01, Democrat", "y": 11803106}, + {"name": "2008-01-01, Republican", "y": 9491109}, + {"name": "2012-01-01, Democrat", "y": 12424128}, + {"name": "2012-01-01, Republican", "y": 8148082}, + {"name": "2016-01-01, Democrat", "y": 4871678}, + {"name": "2016-01-01, Republican", "y": 13438835}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: {' + "point.y} ({" + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + }, + result, + ) def test_pie_chart_dimx2_date_num(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields['candidate-id']] - result = HighCharts(title="Election Votes by Day and Candidate ID") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields["candidate-id"], + ] + result = ( + HighCharts(title="Election Votes by Day and Candidate ID") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx2_date_num_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Election Votes by Day and Candidate ID"}, - "xAxis": {"type": "datetime", "visible": True}, - "yAxis": [ - {"id": "0", "title": {"text": None}, "labels": {"style": {"color": None}}, "visible": True}], - "colors": DEFAULT_COLORS, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{"name": "1996-01-01, 1", "y": 7579518}, - {"name": "1996-01-01, 2", "y": 6564547}, - {"name": "1996-01-01, 3", "y": 1076384}, - {"name": "2000-01-01, 4", "y": 8367068}, - {"name": "2000-01-01, 5", "y": 8294949}, - {"name": "2004-01-01, 4", "y": 10036743}, - {"name": "2004-01-01, 6", "y": 9578189}, - {"name": "2008-01-01, 7", "y": 11803106}, - {"name": "2008-01-01, 8", "y": 9491109}, - {"name": "2012-01-01, 7", "y": 12424128}, - {"name": "2012-01-01, 9", "y": 8148082}, - {"name": "2016-01-01, 10", "y": 13438835}, - {"name": "2016-01-01, 11", "y": 4871678}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: " - "{point.y} ({point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True} - }, result) + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by Day and Candidate ID"}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"name": "1996-01-01, 1", "y": 7579518}, + {"name": "1996-01-01, 2", "y": 6564547}, + {"name": "1996-01-01, 3", "y": 1076384}, + {"name": "2000-01-01, 4", "y": 8367068}, + {"name": "2000-01-01, 5", "y": 8294949}, + {"name": "2004-01-01, 4", "y": 10036743}, + {"name": "2004-01-01, 6", "y": 9578189}, + {"name": "2008-01-01, 7", "y": 11803106}, + {"name": "2008-01-01, 8", "y": 9491109}, + {"name": "2012-01-01, 7", "y": 12424128}, + {"name": "2012-01-01, 9", "y": 8148082}, + {"name": "2016-01-01, 10", "y": 13438835}, + {"name": "2016-01-01, 11", "y": 4871678}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: ' + "{point.y} ({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + }, + result, + ) def test_pie_chart_dimx2_yearly_date_num(self): - dimensions = [year(mock_dataset.fields.timestamp), mock_dataset.fields['candidate-id']] - result = HighCharts(title="Election Votes by Day and Candidate ID") \ - .axis(self.chart_class(mock_dataset.fields.votes)) \ + dimensions = [ + year(mock_dataset.fields.timestamp), + mock_dataset.fields["candidate-id"], + ] + result = ( + HighCharts(title="Election Votes by Day and Candidate ID") + .axis(self.chart_class(mock_dataset.fields.votes)) .transform(dimx2_date_num_df, mock_dataset, dimensions, []) - - self.assertEqual({ - "title": {"text": "Election Votes by Day and Candidate ID"}, - "xAxis": {"type": "datetime", "visible": True}, - "yAxis": [ - {"id": "0", "title": {"text": None}, "labels": {"style": {"color": None}}, "visible": True}], - "colors": DEFAULT_COLORS, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{"name": "1996, 1", "y": 7579518}, - {"name": "1996, 2", "y": 6564547}, - {"name": "1996, 3", "y": 1076384}, - {"name": "2000, 4", "y": 8367068}, - {"name": "2000, 5", "y": 8294949}, - {"name": "2004, 4", "y": 10036743}, - {"name": "2004, 6", "y": 9578189}, - {"name": "2008, 7", "y": 11803106}, - {"name": "2008, 8", "y": 9491109}, - {"name": "2012, 7", "y": 12424128}, - {"name": "2012, 9", "y": 8148082}, - {"name": "2016, 10", "y": 13438835}, - {"name": "2016, 11", "y": 4871678}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: " - "{point.y} ({point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True} - }, result) + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by Day and Candidate ID"}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": None}}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"name": "1996, 1", "y": 7579518}, + {"name": "1996, 2", "y": 6564547}, + {"name": "1996, 3", "y": 1076384}, + {"name": "2000, 4", "y": 8367068}, + {"name": "2000, 5", "y": 8294949}, + {"name": "2004, 4", "y": 10036743}, + {"name": "2004, 6", "y": 9578189}, + {"name": "2008, 7", "y": 11803106}, + {"name": "2008, 8", "y": 9491109}, + {"name": "2012, 7", "y": 12424128}, + {"name": "2012, 9", "y": 8148082}, + {"name": "2016, 10", "y": 13438835}, + {"name": "2016, 11", "y": 4871678}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: ' + "{point.y} ({point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + } + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + }, + result, + ) def test_pie_chart_dimx2_date_str_reference(self): dimensions = [mock_dataset.fields.timestamp, mock_dataset.fields.state] references = [ElectionOverElection(mock_dataset.fields.timestamp)] - result = HighCharts(title="Election Votes by State") \ - .axis(self.chart_class(mock_dataset.fields.votes), - self.chart_class(mock_dataset.fields.wins)) \ + result = ( + HighCharts(title="Election Votes by State") + .axis( + self.chart_class(mock_dataset.fields.votes), + self.chart_class(mock_dataset.fields.wins), + ) .transform(dimx2_date_str_df, mock_dataset, dimensions, references) - - self.assertEqual({ - "title": {"text": "Election Votes by State"}, - "xAxis": {"type": "datetime", "visible": True}, - "yAxis": [{ - "id": "0", - "title": {"text": None}, - "labels": {"style": {"color": "#DDDF0D"}}, - "visible": True - }], - "colors": DEFAULT_COLORS, - "series": [{ - "name": "Votes", - "type": "pie", - "data": [{"name": "1996-01-01, Democrat", "y": 7579518}, - {"name": "1996-01-01, Independent", "y": 1076384}, - {"name": "1996-01-01, Republican", "y": 6564547}, - {"name": "2000-01-01, Democrat", "y": 8294949}, - {"name": "2000-01-01, Republican", "y": 8367068}, - {"name": "2004-01-01, Democrat", "y": 9578189}, - {"name": "2004-01-01, Republican", "y": 10036743}, - {"name": "2008-01-01, Democrat", "y": 11803106}, - {"name": "2008-01-01, Republican", "y": 9491109}, - {"name": "2012-01-01, Democrat", "y": 12424128}, - {"name": "2012-01-01, Republican", "y": 8148082}, - {"name": "2016-01-01, Democrat", "y": 4871678}, - {"name": "2016-01-01, Republican", "y": 13438835}], - "tooltip": { - "pointFormat": "\u25cf {" - "series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }, { - "name": "Votes EoE", - "type": "pie", - "data": [{"name": "1996-01-01, Democrat", "y": 7579518}, - {"name": "1996-01-01, Independent", "y": 1076384}, - {"name": "1996-01-01, Republican", "y": 6564547}, - {"name": "2000-01-01, Democrat", "y": 8294949}, - {"name": "2000-01-01, Republican", "y": 8367068}, - {"name": "2004-01-01, Democrat", "y": 9578189}, - {"name": "2004-01-01, Republican", "y": 10036743}, - {"name": "2008-01-01, Democrat", "y": 11803106}, - {"name": "2008-01-01, Republican", "y": 9491109}, - {"name": "2012-01-01, Democrat", "y": 12424128}, - {"name": "2012-01-01, Republican", "y": 8148082}, - {"name": "2016-01-01, Democrat", "y": 4871678}, - {"name": "2016-01-01, Republican", "y": 13438835}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }, { - "name": "Wins", - "type": "pie", - "data": [{"name": "1996-01-01, Democrat", "y": 2}, - {"name": "1996-01-01, Independent", "y": 0}, - {"name": "1996-01-01, Republican", "y": 0}, - {"name": "2000-01-01, Democrat", "y": 0}, - {"name": "2000-01-01, Republican", "y": 2}, - {"name": "2004-01-01, Democrat", "y": 0}, - {"name": "2004-01-01, Republican", "y": 2}, - {"name": "2008-01-01, Democrat", "y": 2}, - {"name": "2008-01-01, Republican", "y": 0}, - {"name": "2012-01-01, Democrat", "y": 2}, - {"name": "2012-01-01, Republican", "y": 0}, - {"name": "2016-01-01, Democrat", "y": 0}, - {"name": "2016-01-01, Republican", "y": 2}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }, { - "name": "Wins EoE", - "type": "pie", - "data": [{"name": "1996-01-01, Democrat", "y": 2}, - {"name": "1996-01-01, Independent", "y": 0}, - {"name": "1996-01-01, Republican", "y": 0}, - {"name": "2000-01-01, Democrat", "y": 0}, - {"name": "2000-01-01, Republican", "y": 2}, - {"name": "2004-01-01, Democrat", "y": 0}, - {"name": "2004-01-01, Republican", "y": 2}, - {"name": "2008-01-01, Democrat", "y": 2}, - {"name": "2008-01-01, Republican", "y": 0}, - {"name": "2012-01-01, Democrat", "y": 2}, - {"name": "2012-01-01, Republican", "y": 0}, - {"name": "2016-01-01, Democrat", "y": 0}, - {"name": "2016-01-01, Republican", "y": 2}], - "tooltip": { - "pointFormat": "\u25cf {series.name}: {point.y} ({" - "point.percentage:.1f}%)
", - "valueDecimals": None, - "valuePrefix": None, - "valueSuffix": None - } - }], - "tooltip": {"shared": True, "useHTML": True, "enabled": True}, - "legend": {"useHTML": True} - }, result) + ) + + self.assertEqual( + { + "title": {"text": "Election Votes by State"}, + "xAxis": {"type": "datetime", "visible": True}, + "yAxis": [ + { + "id": "0", + "title": {"text": None}, + "labels": {"style": {"color": "#DDDF0D"}}, + "visible": True, + } + ], + "colors": DEFAULT_COLORS, + "series": [ + { + "name": "Votes", + "type": "pie", + "data": [ + {"name": "1996-01-01, Democrat", "y": 7579518}, + {"name": "1996-01-01, Independent", "y": 1076384}, + {"name": "1996-01-01, Republican", "y": 6564547}, + {"name": "2000-01-01, Democrat", "y": 8294949}, + {"name": "2000-01-01, Republican", "y": 8367068}, + {"name": "2004-01-01, Democrat", "y": 9578189}, + {"name": "2004-01-01, Republican", "y": 10036743}, + {"name": "2008-01-01, Democrat", "y": 11803106}, + {"name": "2008-01-01, Republican", "y": 9491109}, + {"name": "2012-01-01, Democrat", "y": 12424128}, + {"name": "2012-01-01, Republican", "y": 8148082}, + {"name": "2016-01-01, Democrat", "y": 4871678}, + {"name": "2016-01-01, Republican", "y": 13438835}, + ], + "tooltip": { + "pointFormat": '\u25cf {' + "series.name}: {point.y} ({" + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + { + "name": "Votes EoE", + "type": "pie", + "data": [ + {"name": "1996-01-01, Democrat", "y": 7579518}, + {"name": "1996-01-01, Independent", "y": 1076384}, + {"name": "1996-01-01, Republican", "y": 6564547}, + {"name": "2000-01-01, Democrat", "y": 8294949}, + {"name": "2000-01-01, Republican", "y": 8367068}, + {"name": "2004-01-01, Democrat", "y": 9578189}, + {"name": "2004-01-01, Republican", "y": 10036743}, + {"name": "2008-01-01, Democrat", "y": 11803106}, + {"name": "2008-01-01, Republican", "y": 9491109}, + {"name": "2012-01-01, Democrat", "y": 12424128}, + {"name": "2012-01-01, Republican", "y": 8148082}, + {"name": "2016-01-01, Democrat", "y": 4871678}, + {"name": "2016-01-01, Republican", "y": 13438835}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: {point.y} ({' + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + { + "name": "Wins", + "type": "pie", + "data": [ + {"name": "1996-01-01, Democrat", "y": 2}, + {"name": "1996-01-01, Independent", "y": 0}, + {"name": "1996-01-01, Republican", "y": 0}, + {"name": "2000-01-01, Democrat", "y": 0}, + {"name": "2000-01-01, Republican", "y": 2}, + {"name": "2004-01-01, Democrat", "y": 0}, + {"name": "2004-01-01, Republican", "y": 2}, + {"name": "2008-01-01, Democrat", "y": 2}, + {"name": "2008-01-01, Republican", "y": 0}, + {"name": "2012-01-01, Democrat", "y": 2}, + {"name": "2012-01-01, Republican", "y": 0}, + {"name": "2016-01-01, Democrat", "y": 0}, + {"name": "2016-01-01, Republican", "y": 2}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: {point.y} ({' + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + { + "name": "Wins EoE", + "type": "pie", + "data": [ + {"name": "1996-01-01, Democrat", "y": 2}, + {"name": "1996-01-01, Independent", "y": 0}, + {"name": "1996-01-01, Republican", "y": 0}, + {"name": "2000-01-01, Democrat", "y": 0}, + {"name": "2000-01-01, Republican", "y": 2}, + {"name": "2004-01-01, Democrat", "y": 0}, + {"name": "2004-01-01, Republican", "y": 2}, + {"name": "2008-01-01, Democrat", "y": 2}, + {"name": "2008-01-01, Republican", "y": 0}, + {"name": "2012-01-01, Democrat", "y": 2}, + {"name": "2012-01-01, Republican", "y": 0}, + {"name": "2016-01-01, Democrat", "y": 0}, + {"name": "2016-01-01, Republican", "y": 2}, + ], + "tooltip": { + "pointFormat": '\u25cf {series.name}: {point.y} ({' + "point.percentage:.1f}%)
", + "valueDecimals": None, + "valuePrefix": None, + "valueSuffix": None, + }, + }, + ], + "tooltip": {"shared": True, "useHTML": True, "enabled": True}, + "legend": {"useHTML": True}, + }, + result, + ) diff --git a/fireant/tests/widgets/test_reacttable.py b/fireant/tests/widgets/test_reacttable.py index 0f97ae86..61eb1e88 100644 --- a/fireant/tests/widgets/test_reacttable.py +++ b/fireant/tests/widgets/test_reacttable.py @@ -1,4 +1,3 @@ -import copy from unittest import TestCase from fireant import ( @@ -20,8 +19,8 @@ dimx2_date_str_ref_df, dimx2_date_str_totals_df, dimx2_date_str_totalsx2_df, - dimx2_str_num_df, mock_dataset, + dimx2_str_str_df, ) from fireant.widgets.base import ReferenceItem from fireant.widgets.reacttable import ReactTable @@ -31,1209 +30,1612 @@ class ReactTableTransformerTests(TestCase): maxDiff = None def test_single_metric(self): - result = ReactTable(mock_dataset.fields.votes) \ - .transform(dimx0_metricx1_df, mock_dataset, [], []) - - self.assertEqual({ - 'columns': [{'Header': 'Votes', 'accessor': '$votes'}], - 'data': [{'$votes': {'display': '111,674,336', 'raw': 111674336}}] - }, result) + result = ReactTable(mock_dataset.fields.votes).transform( + dimx0_metricx1_df, mock_dataset, [], [] + ) + + self.assertEqual( + { + "columns": [{"Header": "Votes", "accessor": "$votes"}], + "data": [{"$votes": {"display": "111,674,336", "raw": 111674336}}], + }, + result, + ) def test_multiple_metrics(self): - result = ReactTable(mock_dataset.fields.votes, mock_dataset.fields.wins) \ - .transform(dimx0_metricx2_df, mock_dataset, [], []) - - self.assertEqual({ - 'columns': [{'Header': 'Votes', 'accessor': '$votes'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [{ - '$votes': {'display': '111,674,336', 'raw': 111674336}, - '$wins': {'display': '12', 'raw': 12} - }] - }, result) + result = ReactTable( + mock_dataset.fields.votes, mock_dataset.fields.wins + ).transform(dimx0_metricx2_df, mock_dataset, [], []) + + self.assertEqual( + { + "columns": [ + {"Header": "Votes", "accessor": "$votes"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$votes": {"display": "111,674,336", "raw": 111674336}, + "$wins": {"display": "12", "raw": 12}, + } + ], + }, + result, + ) def test_multiple_metrics_reversed(self): - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes) \ - .transform(dimx0_metricx2_df, mock_dataset, [], []) - - self.assertEqual({ - 'columns': [{'Header': 'Wins', 'accessor': '$wins'}, - {'Header': 'Votes', 'accessor': '$votes'}], - 'data': [{ - '$votes': {'display': '111,674,336', 'raw': 111674336}, - '$wins': {'display': '12', 'raw': 12} - }] - }, result) + result = ReactTable( + mock_dataset.fields.wins, mock_dataset.fields.votes + ).transform(dimx0_metricx2_df, mock_dataset, [], []) + + self.assertEqual( + { + "columns": [ + {"Header": "Wins", "accessor": "$wins"}, + {"Header": "Votes", "accessor": "$votes"}, + ], + "data": [ + { + "$votes": {"display": "111,674,336", "raw": 111674336}, + "$wins": {"display": "12", "raw": 12}, + } + ], + }, + result, + ) def test_time_series_dim(self): - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx1_date_df, mock_dataset, [day(mock_dataset.fields.timestamp)], []) - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [{ - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }, { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }, { - '$timestamp': {'display': '2004-01-01', 'raw': '2004-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }, { - '$timestamp': {'display': '2008-01-01', 'raw': '2008-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }, { - '$timestamp': {'display': '2012-01-01', 'raw': '2012-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }, { - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2} - }] - }, result) + result = ReactTable(mock_dataset.fields.wins).transform( + dimx1_date_df, mock_dataset, [day(mock_dataset.fields.timestamp)], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + { + "$timestamp": { + "display": "2004-01-01", + "raw": "2004-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + { + "$timestamp": { + "display": "2008-01-01", + "raw": "2008-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + { + "$timestamp": { + "display": "2012-01-01", + "raw": "2012-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + { + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2}, + }, + ], + }, + result, + ) def test_time_series_dim_with_operation(self): - result = ReactTable(CumSum(mock_dataset.fields.votes)) \ - .transform(dimx1_date_operation_df, mock_dataset, [day(mock_dataset.fields.timestamp)], []) - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'CumSum(Votes)', 'accessor': '$cumsum(votes)'}], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '15,220,449', 'raw': 15220449} - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '31,882,466', 'raw': 31882466} - }, - { - '$timestamp': {'display': '2004-01-01', 'raw': '2004-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '51,497,398', 'raw': 51497398} - }, - { - '$timestamp': {'display': '2008-01-01', 'raw': '2008-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '72,791,613', 'raw': 72791613} - }, - { - '$timestamp': {'display': '2012-01-01', 'raw': '2012-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '93,363,823', 'raw': 93363823} - }, - { - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$cumsum(votes)': {'display': '111,674,336', 'raw': 111674336} - } - ] - }, result) + result = ReactTable(CumSum(mock_dataset.fields.votes)).transform( + dimx1_date_operation_df, + mock_dataset, + [day(mock_dataset.fields.timestamp)], + [], + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "CumSum(Votes)", "accessor": "$cumsum(votes)"}, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "15,220,449", "raw": 15220449}, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "31,882,466", "raw": 31882466}, + }, + { + "$timestamp": { + "display": "2004-01-01", + "raw": "2004-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "51,497,398", "raw": 51497398}, + }, + { + "$timestamp": { + "display": "2008-01-01", + "raw": "2008-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "72,791,613", "raw": 72791613}, + }, + { + "$timestamp": { + "display": "2012-01-01", + "raw": "2012-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "93,363,823", "raw": 93363823}, + }, + { + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$cumsum(votes)": {"display": "111,674,336", "raw": 111674336}, + }, + ], + }, + result, + ) def test_dimx1_str(self): - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], []) - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$political_party': {'raw': 'Democrat'}, - '$wins': {'display': '6', 'raw': 6.0} - }, - { - '$political_party': {'raw': 'Independent'}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$political_party': {'raw': 'Republican'}, - '$wins': {'display': '6', 'raw': 6.0} - } - ] - }, result) + result = ReactTable(mock_dataset.fields.wins).transform( + dimx1_str_df, mock_dataset, [mock_dataset.fields.political_party], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": {"display": "6", "raw": 6.0}, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$political_party": { + "raw": "Republican", + "hyperlink": "http://example.com/Republican", + }, + "$wins": {"display": "6", "raw": 6.0}, + }, + ], + }, + result, + ) def test_dimx1_int(self): - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx1_num_df, mock_dataset, [mock_dataset.fields['candidate-id']], []) - - self.assertEqual({ - 'columns': [{'Header': 'Candidate ID', 'accessor': '$candidate-id'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$candidate-id': {'display': '1', 'raw': 1.0}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$candidate-id': {'display': '2', 'raw': 2.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '3', 'raw': 3.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '4', 'raw': 4.0}, - '$wins': {'display': '4', 'raw': 4.0} - }, - { - '$candidate-id': {'display': '5', 'raw': 5.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '6', 'raw': 6.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '7', 'raw': 7.0}, - '$wins': {'display': '4', 'raw': 4.0} - }, - { - '$candidate-id': {'display': '8', 'raw': 8.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '9', 'raw': 9.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '10', 'raw': 10.0}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$candidate-id': {'display': '11', 'raw': 11.0}, - '$wins': {'display': '0', 'raw': 0.0} - } - ] - }, result) + result = ReactTable(mock_dataset.fields.wins).transform( + dimx1_num_df, mock_dataset, [mock_dataset.fields["candidate-id"]], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Candidate ID", "accessor": "$candidate-id"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$candidate-id": {"display": "1", "raw": 1.0}, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$candidate-id": {"display": "2", "raw": 2.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "3", "raw": 3.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "4", "raw": 4.0}, + "$wins": {"display": "4", "raw": 4.0}, + }, + { + "$candidate-id": {"display": "5", "raw": 5.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "6", "raw": 6.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "7", "raw": 7.0}, + "$wins": {"display": "4", "raw": 4.0}, + }, + { + "$candidate-id": {"display": "8", "raw": 8.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "9", "raw": 9.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "10", "raw": 10.0}, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$candidate-id": {"display": "11", "raw": 11.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + ], + }, + result, + ) def test_dimx2_date_str(self): - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx2_date_str_df, mock_dataset, - [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party], []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [{ - '$political_party': {'raw': 'Democrat'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} + result = ReactTable(mock_dataset.fields.wins).transform( + dimx2_date_str_df, + mock_dataset, + [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party], + [], + ) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + ], }, - { - '$political_party': {'raw': 'Independent'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '0', 'raw': 0.0} - }] - }, result) + result, + ) def test_dimx2_date_str_totals_date(self): - dimensions = [day(mock_dataset.fields.timestamp), Rollup(mock_dataset.fields.political_party)] - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx2_date_str_totals_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][-3:] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$political_party': {'raw': 'Democrat'}, - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$political_party': {'raw': 'Republican'}, - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$political_party': {'display': 'Totals', 'raw': '$totals'}, - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - } - ], - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + Rollup(mock_dataset.fields.political_party), + ] + result = ReactTable(mock_dataset.fields.wins).transform( + dimx2_date_str_totals_df, mock_dataset, dimensions, [] + ) + + self.assertIn("data", result) + result["data"] = result["data"][ + -3: + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$political_party": { + "raw": "Republican", + "hyperlink": "http://example.com/Republican", + }, + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$political_party": { + "display": "Totals", + "raw": "$totals", + "hyperlink": "http://example.com/~~totals", + }, + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + ], + }, + result, + ) def test_dimx2_date_str_totals_all(self): - dimensions = [Rollup(day(mock_dataset.fields.timestamp)), Rollup(mock_dataset.fields.political_party)] - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - self.assertIn('data', result) - result['data'] = result['data'][:3] + result['data'][-1:] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$political_party': {'raw': 'Democrat'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$political_party': {'raw': 'Independent'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$political_party': {'raw': 'Republican'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$political_party': {'display': 'Totals', 'raw': '$totals'}, - '$timestamp': {'display': 'Totals', 'raw': '$totals'}, - '$wins': {'display': '12', 'raw': 12.0} - } - ], - }, result) + dimensions = [ + Rollup(day(mock_dataset.fields.timestamp)), + Rollup(mock_dataset.fields.political_party), + ] + result = ReactTable(mock_dataset.fields.wins).transform( + dimx2_date_str_totalsx2_df, mock_dataset, dimensions, [] + ) + self.assertIn("data", result) + result["data"] = ( + result["data"][:3] + result["data"][-1:] + ) # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$political_party": { + "raw": "Republican", + "hyperlink": "http://example.com/Republican", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$political_party": { + "display": "Totals", + "raw": "$totals", + "hyperlink": "http://example.com/~~totals", + }, + "$timestamp": {"display": "Totals", "raw": "$totals"}, + "$wins": {"display": "12", "raw": 12.0}, + }, + ], + }, + result, + ) def test_dimx2_date_str_reference(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] references = [ElectionOverElection(mock_dataset.fields.timestamp)] - result = ReactTable(mock_dataset.fields.votes) \ - .transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Votes', 'accessor': '$votes'}, - {'Header': 'Votes EoE', 'accessor': '$votes_eoe'}], - 'data': [{ - '$political_party': {'raw': 'Republican'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': {'display': '6,564,547', 'raw': 6564547}, - '$votes_eoe': {'display': '7,579,518', 'raw': 7579518} + result = ReactTable(mock_dataset.fields.votes).transform( + dimx2_date_str_ref_df, mock_dataset, dimensions, references + ) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Votes", "accessor": "$votes"}, + {"Header": "Votes EoE", "accessor": "$votes_eoe"}, + ], + "data": [ + { + "$political_party": { + "raw": "Republican", + "hyperlink": "http://example.com/Republican", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": {"display": "6,564,547", "raw": 6564547}, + "$votes_eoe": {"display": "7,579,518", "raw": 7579518}, + }, + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": {"display": "8,294,949", "raw": 8294949}, + "$votes_eoe": {"display": "1,076,384", "raw": 1076384}, + }, + ], }, - { - '$political_party': {'raw': 'Democrat'}, - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': {'display': '8,294,949', 'raw': 8294949}, - '$votes_eoe': {'display': '1,076,384', 'raw': 1076384} - }] - }, result) + result, + ) def test_dimx1_date_metricsx2_references(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] references = [ElectionOverElection(mock_dataset.fields.timestamp)] - result = ReactTable(mock_dataset.fields.votes, mock_dataset.fields.wins) \ - .transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Votes', 'accessor': '$votes'}, - {'Header': 'Votes EoE', 'accessor': '$votes_eoe'}, - {'Header': 'Wins', 'accessor': '$wins'}, - {'Header': 'Wins EoE', 'accessor': '$wins_eoe'}], - 'data': [ - { - '$political_party': {'raw': 'Republican'}, - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': {'display': '6,564,547', 'raw': 6564547}, - '$votes_eoe': {'display': '7,579,518', 'raw': 7579518}, - '$wins': {'display': '0', 'raw': 0}, - '$wins_eoe': {'display': '2', 'raw': 2} - }, - { - '$political_party': {'raw': 'Democrat'}, - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': {'display': '8,294,949', 'raw': 8294949}, - '$votes_eoe': {'display': '1,076,384', 'raw': 1076384}, - '$wins': {'display': '0', 'raw': 0}, - '$wins_eoe': {'display': '0', 'raw': 0} - }] - }, result) + result = ReactTable( + mock_dataset.fields.votes, mock_dataset.fields.wins + ).transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Votes", "accessor": "$votes"}, + {"Header": "Votes EoE", "accessor": "$votes_eoe"}, + {"Header": "Wins", "accessor": "$wins"}, + {"Header": "Wins EoE", "accessor": "$wins_eoe"}, + ], + "data": [ + { + "$political_party": { + "raw": "Republican", + "hyperlink": "http://example.com/Republican", + }, + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": {"display": "6,564,547", "raw": 6564547}, + "$votes_eoe": {"display": "7,579,518", "raw": 7579518}, + "$wins": {"display": "0", "raw": 0}, + "$wins_eoe": {"display": "2", "raw": 2}, + }, + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": {"display": "8,294,949", "raw": 8294949}, + "$votes_eoe": {"display": "1,076,384", "raw": 1076384}, + "$wins": {"display": "0", "raw": 0}, + "$wins_eoe": {"display": "0", "raw": 0}, + }, + ], + }, + result, + ) def test_transpose(self): dimensions = [mock_dataset.fields.political_party] - result = ReactTable(mock_dataset.fields.wins, transpose=True) \ - .transform(dimx1_str_df, mock_dataset, dimensions, []) - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': 'Democrat', 'accessor': 'Democrat'}, - {'Header': 'Independent', 'accessor': 'Independent'}, - {'Header': 'Republican', 'accessor': 'Republican'}], - 'data': [{ - '$metrics': {'raw': 'Wins'}, - 'Democrat': {'display': '6', 'raw': 6.0}, - 'Independent': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '6', 'raw': 6.0} - }] - }, result) + result = ReactTable(mock_dataset.fields.wins, transpose=True).transform( + dimx1_str_df, mock_dataset, dimensions, [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "Democrat", "accessor": "Democrat"}, + {"Header": "Independent", "accessor": "Independent"}, + {"Header": "Republican", "accessor": "Republican"}, + ], + "data": [ + { + "$metrics": {"raw": "Wins"}, + "Democrat": {"display": "6", "raw": 6.0}, + "Independent": {"display": "0", "raw": 0.0}, + "Republican": {"display": "6", "raw": 6.0}, + } + ], + }, + result, + ) def test_transpose_without_dimension(self): - result = ReactTable(mock_dataset.fields.votes, mock_dataset.fields.wins, transpose=True) \ - .transform(dimx1_none_df, mock_dataset, [], []) - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': '', 'accessor': '0'}], - 'data': [{ - 0: {'display': '111,674,336', 'raw': 111674336}, - '$metrics': {'raw': 'Votes'} - }, { - 0: {'display': '12', 'raw': 12}, - '$metrics': {'raw': 'Wins'} - }] - }, result) + result = ReactTable( + mock_dataset.fields.votes, mock_dataset.fields.wins, transpose=True + ).transform(dimx1_none_df, mock_dataset, [], []) + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "", "accessor": "0"}, + ], + "data": [ + { + 0: {"display": "111,674,336", "raw": 111674336}, + "$metrics": {"raw": "Votes"}, + }, + {0: {"display": "12", "raw": 12}, "$metrics": {"raw": "Wins"}}, + ], + }, + result, + ) def test_dimx2_pivot_dim1(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] - result = ReactTable(mock_dataset.fields.wins, - pivot=[mock_dataset.fields.timestamp]) \ - .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': '1996-01-01', 'accessor': '$wins.1996-01-01T00:00:00'}, - {'Header': '2000-01-01', 'accessor': '$wins.2000-01-01T00:00:00'}, - {'Header': '2004-01-01', 'accessor': '$wins.2004-01-01T00:00:00'}, - {'Header': '2008-01-01', 'accessor': '$wins.2008-01-01T00:00:00'}, - {'Header': '2012-01-01', 'accessor': '$wins.2012-01-01T00:00:00'}, - {'Header': '2016-01-01', 'accessor': '$wins.2016-01-01T00:00:00'}], - 'data': [ - { - '$political_party': {'raw': 'Democrat'}, - '$wins': { - '1996-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2000-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2004-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2008-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2012-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2016-01-01T00:00:00': {'display': '0', 'raw': 0.0} - } - }, - { - '$political_party': {'raw': 'Independent'}, - '$wins': { - '1996-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2000-01-01T00:00:00': {'display': '', 'raw': None}, - '2004-01-01T00:00:00': {'display': '', 'raw': None}, - '2008-01-01T00:00:00': {'display': '', 'raw': None}, - '2012-01-01T00:00:00': {'display': '', 'raw': None}, - '2016-01-01T00:00:00': {'display': '', 'raw': None} - } - } - ] - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] + result = ReactTable( + mock_dataset.fields.wins, pivot=[mock_dataset.fields.timestamp] + ).transform(dimx2_date_str_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "1996-01-01", "accessor": "$wins.1996-01-01T00:00:00"}, + {"Header": "2000-01-01", "accessor": "$wins.2000-01-01T00:00:00"}, + {"Header": "2004-01-01", "accessor": "$wins.2004-01-01T00:00:00"}, + {"Header": "2008-01-01", "accessor": "$wins.2008-01-01T00:00:00"}, + {"Header": "2012-01-01", "accessor": "$wins.2012-01-01T00:00:00"}, + {"Header": "2016-01-01", "accessor": "$wins.2016-01-01T00:00:00"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": { + "1996-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2000-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2004-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2008-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2012-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2016-01-01T00:00:00": {"display": "0", "raw": 0.0}, + }, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$wins": { + "1996-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2000-01-01T00:00:00": {"display": "", "raw": None}, + "2004-01-01T00:00:00": {"display": "", "raw": None}, + "2008-01-01T00:00:00": {"display": "", "raw": None}, + "2012-01-01T00:00:00": {"display": "", "raw": None}, + "2016-01-01T00:00:00": {"display": "", "raw": None}, + }, + }, + ], + }, + result, + ) def test_dimx2_pivot_dim1_with_sorting(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] - result = ReactTable(mock_dataset.fields.wins, - pivot=[mock_dataset.fields.timestamp], - sort=[0]) \ - .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': '1996-01-01', 'accessor': '$wins.1996-01-01T00:00:00'}, - {'Header': '2000-01-01', 'accessor': '$wins.2000-01-01T00:00:00'}, - {'Header': '2004-01-01', 'accessor': '$wins.2004-01-01T00:00:00'}, - {'Header': '2008-01-01', 'accessor': '$wins.2008-01-01T00:00:00'}, - {'Header': '2012-01-01', 'accessor': '$wins.2012-01-01T00:00:00'}, - {'Header': '2016-01-01', 'accessor': '$wins.2016-01-01T00:00:00'}], - 'data': [ - { - '$political_party': {'raw': 'Democrat'}, - '$wins': { - '1996-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2000-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2004-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2008-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2012-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2016-01-01T00:00:00': {'display': '0', 'raw': 0.0} - } - }, - { - '$political_party': {'raw': 'Independent'}, - '$wins': { - '1996-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2000-01-01T00:00:00': {'display': '', 'raw': None}, - '2004-01-01T00:00:00': {'display': '', 'raw': None}, - '2008-01-01T00:00:00': {'display': '', 'raw': None}, - '2012-01-01T00:00:00': {'display': '', 'raw': None}, - '2016-01-01T00:00:00': {'display': '', 'raw': None} - } - } - ] - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] + result = ReactTable( + mock_dataset.fields.wins, pivot=[mock_dataset.fields.timestamp], sort=[0] + ).transform(dimx2_date_str_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "1996-01-01", "accessor": "$wins.1996-01-01T00:00:00"}, + {"Header": "2000-01-01", "accessor": "$wins.2000-01-01T00:00:00"}, + {"Header": "2004-01-01", "accessor": "$wins.2004-01-01T00:00:00"}, + {"Header": "2008-01-01", "accessor": "$wins.2008-01-01T00:00:00"}, + {"Header": "2012-01-01", "accessor": "$wins.2012-01-01T00:00:00"}, + {"Header": "2016-01-01", "accessor": "$wins.2016-01-01T00:00:00"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": { + "1996-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2000-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2004-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2008-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2012-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2016-01-01T00:00:00": {"display": "0", "raw": 0.0}, + }, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$wins": { + "1996-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2000-01-01T00:00:00": {"display": "", "raw": None}, + "2004-01-01T00:00:00": {"display": "", "raw": None}, + "2008-01-01T00:00:00": {"display": "", "raw": None}, + "2012-01-01T00:00:00": {"display": "", "raw": None}, + "2016-01-01T00:00:00": {"display": "", "raw": None}, + }, + }, + ], + }, + result, + ) def test_dimx2_pivot_dim2(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] - result = ReactTable(mock_dataset.fields.wins, pivot=[mock_dataset.fields.political_party]) \ - .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Democrat', 'accessor': '$wins.Democrat'}, - {'Header': 'Independent', 'accessor': '$wins.Independent'}, - {'Header': 'Republican', 'accessor': '$wins.Republican'}], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': { - 'Democrat': {'display': '2', 'raw': 2.0}, - 'Independent': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '0', 'raw': 0.0} - } - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$wins': { - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2.0} - } - }, - ] - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] + result = ReactTable( + mock_dataset.fields.wins, pivot=[mock_dataset.fields.political_party] + ).transform(dimx2_date_str_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Democrat", "accessor": "$wins.Democrat"}, + {"Header": "Independent", "accessor": "$wins.Independent"}, + {"Header": "Republican", "accessor": "$wins.Republican"}, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": { + "Democrat": {"display": "2", "raw": 2.0}, + "Independent": {"display": "0", "raw": 0.0}, + "Republican": {"display": "0", "raw": 0.0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$wins": { + "Democrat": {"display": "0", "raw": 0.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2.0}, + }, + }, + ], + }, + result, + ) def test_metricx2_pivot_dim2(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, - pivot=[mock_dataset.fields.political_party]) \ - .transform(dimx2_date_str_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [ - {'Header': 'Timestamp', 'accessor': '$timestamp'}, - { - 'Header': 'Votes', - 'columns': [{'Header': 'Democrat', 'accessor': '$votes.Democrat'}, - { - 'Header': 'Independent', - 'accessor': '$votes.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$votes.Republican' - }] - }, - { - 'Header': 'Wins', - 'columns': [{'Header': 'Democrat', 'accessor': '$wins.Democrat'}, - { - 'Header': 'Independent', - 'accessor': '$wins.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$wins.Republican' - }] - } - ], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': { - 'Democrat': {'display': '7,579,518', 'raw': 7579518}, - 'Independent': {'display': '1,076,384', 'raw': 1076384}, - 'Republican': {'display': '6,564,547', 'raw': 6564547} - }, - '$wins': { - 'Democrat': {'display': '2', 'raw': 2}, - 'Independent': {'display': '0', 'raw': 0}, - 'Republican': {'display': '0', 'raw': 0} - } - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': { - 'Democrat': {'display': '8,294,949', 'raw': 8294949}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '8,367,068', 'raw': 8367068} - }, - '$wins': { - 'Democrat': {'display': '0', 'raw': 0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2} - } - }] - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] + result = ReactTable( + mock_dataset.fields.wins, + mock_dataset.fields.votes, + pivot=[mock_dataset.fields.political_party], + ).transform(dimx2_date_str_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + { + "Header": "Votes", + "columns": [ + {"Header": "Democrat", "accessor": "$votes.Democrat"}, + {"Header": "Independent", "accessor": "$votes.Independent"}, + {"Header": "Republican", "accessor": "$votes.Republican"}, + ], + }, + { + "Header": "Wins", + "columns": [ + {"Header": "Democrat", "accessor": "$wins.Democrat"}, + {"Header": "Independent", "accessor": "$wins.Independent"}, + {"Header": "Republican", "accessor": "$wins.Republican"}, + ], + }, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": { + "Democrat": {"display": "7,579,518", "raw": 7579518}, + "Independent": {"display": "1,076,384", "raw": 1076384}, + "Republican": {"display": "6,564,547", "raw": 6564547}, + }, + "$wins": { + "Democrat": {"display": "2", "raw": 2}, + "Independent": {"display": "0", "raw": 0}, + "Republican": {"display": "0", "raw": 0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": { + "Democrat": {"display": "8,294,949", "raw": 8294949}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "8,367,068", "raw": 8367068}, + }, + "$wins": { + "Democrat": {"display": "0", "raw": 0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2}, + }, + }, + ], + }, + result, + ) def test_dimx2_metricx2_refx2_pivot_dim2(self): - dimensions = [day(mock_dataset.fields.timestamp), mock_dataset.fields.political_party] + dimensions = [ + day(mock_dataset.fields.timestamp), + mock_dataset.fields.political_party, + ] references = [ElectionOverElection(mock_dataset.fields.timestamp)] - result = ReactTable(mock_dataset.fields.votes, mock_dataset.fields.wins, - pivot=[mock_dataset.fields.political_party]) \ - .transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [ - {'Header': 'Timestamp', 'accessor': '$timestamp'}, - { - 'Header': 'Votes', - 'columns': [{ - 'Header': 'Republican', - 'accessor': '$votes.Republican' - }, - { - 'Header': 'Democrat', - 'accessor': '$votes.Democrat' - }] - }, - { - 'Header': 'Votes EoE', - 'columns': [{ - 'Header': 'Republican', - 'accessor': '$votes_eoe.Republican' - }, - { - 'Header': 'Democrat', - 'accessor': '$votes_eoe.Democrat' - }] - }, - { - 'Header': 'Wins', - 'columns': [{ - 'Header': 'Republican', - 'accessor': '$wins.Republican' - }, - { - 'Header': 'Democrat', - 'accessor': '$wins.Democrat' - }] - }, - { - 'Header': 'Wins EoE', - 'columns': [{ - 'Header': 'Republican', - 'accessor': '$wins_eoe.Republican' - }, - { - 'Header': 'Democrat', - 'accessor': '$wins_eoe.Democrat' - }] - }], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': { - 'Democrat': {'display': '', 'raw': None}, - 'Republican': {'display': '6,564,547', 'raw': 6564547.0} - }, - '$votes_eoe': { - 'Democrat': {'display': '', 'raw': None}, - 'Republican': { - 'display': '7,579,518', - 'raw': 7579518.0 - } - }, - '$wins': { - 'Democrat': {'display': '', 'raw': None}, - 'Republican': {'display': '0', 'raw': 0.0} - }, - '$wins_eoe': { - 'Democrat': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2.0} - } - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': { - 'Democrat': {'display': '8,294,949', 'raw': 8294949.0}, - 'Republican': {'display': '8,367,068', 'raw': 8367068.0} - }, - '$votes_eoe': { - 'Democrat': { - 'display': '1,076,384', - 'raw': 1076384.0 - }, - 'Republican': { - 'display': '6,564,547', - 'raw': 6564547.0 - } - }, - '$wins': { - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '2', 'raw': 2.0} - }, - '$wins_eoe': { - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '0', 'raw': 0.0} - } - }] - }, result) + result = ReactTable( + mock_dataset.fields.votes, + mock_dataset.fields.wins, + pivot=[mock_dataset.fields.political_party], + ).transform(dimx2_date_str_ref_df, mock_dataset, dimensions, references) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + { + "Header": "Votes", + "columns": [ + {"Header": "Republican", "accessor": "$votes.Republican"}, + {"Header": "Democrat", "accessor": "$votes.Democrat"}, + ], + }, + { + "Header": "Votes EoE", + "columns": [ + { + "Header": "Republican", + "accessor": "$votes_eoe.Republican", + }, + {"Header": "Democrat", "accessor": "$votes_eoe.Democrat"}, + ], + }, + { + "Header": "Wins", + "columns": [ + {"Header": "Republican", "accessor": "$wins.Republican"}, + {"Header": "Democrat", "accessor": "$wins.Democrat"}, + ], + }, + { + "Header": "Wins EoE", + "columns": [ + { + "Header": "Republican", + "accessor": "$wins_eoe.Republican", + }, + {"Header": "Democrat", "accessor": "$wins_eoe.Democrat"}, + ], + }, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": { + "Democrat": {"display": "", "raw": None}, + "Republican": {"display": "6,564,547", "raw": 6564547.0}, + }, + "$votes_eoe": { + "Democrat": {"display": "", "raw": None}, + "Republican": {"display": "7,579,518", "raw": 7579518.0}, + }, + "$wins": { + "Democrat": {"display": "", "raw": None}, + "Republican": {"display": "0", "raw": 0.0}, + }, + "$wins_eoe": { + "Democrat": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2.0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": { + "Democrat": {"display": "8,294,949", "raw": 8294949.0}, + "Republican": {"display": "8,367,068", "raw": 8367068.0}, + }, + "$votes_eoe": { + "Democrat": {"display": "1,076,384", "raw": 1076384.0}, + "Republican": {"display": "6,564,547", "raw": 6564547.0}, + }, + "$wins": { + "Democrat": {"display": "0", "raw": 0.0}, + "Republican": {"display": "2", "raw": 2.0}, + }, + "$wins_eoe": { + "Democrat": {"display": "0", "raw": 0.0}, + "Republican": {"display": "0", "raw": 0.0}, + }, + }, + ], + }, + result, + ) def test_dimx1_int_metricx1_pivot_dim1_same_as_transpose(self): - result = ReactTable(mock_dataset.fields.wins, pivot=[mock_dataset.fields['candidate-id']]) \ - .transform(dimx1_num_df, mock_dataset, [mock_dataset.fields['candidate-id']], []) - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': '1', 'accessor': '1'}, - {'Header': '2', 'accessor': '2'}, - {'Header': '3', 'accessor': '3'}, - {'Header': '4', 'accessor': '4'}, - {'Header': '5', 'accessor': '5'}, - {'Header': '6', 'accessor': '6'}, - {'Header': '7', 'accessor': '7'}, - {'Header': '8', 'accessor': '8'}, - {'Header': '9', 'accessor': '9'}, - {'Header': '10', 'accessor': '10'}, - {'Header': '11', 'accessor': '11'}], - 'data': [{ - '$metrics': {'raw': 'Wins'}, - '1': {'display': '2', 'raw': 2.0}, - '2': {'display': '0', 'raw': 0.0}, - '3': {'display': '0', 'raw': 0.0}, - '4': {'display': '4', 'raw': 4.0}, - '5': {'display': '0', 'raw': 0.0}, - '6': {'display': '0', 'raw': 0.0}, - '7': {'display': '4', 'raw': 4.0}, - '8': {'display': '0', 'raw': 0.0}, - '9': {'display': '0', 'raw': 0.0}, - '10': {'display': '2', 'raw': 2.0}, - '11': {'display': '0', 'raw': 0.0}, - }] - }, result) + result = ReactTable( + mock_dataset.fields.wins, pivot=[mock_dataset.fields["candidate-id"]] + ).transform( + dimx1_num_df, mock_dataset, [mock_dataset.fields["candidate-id"]], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "1", "accessor": "1"}, + {"Header": "2", "accessor": "2"}, + {"Header": "3", "accessor": "3"}, + {"Header": "4", "accessor": "4"}, + {"Header": "5", "accessor": "5"}, + {"Header": "6", "accessor": "6"}, + {"Header": "7", "accessor": "7"}, + {"Header": "8", "accessor": "8"}, + {"Header": "9", "accessor": "9"}, + {"Header": "10", "accessor": "10"}, + {"Header": "11", "accessor": "11"}, + ], + "data": [ + { + "$metrics": {"raw": "Wins"}, + "1": {"display": "2", "raw": 2.0}, + "2": {"display": "0", "raw": 0.0}, + "3": {"display": "0", "raw": 0.0}, + "4": {"display": "4", "raw": 4.0}, + "5": {"display": "0", "raw": 0.0}, + "6": {"display": "0", "raw": 0.0}, + "7": {"display": "4", "raw": 4.0}, + "8": {"display": "0", "raw": 0.0}, + "9": {"display": "0", "raw": 0.0}, + "10": {"display": "2", "raw": 2.0}, + "11": {"display": "0", "raw": 0.0}, + } + ], + }, + result, + ) def test_dimx1_int_metricx1_transpose(self): - result = ReactTable(mock_dataset.fields.wins, pivot=[mock_dataset.fields['candidate-id']], transpose=True) \ - .transform(dimx1_num_df, mock_dataset, [mock_dataset.fields['candidate-id']], []) - - self.assertEqual({ - 'columns': [{'Header': 'Candidate ID', 'accessor': '$candidate-id'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$candidate-id': {'display': '1', 'raw': 1.0}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$candidate-id': {'display': '2', 'raw': 2.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '3', 'raw': 3.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '4', 'raw': 4.0}, - '$wins': {'display': '4', 'raw': 4.0} - }, - { - '$candidate-id': {'display': '5', 'raw': 5.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '6', 'raw': 6.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '7', 'raw': 7.0}, - '$wins': {'display': '4', 'raw': 4.0} - }, - { - '$candidate-id': {'display': '8', 'raw': 8.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '9', 'raw': 9.0}, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$candidate-id': {'display': '10', 'raw': 10.0}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$candidate-id': {'display': '11', 'raw': 11.0}, - '$wins': {'display': '0', 'raw': 0.0} - } - ], - }, result) + result = ReactTable( + mock_dataset.fields.wins, + pivot=[mock_dataset.fields["candidate-id"]], + transpose=True, + ).transform( + dimx1_num_df, mock_dataset, [mock_dataset.fields["candidate-id"]], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Candidate ID", "accessor": "$candidate-id"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$candidate-id": {"display": "1", "raw": 1.0}, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$candidate-id": {"display": "2", "raw": 2.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "3", "raw": 3.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "4", "raw": 4.0}, + "$wins": {"display": "4", "raw": 4.0}, + }, + { + "$candidate-id": {"display": "5", "raw": 5.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "6", "raw": 6.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "7", "raw": 7.0}, + "$wins": {"display": "4", "raw": 4.0}, + }, + { + "$candidate-id": {"display": "8", "raw": 8.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "9", "raw": 9.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$candidate-id": {"display": "10", "raw": 10.0}, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$candidate-id": {"display": "11", "raw": 11.0}, + "$wins": {"display": "0", "raw": 0.0}, + }, + ], + }, + result, + ) def test_dimx1_int_metricx2_pivot(self): - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, - pivot=[mock_dataset.fields['candidate-id']]) \ - .transform(dimx1_num_df, mock_dataset, [mock_dataset.fields['candidate-id']], []) - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': '1', 'accessor': '1'}, - {'Header': '2', 'accessor': '2'}, - {'Header': '3', 'accessor': '3'}, - {'Header': '4', 'accessor': '4'}, - {'Header': '5', 'accessor': '5'}, - {'Header': '6', 'accessor': '6'}, - {'Header': '7', 'accessor': '7'}, - {'Header': '8', 'accessor': '8'}, - {'Header': '9', 'accessor': '9'}, - {'Header': '10', 'accessor': '10'}, - {'Header': '11', 'accessor': '11'}], - 'data': [ - { - '1': {'display': '2', 'raw': 2.0}, - '2': {'display': '0', 'raw': 0.0}, - '3': {'display': '0', 'raw': 0.0}, - '4': {'display': '4', 'raw': 4.0}, - '5': {'display': '0', 'raw': 0.0}, - '6': {'display': '0', 'raw': 0.0}, - '7': {'display': '4', 'raw': 4.0}, - '8': {'display': '0', 'raw': 0.0}, - '9': {'display': '0', 'raw': 0.0}, - '10': {'display': '2', 'raw': 2.0}, - '11': {'display': '0', 'raw': 0.0}, - '$metrics': {'raw': 'Wins'} - }, - { - '1': {'display': '7,579,518', 'raw': 7579518.0}, - '2': {'display': '6,564,547', 'raw': 6564547.0}, - '3': {'display': '1,076,384', 'raw': 1076384.0}, - '4': {'display': '18,403,811', 'raw': 18403811.0}, - '5': {'display': '8,294,949', 'raw': 8294949.0}, - '6': {'display': '9,578,189', 'raw': 9578189.0}, - '7': {'display': '24,227,234', 'raw': 24227234.0}, - '8': {'display': '9,491,109', 'raw': 9491109.0}, - '9': {'display': '8,148,082', 'raw': 8148082.0}, - '10': {'display': '13,438,835', 'raw': 13438835.0}, - '11': {'display': '4,871,678', 'raw': 4871678.0}, - '$metrics': {'raw': 'Votes'} - }] - }, result) + result = ReactTable( + mock_dataset.fields.wins, + mock_dataset.fields.votes, + pivot=[mock_dataset.fields["candidate-id"]], + ).transform( + dimx1_num_df, mock_dataset, [mock_dataset.fields["candidate-id"]], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "1", "accessor": "1"}, + {"Header": "2", "accessor": "2"}, + {"Header": "3", "accessor": "3"}, + {"Header": "4", "accessor": "4"}, + {"Header": "5", "accessor": "5"}, + {"Header": "6", "accessor": "6"}, + {"Header": "7", "accessor": "7"}, + {"Header": "8", "accessor": "8"}, + {"Header": "9", "accessor": "9"}, + {"Header": "10", "accessor": "10"}, + {"Header": "11", "accessor": "11"}, + ], + "data": [ + { + "1": {"display": "2", "raw": 2.0}, + "2": {"display": "0", "raw": 0.0}, + "3": {"display": "0", "raw": 0.0}, + "4": {"display": "4", "raw": 4.0}, + "5": {"display": "0", "raw": 0.0}, + "6": {"display": "0", "raw": 0.0}, + "7": {"display": "4", "raw": 4.0}, + "8": {"display": "0", "raw": 0.0}, + "9": {"display": "0", "raw": 0.0}, + "10": {"display": "2", "raw": 2.0}, + "11": {"display": "0", "raw": 0.0}, + "$metrics": {"raw": "Wins"}, + }, + { + "1": {"display": "7,579,518", "raw": 7579518.0}, + "2": {"display": "6,564,547", "raw": 6564547.0}, + "3": {"display": "1,076,384", "raw": 1076384.0}, + "4": {"display": "18,403,811", "raw": 18403811.0}, + "5": {"display": "8,294,949", "raw": 8294949.0}, + "6": {"display": "9,578,189", "raw": 9578189.0}, + "7": {"display": "24,227,234", "raw": 24227234.0}, + "8": {"display": "9,491,109", "raw": 9491109.0}, + "9": {"display": "8,148,082", "raw": 8148082.0}, + "10": {"display": "13,438,835", "raw": 13438835.0}, + "11": {"display": "4,871,678", "raw": 4871678.0}, + "$metrics": {"raw": "Votes"}, + }, + ], + }, + result, + ) def test_dimx1_date_metricx1(self): - result = ReactTable(mock_dataset.fields.wins) \ - .transform(dimx1_date_df, mock_dataset, [day(mock_dataset.fields.timestamp)], []) - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$timestamp': {'display': '2004-01-01', 'raw': '2004-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$timestamp': {'display': '2008-01-01', 'raw': '2008-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$timestamp': {'display': '2012-01-01', 'raw': '2012-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - }, - { - '$timestamp': {'display': '2016-01-01', 'raw': '2016-01-01T00:00:00'}, - '$wins': {'display': '2', 'raw': 2.0} - } - ] - }, result) + result = ReactTable(mock_dataset.fields.wins).transform( + dimx1_date_df, mock_dataset, [day(mock_dataset.fields.timestamp)], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$timestamp": { + "display": "2004-01-01", + "raw": "2004-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$timestamp": { + "display": "2008-01-01", + "raw": "2008-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$timestamp": { + "display": "2012-01-01", + "raw": "2012-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + { + "$timestamp": { + "display": "2016-01-01", + "raw": "2016-01-01T00:00:00", + }, + "$wins": {"display": "2", "raw": 2.0}, + }, + ], + }, + result, + ) def test_dimx2_metricx1_pivot_dim2_rollup_dim2(self): - dimensions = [day(mock_dataset.fields.timestamp), Rollup(mock_dataset.fields.political_party)] - result = ReactTable(mock_dataset.fields.votes, - pivot=[mock_dataset.fields.political_party]) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] + result['data'][-1:] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - { - 'Header': 'Democrat', - 'accessor': '$votes.Democrat' - }, - { - 'Header': 'Independent', - 'accessor': '$votes.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$votes.Republican' - }, - { - 'Header': 'Totals', - 'accessor': '$votes.$totals', - 'className': 'fireant-totals' - }], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': { - '$totals': {'display': '15,220,449', 'raw': 15220449.0}, - 'Democrat': {'display': '7,579,518', 'raw': 7579518.0}, - 'Independent': {'display': '1,076,384', 'raw': 1076384.0}, - 'Republican': {'display': '6,564,547', 'raw': 6564547.0} - }, - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': { - '$totals': {'display': '16,662,017', 'raw': 16662017.0}, - 'Democrat': {'display': '8,294,949', 'raw': 8294949.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '8,367,068', 'raw': 8367068.0} - }, - }, - { - '$timestamp': {'display': 'Totals', 'raw': '$totals'}, - '$votes': { - '$totals': {'display': '111,674,336', 'raw': 111674336.0}, - 'Democrat': {'display': '', 'raw': None}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '', 'raw': None} - }, - } - ] - }, result) + dimensions = [ + day(mock_dataset.fields.timestamp), + Rollup(mock_dataset.fields.political_party), + ] + result = ReactTable( + mock_dataset.fields.votes, pivot=[mock_dataset.fields.political_party] + ).transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = ( + result["data"][:2] + result["data"][-1:] + ) # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + {"Header": "Democrat", "accessor": "$votes.Democrat"}, + {"Header": "Independent", "accessor": "$votes.Independent"}, + {"Header": "Republican", "accessor": "$votes.Republican"}, + { + "Header": "Totals", + "accessor": "$votes.$totals", + "className": "fireant-totals", + }, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "15,220,449", "raw": 15220449.0}, + "Democrat": {"display": "7,579,518", "raw": 7579518.0}, + "Independent": {"display": "1,076,384", "raw": 1076384.0}, + "Republican": {"display": "6,564,547", "raw": 6564547.0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "16,662,017", "raw": 16662017.0}, + "Democrat": {"display": "8,294,949", "raw": 8294949.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "8,367,068", "raw": 8367068.0}, + }, + }, + { + "$timestamp": {"display": "Totals", "raw": "$totals"}, + "$votes": { + "$totals": {"display": "111,674,336", "raw": 111674336.0}, + "Democrat": {"display": "", "raw": None}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "", "raw": None}, + }, + }, + ], + }, + result, + ) def test_dimx2_date_str_pivot_dim2_rollup_all(self): political_party = Rollup(mock_dataset.fields.political_party) dimensions = [Rollup(day(mock_dataset.fields.timestamp)), political_party] - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, pivot=[political_party]) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] + result['data'][-1:] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - { - 'Header': 'Votes', - 'columns': [ - { - 'Header': 'Democrat', - 'accessor': '$votes.Democrat' - }, - { - 'Header': 'Independent', - 'accessor': '$votes.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$votes.Republican' - }, - { - 'Header': 'Totals', - 'accessor': '$votes.$totals', - 'className': 'fireant-totals' - } - ], - }, - { - 'Header': 'Wins', - 'columns': [ - { - 'Header': 'Democrat', - 'accessor': '$wins.Democrat' - }, - { - 'Header': 'Independent', - 'accessor': '$wins.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$wins.Republican' - }, - { - 'Header': 'Totals', - 'accessor': '$wins.$totals', - 'className': 'fireant-totals' - } - ], - }], - 'data': [ - { - '$timestamp': {'display': '1996-01-01', 'raw': '1996-01-01T00:00:00'}, - '$votes': { - '$totals': {'display': '15,220,449', 'raw': 15220449.0}, - 'Democrat': {'display': '7,579,518', 'raw': 7579518.0}, - 'Independent': {'display': '1,076,384', 'raw': 1076384.0}, - 'Republican': {'display': '6,564,547', 'raw': 6564547.0} - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '2', 'raw': 2.0}, - 'Independent': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '0', 'raw': 0.0} - } - }, - { - '$timestamp': {'display': '2000-01-01', 'raw': '2000-01-01T00:00:00'}, - '$votes': { - '$totals': {'display': '16,662,017', 'raw': 16662017.0}, - 'Democrat': {'display': '8,294,949', 'raw': 8294949.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '8,367,068', 'raw': 8367068.0} - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2.0} - } - }, - { - '$timestamp': {'display': 'Totals', 'raw': '$totals'}, - '$votes': { - '$totals': {'display': '111,674,336', 'raw': 111674336.0}, - 'Democrat': {'display': '', 'raw': None}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '', 'raw': None} - }, - '$wins': { - '$totals': {'display': '12', 'raw': 12.0}, - 'Democrat': {'display': '', 'raw': None}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '', 'raw': None} - } - }] - }, result) + result = ReactTable( + mock_dataset.fields.wins, mock_dataset.fields.votes, pivot=[political_party] + ).transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = ( + result["data"][:2] + result["data"][-1:] + ) # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + { + "Header": "Votes", + "columns": [ + {"Header": "Democrat", "accessor": "$votes.Democrat"}, + {"Header": "Independent", "accessor": "$votes.Independent"}, + {"Header": "Republican", "accessor": "$votes.Republican"}, + { + "Header": "Totals", + "accessor": "$votes.$totals", + "className": "fireant-totals", + }, + ], + }, + { + "Header": "Wins", + "columns": [ + {"Header": "Democrat", "accessor": "$wins.Democrat"}, + {"Header": "Independent", "accessor": "$wins.Independent"}, + {"Header": "Republican", "accessor": "$wins.Republican"}, + { + "Header": "Totals", + "accessor": "$wins.$totals", + "className": "fireant-totals", + }, + ], + }, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "15,220,449", "raw": 15220449.0}, + "Democrat": {"display": "7,579,518", "raw": 7579518.0}, + "Independent": {"display": "1,076,384", "raw": 1076384.0}, + "Republican": {"display": "6,564,547", "raw": 6564547.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "2", "raw": 2.0}, + "Independent": {"display": "0", "raw": 0.0}, + "Republican": {"display": "0", "raw": 0.0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "16,662,017", "raw": 16662017.0}, + "Democrat": {"display": "8,294,949", "raw": 8294949.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "8,367,068", "raw": 8367068.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "0", "raw": 0.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2.0}, + }, + }, + { + "$timestamp": {"display": "Totals", "raw": "$totals"}, + "$votes": { + "$totals": {"display": "111,674,336", "raw": 111674336.0}, + "Democrat": {"display": "", "raw": None}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "", "raw": None}, + }, + "$wins": { + "$totals": {"display": "12", "raw": 12.0}, + "Democrat": {"display": "", "raw": None}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "", "raw": None}, + }, + }, + ], + }, + result, + ) def test_dimx2_pivot_both_dims_and_transpose(self): political_party = Rollup(mock_dataset.fields.political_party) dimensions = [Rollup(day(mock_dataset.fields.timestamp)), political_party] - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, - pivot=[political_party]) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:4] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Timestamp', 'accessor': '$timestamp'}, - { - 'Header': 'Votes', - 'columns': [{'Header': 'Democrat', 'accessor': '$votes.Democrat'}, - { - 'Header': 'Independent', - 'accessor': '$votes.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$votes.Republican' - }, - { - 'Header': 'Totals', - 'accessor': '$votes.$totals', - 'className': 'fireant-totals' - }] - }, - { - 'Header': 'Wins', - 'columns': [{'Header': 'Democrat', 'accessor': '$wins.Democrat'}, - { - 'Header': 'Independent', - 'accessor': '$wins.Independent' - }, - { - 'Header': 'Republican', - 'accessor': '$wins.Republican' - }, - { - 'Header': 'Totals', - 'accessor': '$wins.$totals', - 'className': 'fireant-totals' - }] - }], - 'data': [{ - '$timestamp': { - 'display': '1996-01-01', - 'raw': '1996-01-01T00:00:00' - }, - '$votes': { - '$totals': {'display': '15,220,449', 'raw': 15220449.0}, - 'Democrat': {'display': '7,579,518', 'raw': 7579518.0}, - 'Independent': {'display': '1,076,384', 'raw': 1076384.0}, - 'Republican': {'display': '6,564,547', 'raw': 6564547.0} - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '2', 'raw': 2.0}, - 'Independent': {'display': '0', 'raw': 0.0}, - 'Republican': {'display': '0', 'raw': 0.0} - } + result = ReactTable( + mock_dataset.fields.wins, mock_dataset.fields.votes, pivot=[political_party] + ).transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :4 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Timestamp", "accessor": "$timestamp"}, + { + "Header": "Votes", + "columns": [ + {"Header": "Democrat", "accessor": "$votes.Democrat"}, + {"Header": "Independent", "accessor": "$votes.Independent"}, + {"Header": "Republican", "accessor": "$votes.Republican"}, + { + "Header": "Totals", + "accessor": "$votes.$totals", + "className": "fireant-totals", + }, + ], + }, + { + "Header": "Wins", + "columns": [ + {"Header": "Democrat", "accessor": "$wins.Democrat"}, + {"Header": "Independent", "accessor": "$wins.Independent"}, + {"Header": "Republican", "accessor": "$wins.Republican"}, + { + "Header": "Totals", + "accessor": "$wins.$totals", + "className": "fireant-totals", + }, + ], + }, + ], + "data": [ + { + "$timestamp": { + "display": "1996-01-01", + "raw": "1996-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "15,220,449", "raw": 15220449.0}, + "Democrat": {"display": "7,579,518", "raw": 7579518.0}, + "Independent": {"display": "1,076,384", "raw": 1076384.0}, + "Republican": {"display": "6,564,547", "raw": 6564547.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "2", "raw": 2.0}, + "Independent": {"display": "0", "raw": 0.0}, + "Republican": {"display": "0", "raw": 0.0}, + }, + }, + { + "$timestamp": { + "display": "2000-01-01", + "raw": "2000-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "16,662,017", "raw": 16662017.0}, + "Democrat": {"display": "8,294,949", "raw": 8294949.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "8,367,068", "raw": 8367068.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "0", "raw": 0.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2.0}, + }, + }, + { + "$timestamp": { + "display": "2004-01-01", + "raw": "2004-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "19,614,932", "raw": 19614932.0}, + "Democrat": {"display": "9,578,189", "raw": 9578189.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "10,036,743", "raw": 10036743.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "0", "raw": 0.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "2", "raw": 2.0}, + }, + }, + { + "$timestamp": { + "display": "2008-01-01", + "raw": "2008-01-01T00:00:00", + }, + "$votes": { + "$totals": {"display": "21,294,215", "raw": 21294215.0}, + "Democrat": {"display": "11,803,106", "raw": 11803106.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "9,491,109", "raw": 9491109.0}, + }, + "$wins": { + "$totals": {"display": "2", "raw": 2.0}, + "Democrat": {"display": "2", "raw": 2.0}, + "Independent": {"display": "", "raw": None}, + "Republican": {"display": "0", "raw": 0.0}, + }, + }, + ], }, - { - '$timestamp': { - 'display': '2000-01-01', - 'raw': '2000-01-01T00:00:00' - }, - '$votes': { - '$totals': {'display': '16,662,017', 'raw': 16662017.0}, - 'Democrat': {'display': '8,294,949', 'raw': 8294949.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '8,367,068', 'raw': 8367068.0} - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2.0} - } - }, - { - '$timestamp': { - 'display': '2004-01-01', - 'raw': '2004-01-01T00:00:00' - }, - '$votes': { - '$totals': {'display': '19,614,932', 'raw': 19614932.0}, - 'Democrat': {'display': '9,578,189', 'raw': 9578189.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': { - 'display': '10,036,743', - 'raw': 10036743.0 - } - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '0', 'raw': 0.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '2', 'raw': 2.0} - } - }, - { - '$timestamp': { - 'display': '2008-01-01', - 'raw': '2008-01-01T00:00:00' - }, - '$votes': { - '$totals': {'display': '21,294,215', 'raw': 21294215.0}, - 'Democrat': {'display': '11,803,106', 'raw': 11803106.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '9,491,109', 'raw': 9491109.0} - }, - '$wins': { - '$totals': {'display': '2', 'raw': 2.0}, - 'Democrat': {'display': '2', 'raw': 2.0}, - 'Independent': {'display': '', 'raw': None}, - 'Republican': {'display': '0', 'raw': 0.0} - } - }] - }, result) + result, + ) def test_dimx2_date_str_pivot_dim2_transpose_rollup_all(self): political_party = Rollup(mock_dataset.fields.political_party) dimensions = [Rollup(day(mock_dataset.fields.timestamp)), political_party] - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, - pivot=[political_party], - transpose=True) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': '1996-01-01', 'accessor': '1996-01-01T00:00:00'}, - {'Header': '2000-01-01', 'accessor': '2000-01-01T00:00:00'}, - {'Header': '2004-01-01', 'accessor': '2004-01-01T00:00:00'}, - {'Header': '2008-01-01', 'accessor': '2008-01-01T00:00:00'}, - {'Header': '2012-01-01', 'accessor': '2012-01-01T00:00:00'}, - {'Header': '2016-01-01', 'accessor': '2016-01-01T00:00:00'}, - {'Header': 'Totals', 'accessor': '$totals', 'className': 'fireant-totals'}], - 'data': [ - { - '$metrics': {'raw': 'Wins'}, - '$political_party': {'raw': 'Democrat'}, - '$totals': {'display': '', 'raw': None}, - '1996-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2000-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2004-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2008-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2012-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2016-01-01T00:00:00': {'display': '0', 'raw': 0.0} - }, - { - '$metrics': {'raw': 'Wins'}, - '$political_party': {'raw': 'Independent'}, - '$totals': {'display': '', 'raw': None}, - '1996-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2000-01-01T00:00:00': {'display': '', 'raw': None}, - '2004-01-01T00:00:00': {'display': '', 'raw': None}, - '2008-01-01T00:00:00': {'display': '', 'raw': None}, - '2012-01-01T00:00:00': {'display': '', 'raw': None}, - '2016-01-01T00:00:00': {'display': '', 'raw': None} - }] - }, result) + result = ReactTable( + mock_dataset.fields.wins, + mock_dataset.fields.votes, + pivot=[political_party], + transpose=True, + ).transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "1996-01-01", "accessor": "1996-01-01T00:00:00"}, + {"Header": "2000-01-01", "accessor": "2000-01-01T00:00:00"}, + {"Header": "2004-01-01", "accessor": "2004-01-01T00:00:00"}, + {"Header": "2008-01-01", "accessor": "2008-01-01T00:00:00"}, + {"Header": "2012-01-01", "accessor": "2012-01-01T00:00:00"}, + {"Header": "2016-01-01", "accessor": "2016-01-01T00:00:00"}, + { + "Header": "Totals", + "accessor": "$totals", + "className": "fireant-totals", + }, + ], + "data": [ + { + "$metrics": {"raw": "Wins"}, + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$totals": {"display": "", "raw": None}, + "1996-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2000-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2004-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2008-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2012-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2016-01-01T00:00:00": {"display": "0", "raw": 0.0}, + }, + { + "$metrics": {"raw": "Wins"}, + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$totals": {"display": "", "raw": None}, + "1996-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2000-01-01T00:00:00": {"display": "", "raw": None}, + "2004-01-01T00:00:00": {"display": "", "raw": None}, + "2008-01-01T00:00:00": {"display": "", "raw": None}, + "2012-01-01T00:00:00": {"display": "", "raw": None}, + "2016-01-01T00:00:00": {"display": "", "raw": None}, + }, + ], + }, + result, + ) def test_dimx2_pivot_dim2_rollup_all_no_rollup_on_pivot_arg(self): - dimensions = [Rollup(day(mock_dataset.fields.timestamp)), - Rollup(mock_dataset.fields.political_party)] - result = ReactTable(mock_dataset.fields.wins, mock_dataset.fields.votes, - pivot=[mock_dataset.fields.political_party], - transpose=True) \ - .transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': 'Party', 'accessor': '$political_party'}, - {'Header': '1996-01-01', 'accessor': '1996-01-01T00:00:00'}, - {'Header': '2000-01-01', 'accessor': '2000-01-01T00:00:00'}, - {'Header': '2004-01-01', 'accessor': '2004-01-01T00:00:00'}, - {'Header': '2008-01-01', 'accessor': '2008-01-01T00:00:00'}, - {'Header': '2012-01-01', 'accessor': '2012-01-01T00:00:00'}, - {'Header': '2016-01-01', 'accessor': '2016-01-01T00:00:00'}, - {'Header': 'Totals', 'accessor': '$totals', 'className': 'fireant-totals'}], - 'data': [ - { - '$metrics': {'raw': 'Wins'}, - '$political_party': {'raw': 'Democrat'}, - '$totals': {'display': '', 'raw': None}, - '1996-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2000-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2004-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2008-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2012-01-01T00:00:00': {'display': '2', 'raw': 2.0}, - '2016-01-01T00:00:00': {'display': '0', 'raw': 0.0} - }, - { - '$metrics': {'raw': 'Wins'}, - '$political_party': {'raw': 'Independent'}, - '$totals': {'display': '', 'raw': None}, - '1996-01-01T00:00:00': {'display': '0', 'raw': 0.0}, - '2000-01-01T00:00:00': {'display': '', 'raw': None}, - '2004-01-01T00:00:00': {'display': '', 'raw': None}, - '2008-01-01T00:00:00': {'display': '', 'raw': None}, - '2012-01-01T00:00:00': {'display': '', 'raw': None}, - '2016-01-01T00:00:00': {'display': '', 'raw': None} - }] - }, result) + dimensions = [ + Rollup(day(mock_dataset.fields.timestamp)), + Rollup(mock_dataset.fields.political_party), + ] + result = ReactTable( + mock_dataset.fields.wins, + mock_dataset.fields.votes, + pivot=[mock_dataset.fields.political_party], + transpose=True, + ).transform(dimx2_date_str_totalsx2_df, mock_dataset, dimensions, []) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "1996-01-01", "accessor": "1996-01-01T00:00:00"}, + {"Header": "2000-01-01", "accessor": "2000-01-01T00:00:00"}, + {"Header": "2004-01-01", "accessor": "2004-01-01T00:00:00"}, + {"Header": "2008-01-01", "accessor": "2008-01-01T00:00:00"}, + {"Header": "2012-01-01", "accessor": "2012-01-01T00:00:00"}, + {"Header": "2016-01-01", "accessor": "2016-01-01T00:00:00"}, + { + "Header": "Totals", + "accessor": "$totals", + "className": "fireant-totals", + }, + ], + "data": [ + { + "$metrics": {"raw": "Wins"}, + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$totals": {"display": "", "raw": None}, + "1996-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2000-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2004-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2008-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2012-01-01T00:00:00": {"display": "2", "raw": 2.0}, + "2016-01-01T00:00:00": {"display": "0", "raw": 0.0}, + }, + { + "$metrics": {"raw": "Wins"}, + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$totals": {"display": "", "raw": None}, + "1996-01-01T00:00:00": {"display": "0", "raw": 0.0}, + "2000-01-01T00:00:00": {"display": "", "raw": None}, + "2004-01-01T00:00:00": {"display": "", "raw": None}, + "2008-01-01T00:00:00": {"display": "", "raw": None}, + "2012-01-01T00:00:00": {"display": "", "raw": None}, + "2016-01-01T00:00:00": {"display": "", "raw": None}, + }, + ], + }, + result, + ) class ReactTableHyperlinkTransformerTests(TestCase): @@ -1241,138 +1643,188 @@ class ReactTableHyperlinkTransformerTests(TestCase): @classmethod def setUpClass(cls): - cls.slicer = copy.deepcopy(mock_dataset) + cls.slicer = mock_dataset def test_add_hyperlink_with_formatted_values(self): - slicer = self.slicer - slicer.fields.political_party.hyperlink_template = 'http://example.com/{political_party}' - - result = ReactTable(slicer.fields.wins) \ - .transform(dimx1_str_df, slicer, [slicer.fields.political_party], []) - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [ - - { - '$political_party': { - 'hyperlink': 'http://example.com/Democrat', - 'raw': 'Democrat' - }, - '$wins': {'display': '6', 'raw': 6.0} - }, - { - '$political_party': { - 'hyperlink': 'http://example.com/Independent', - 'raw': 'Independent' - }, - '$wins': {'display': '0', 'raw': 0.0} - }, - { - '$political_party': { - 'hyperlink': 'http://example.com/Republican', - 'raw': 'Republican' - }, - '$wins': {'display': '6', 'raw': 6.0} - } - ] - }, result) + result = ReactTable(self.slicer.fields.wins).transform( + dimx1_str_df, self.slicer, [self.slicer.fields.political_party], [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "hyperlink": "http://example.com/Democrat", + "raw": "Democrat", + }, + "$wins": {"display": "6", "raw": 6.0}, + }, + { + "$political_party": { + "hyperlink": "http://example.com/Independent", + "raw": "Independent", + }, + "$wins": {"display": "0", "raw": 0.0}, + }, + { + "$political_party": { + "hyperlink": "http://example.com/Republican", + "raw": "Republican", + }, + "$wins": {"display": "6", "raw": 6.0}, + }, + ], + }, + result, + ) def test_do_not_add_hyperlink_to_pivoted_dimensions(self): - slicer = self.slicer - slicer.fields.political_party.hyperlink_template = 'http://example.com/{political_party}' - - dimensions = [slicer.fields.political_party] - result = ReactTable(slicer.fields.wins, pivot=dimensions) \ - .transform(dimx1_str_df, slicer, dimensions, []) - - self.assertEqual({ - 'columns': [{'Header': '', 'accessor': '$metrics'}, - {'Header': 'Democrat', 'accessor': 'Democrat'}, - {'Header': 'Independent', 'accessor': 'Independent'}, - {'Header': 'Republican', 'accessor': 'Republican'}], - 'data': [{ - '$metrics': {'raw': 'Wins'}, - 'Democrat': {'display': '6', 'raw': 6}, - 'Independent': {'display': '0', 'raw': 0}, - 'Republican': {'display': '6', 'raw': 6} - }] - }, result) - - def test_dim_with_hyperlink_depending_on_another_dim_not_included_if_other_dim_is_not_selected(self): - slicer = self.slicer - slicer.fields.political_party.hyperlink_template = 'http://example.com/{candidate}' - - result = ReactTable(slicer.fields.wins) \ - .transform(dimx1_str_df, slicer, [slicer.fields.political_party], []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [{ - '$political_party': {'raw': 'Democrat'}, - '$wins': {'display': '6', 'raw': 6} - }, { - '$political_party': {'raw': 'Independent'}, - '$wins': {'display': '0', 'raw': 0} - }] - }, result) - - def test_dim_with_hyperlink_depending_on_another_dim_included_if_other_dim_is_selected(self): - slicer = self.slicer - slicer.fields.political_party.hyperlink_template = 'http://example.com/candidates/{candidate-id}/' - - result = ReactTable(slicer.fields.wins) \ - .transform(dimx2_str_num_df, slicer, [slicer.fields.political_party, slicer.fields['candidate-id']], []) - - self.assertIn('data', result) - result['data'] = result['data'][:2] # shorten the results to make the test easier to read - - self.assertEqual({ - 'columns': [{'Header': 'Party', 'accessor': '$political_party'}, - {'Header': 'Candidate ID', 'accessor': '$candidate-id'}, - {'Header': 'Wins', 'accessor': '$wins'}], - 'data': [{ - '$candidate-id': {'display': '1', 'raw': 1.0}, - '$political_party': { - 'raw': 'Democrat', - 'hyperlink': 'http://example.com/candidates/1/', - }, - '$wins': {'display': '2', 'raw': 2} - }, { - '$candidate-id': {'display': '5', 'raw': 5.0}, - '$political_party': { - 'raw': 'Democrat', - 'hyperlink': 'http://example.com/candidates/5/', - }, - '$wins': {'display': '0', 'raw': 0} - }] - }, result) + dimensions = [self.slicer.fields.political_party] + result = ReactTable(self.slicer.fields.wins, pivot=dimensions).transform( + dimx1_str_df, self.slicer, dimensions, [] + ) + + self.assertEqual( + { + "columns": [ + {"Header": "", "accessor": "$metrics"}, + {"Header": "Democrat", "accessor": "Democrat"}, + {"Header": "Independent", "accessor": "Independent"}, + {"Header": "Republican", "accessor": "Republican"}, + ], + "data": [ + { + "$metrics": {"raw": "Wins"}, + "Democrat": {"display": "6", "raw": 6}, + "Independent": {"display": "0", "raw": 0}, + "Republican": {"display": "6", "raw": 6}, + } + ], + }, + result, + ) + + def test_dim_with_hyperlink_depending_on_another_dim_not_included_if_other_dim_is_not_selected( + self, + ): + result = ReactTable(self.slicer.fields.wins).transform( + dimx1_str_df, self.slicer, [self.slicer.fields.political_party], [] + ) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": {"display": "6", "raw": 6}, + }, + { + "$political_party": { + "raw": "Independent", + "hyperlink": "http://example.com/Independent", + }, + "$wins": {"display": "0", "raw": 0}, + }, + ], + }, + result, + ) + + def test_dim_with_hyperlink_depending_on_another_dim_included_if_other_dim_is_selected( + self, + ): + result = ReactTable(self.slicer.fields.wins).transform( + dimx2_str_str_df, + self.slicer, + [self.slicer.fields.political_party, self.slicer.fields["candidate-name"]], + [], + ) + + self.assertIn("data", result) + result["data"] = result["data"][ + :2 + ] # shorten the results to make the test easier to read + + self.assertEqual( + { + "columns": [ + {"Header": "Party", "accessor": "$political_party"}, + {"Header": "Candidate Name", "accessor": "$candidate-name"}, + {"Header": "Wins", "accessor": "$wins"}, + ], + "data": [ + { + "$candidate-name": { + "hyperlink": "http://example.com/Democrat/Al Gore", + "raw": "Al Gore", + }, + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": {"display": "0", "raw": 0}, + }, + { + "$candidate-name": { + "hyperlink": "http://example.com/Democrat/Barrack Obama", + "raw": "Barrack Obama", + }, + "$political_party": { + "raw": "Democrat", + "hyperlink": "http://example.com/Democrat", + }, + "$wins": {"display": "4", "raw": 4}, + }, + ], + }, + result, + ) class ReactTableReferenceItemFormatTests(TestCase): @classmethod def setUpClass(cls): - cls.ref_item_attrs = ['alias', 'label', 'prefix', 'suffix', 'thousands', 'precision', 'data_type'] + cls.ref_item_attrs = [ + "alias", + "label", + "prefix", + "suffix", + "thousands", + "precision", + "data_type", + ] def assert_object_dict(self, obj, exp, attributes=()): for attribute in attributes: - with self.subTest(attribute + ' should be equal'): + with self.subTest(attribute + " should be equal"): self.assertEqual(getattr(obj, attribute), exp[attribute]) def test_base_ref_item(self): exp_ref_item = { - 'alias': 'wins_with_style_eoe', - 'label': 'Wins EoE', - 'prefix': '$', - 'suffix': '€', - 'thousands': '_', - 'precision': None, - 'data_type': DataType.number, + "alias": "wins_with_style_eoe", + "label": "Wins EoE", + "prefix": "$", + "suffix": None, + "thousands": "_", + "precision": 0, + "data_type": DataType.number, } ref = ElectionOverElection(mock_dataset.fields.timestamp) @@ -1382,16 +1834,18 @@ def test_base_ref_item(self): def test_ref_item_with_delta_percentage_formats_prefix_suffix(self): exp_ref_item = { - 'alias': 'wins_with_style_eoe_delta_percent', - 'label': 'Wins EoE Δ%', - 'prefix': None, - 'suffix': '%', - 'thousands': '_', - 'precision': None, - 'data_type': DataType.number, + "alias": "wins_with_style_eoe_delta_percent", + "label": "Wins EoE Δ%", + "prefix": None, + "suffix": "%", + "thousands": "_", + "precision": 0, + "data_type": DataType.number, } - ref = ElectionOverElection(mock_dataset.fields.timestamp, delta=True, delta_percent=True) + ref = ElectionOverElection( + mock_dataset.fields.timestamp, delta=True, delta_percent=True + ) ref_item = ReferenceItem(mock_dataset.fields.wins_with_style, ref) self.assert_object_dict(ref_item, exp_ref_item, self.ref_item_attrs) diff --git a/fireant/utils.py b/fireant/utils.py index 33303104..33f7887d 100644 --- a/fireant/utils.py +++ b/fireant/utils.py @@ -1,11 +1,37 @@ -import inspect import csv +import inspect import tempfile - from collections import OrderedDict from functools import partial +def immutable(func): + """ + Decorator for wrapper "builder" functions. These are functions on the Query class or other classes used for + building queries which mutate the query and return self. To make the build functions immutable, this decorator is + used which will deepcopy the current instance. This decorator will return the return value of the inner function + or the new copy of the instance. The inner function does not need to return self. + """ + import copy + + def _copy(self, *args, mutate=False, **kwargs): + """ + :param mutate: + When True, overrides the immutable behavior of this decorator. + """ + self_copy = self if mutate else copy.deepcopy(self) + result = func(self_copy, *args, **kwargs) + + # Return self if the inner function returns None. This way the inner function can return something + # different (for example when creating joins, a different builder is returned). + if result is None: + return self_copy + + return result + + return _copy + + def wrap_list(value, wrapper=list): return value if isinstance(value, (tuple, list)) else wrapper([value]) @@ -148,33 +174,6 @@ def chunks(l, n): return [l[i : i + n] for i in range(0, len(l), n)] -def immutable(func): - """ - Decorator for wrapper "builder" functions. These are functions on the Query class or other classes used for - building queries which mutate the query and return self. To make the build functions immutable, this decorator is - used which will deepcopy the current instance. This decorator will return the return value of the inner function - or the new copy of the instance. The inner function does not need to return self. - """ - import copy - - def _copy(self, *args, mutate=False, **kwargs): - """ - :param mutate: - When True, overrides the immutable behavior of this decorator. - """ - self_copy = self if mutate else copy.deepcopy(self) - result = func(self_copy, *args, **kwargs) - - # Return self if the inner function returns None. This way the inner function can return something - # different (for example when creating joins, a different builder is returned). - if result is None: - return self_copy - - return result - - return _copy - - def ordered_distinct_list(l): seen = set() return [x for x in l if not x in seen and not seen.add(x)] diff --git a/fireant/widgets/base.py b/fireant/widgets/base.py index fc00f97a..ab1deb51 100644 --- a/fireant/widgets/base.py +++ b/fireant/widgets/base.py @@ -36,6 +36,21 @@ def metrics(self): for metric in getattr(group, "metrics", [group]) ] + def __deepcopy__(self, memo): + from copy import deepcopy + + cls = self.__class__ + result = cls.__new__(cls) + + memo[id(self)] = result + for item in self.items: + memo[id(item)] = item + + for k, v in self.__dict__.items(): + setattr(result, k, deepcopy(v, memo)) + + return result + @property def operations(self): return [item for item in self.items if isinstance(item, Operation)] diff --git a/fireant/widgets/chart_base.py b/fireant/widgets/chart_base.py index d0dcc9da..26df0dd9 100644 --- a/fireant/widgets/chart_base.py +++ b/fireant/widgets/chart_base.py @@ -3,14 +3,14 @@ Union, ) +from fireant import utils from fireant.dataset.fields import Field from fireant.dataset.operations import Operation -from fireant import utils - from .base import ( MetricRequiredException, Widget, ) +from ..utils import immutable class Series: @@ -23,8 +23,7 @@ def __init__(self, metric: Union[Field, Operation], stacking=None): self.stacking = self.stacking or stacking def __repr__(self): - return "{}({})".format(self.__class__.__name__, - repr(self.metric)) + return "{}({})".format(self.__class__.__name__, repr(self.metric)) class ContinuousAxisSeries(Series): @@ -49,10 +48,10 @@ def __repr__(self): class ChartWidget(Widget): class LineSeries(ContinuousAxisSeries): - type = 'line' + type = "line" class AreaSeries(ContinuousAxisSeries): - type = 'area' + type = "area" class AreaStackedSeries(AreaSeries): stacking = "normal" @@ -61,21 +60,21 @@ class AreaPercentageSeries(AreaSeries): stacking = "percent" class PieSeries(Series): - type = 'pie' + type = "pie" class BarSeries(Series): - type = 'bar' + type = "bar" class StackedBarSeries(BarSeries): stacking = "normal" class ColumnSeries(Series): - type = 'column' + type = "column" class StackedColumnSeries(ColumnSeries): stacking = "normal" - @utils.immutable + @immutable def axis(self, *series: Series, **kwargs): """ (Immutable) Adds an axis to the Chart. @@ -96,16 +95,22 @@ def metrics(self): raise MetricRequiredException(str(self)) seen = set() - return [metric - for axis in self.items - for series in axis - for metric in getattr(series.metric, 'metrics', [series.metric]) - if not (metric.alias in seen or seen.add(metric.alias))] + return [ + metric + for axis in self.items + for series in axis + for metric in getattr(series.metric, "metrics", [series.metric]) + if not (metric.alias in seen or seen.add(metric.alias)) + ] @property def operations(self): - return utils.ordered_distinct_list_by_attr([operation - for axis in self.items - for series in axis - if isinstance(series.metric, Operation) - for operation in [series.metric] + series.metric.operations]) + return utils.ordered_distinct_list_by_attr( + [ + operation + for axis in self.items + for series in axis + if isinstance(series.metric, Operation) + for operation in [series.metric] + series.metric.operations + ] + ) From f595cc38b791d13bce89c6f59f2601ab0cedf4cb Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Tue, 7 Jan 2020 11:26:53 +0100 Subject: [PATCH 2/6] Fixed the data blending query to work with two blended datasets that have overlapping field aliases --- fireant/dataset/data_blending.py | 2 +- fireant/dataset/klass.py | 3 -- fireant/dataset/modifiers.py | 2 +- .../builder/dataset_blender_query_builder.py | 30 +++++++++++-------- fireant/queries/builder/query_builder.py | 14 ++++----- fireant/queries/finders.py | 4 --- 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/fireant/dataset/data_blending.py b/fireant/dataset/data_blending.py index cb91b4b9..99891a9a 100644 --- a/fireant/dataset/data_blending.py +++ b/fireant/dataset/data_blending.py @@ -1,7 +1,7 @@ from fireant.dataset.fields import Field from fireant.dataset.klass import DataSet -from fireant.utils import immutable from fireant.queries.builder import DataSetBlenderQueryBuilder +from fireant.utils import immutable class DataSetBlender: diff --git a/fireant/dataset/klass.py b/fireant/dataset/klass.py index 89e4e825..78fb21e8 100644 --- a/fireant/dataset/klass.py +++ b/fireant/dataset/klass.py @@ -29,9 +29,6 @@ def __init__(self, items=()): for item in items: setattr(self, item.alias, item) - def __copy__(self): - return type(self)(self._items) - def __deepcopy__(self, memodict): for field in self: memodict[id(field)] = field diff --git a/fireant/dataset/modifiers.py b/fireant/dataset/modifiers.py index 4156d436..92d7a93d 100644 --- a/fireant/dataset/modifiers.py +++ b/fireant/dataset/modifiers.py @@ -57,7 +57,7 @@ def __repr__(self): @immutable def for_(self, wrapped): - wrapped_key = super(type(self), self).__getattribute__("wrapped_key") + wrapped_key = super().__getattribute__("wrapped_key") setattr(self, wrapped_key, wrapped) diff --git a/fireant/queries/builder/dataset_blender_query_builder.py b/fireant/queries/builder/dataset_blender_query_builder.py index 96e7181d..8cfd31ef 100644 --- a/fireant/queries/builder/dataset_blender_query_builder.py +++ b/fireant/queries/builder/dataset_blender_query_builder.py @@ -5,13 +5,13 @@ List, ) -from fireant.exceptions import DataSetException from fireant.dataset.fields import Field +from fireant.exceptions import DataSetException from fireant.queries.builder.dataset_query_builder import DataSetQueryBuilder from fireant.queries.finders import ( find_dataset_metrics, - find_metrics_for_widgets, find_field_in_modified_field, + find_metrics_for_widgets, ) from fireant.reference_helpers import reference_alias from fireant.utils import alias_selector @@ -38,14 +38,20 @@ def _flatten_blend_datasets(dataset) -> List: return zip(*_flatten_blend_datasets(blender)) -def _replace_field(dimension, field_map, omit_umapped=False): +def _replace_field(dimension, field_map=None, dataset=None, omit_umapped=False): root_dimension = find_field_in_modified_field(dimension) if root_dimension is not dimension: # Handle modified dimensions - wrapped_dimension = _replace_field(root_dimension, field_map) + wrapped_dimension = _replace_field(root_dimension, field_map, dataset) return dimension.for_(wrapped_dimension) - if field_map is None: + if field_map is not None and dimension in field_map: + return field_map.get(dimension, None) + + if dataset is not None and dimension.alias in dataset.fields: + return dataset.fields[dimension.alias] + + if dimension.definition is not None: return dimension.definition if not omit_umapped and dimension not in field_map: @@ -75,12 +81,12 @@ def _build_dataset_query(dataset, field_map, metrics, dimensions, filters, refer return None blended_dimensions = [ - _replace_field(dimension, field_map) for dimension in dimensions + _replace_field(dimension, field_map, dataset) for dimension in dimensions ] blended_filters = [] for fltr in filters: - filter_field = _replace_field(fltr.field, field_map, omit_umapped=True) + filter_field = _replace_field(fltr.field, field_map, dataset, omit_umapped=True) if filter_field not in dataset.fields: continue @@ -89,7 +95,7 @@ def _build_dataset_query(dataset, field_map, metrics, dimensions, filters, refer blended_references = [] for reference in references: - reference_field = _replace_field(reference.field, field_map) + reference_field = _replace_field(reference.field, field_map, dataset) if reference_field not in dataset.fields: continue @@ -98,10 +104,10 @@ def _build_dataset_query(dataset, field_map, metrics, dimensions, filters, refer return ( dataset.query() - .widget(EmptyWidget(*dataset_metrics)) - .dimension(*blended_dimensions) - .filter(*blended_filters) - .reference(*blended_references) + .widget(EmptyWidget(*dataset_metrics), mutate=True) + .dimension(*blended_dimensions, mutate=True) + .filter(*blended_filters, mutate=True) + .reference(*blended_references, mutate=True) ) diff --git a/fireant/queries/builder/query_builder.py b/fireant/queries/builder/query_builder.py index 58c48c05..8eff0e6d 100644 --- a/fireant/queries/builder/query_builder.py +++ b/fireant/queries/builder/query_builder.py @@ -3,7 +3,7 @@ from fireant.utils import immutable from pypika import Order from ..execution import fetch_data -from ..finders import find_fields_in_modified_fields +from ..finders import find_field_in_modified_field class QueryException(DataSetException): @@ -29,16 +29,16 @@ def get_column_names(database, table): def _strip_modifiers(fields): for field in fields: - next = field - while hasattr(next, "dimension"): - next = next.dimension - yield next + node = field + while hasattr(node, "dimension"): + node = node.dimension + yield node def _validate_fields(fields, dataset): - fields = find_fields_in_modified_fields(fields) - invalid = [field.alias for field in fields if field not in dataset.fields] + fields = [find_field_in_modified_field(field) for field in fields] + invalid = [field.alias for field in fields if field not in dataset.fields] if not invalid: return diff --git a/fireant/queries/finders.py b/fireant/queries/finders.py index 58ac7fc4..fbbe9305 100644 --- a/fireant/queries/finders.py +++ b/fireant/queries/finders.py @@ -195,10 +195,6 @@ def find_field_in_modified_field(field): return root -def find_fields_in_modified_fields(fields): - return [find_field_in_modified_field(field) for field in fields] - - interval_weekdays = { "month": ("week", 4), "quarter": ("week", 4 * 3), From 1a0f71c401d50695cda435c13a89ed34d724c83d Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Tue, 7 Jan 2020 11:32:16 +0100 Subject: [PATCH 3/6] Removed the copy and deepcopy methods from fields --- fireant/dataset/fields.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/fireant/dataset/fields.py b/fireant/dataset/fields.py index 81e5a86b..178ecd95 100644 --- a/fireant/dataset/fields.py +++ b/fireant/dataset/fields.py @@ -115,22 +115,6 @@ def __init__( self.precision = precision self.hyperlink_template = hyperlink_template - def __copy__(self): - cls = self.__class__ - result = cls.__new__(cls) - result.__dict__.update(self.__dict__) - return result - - def __deepcopy__(self, memo): - cls = self.__class__ - result = cls.__new__(cls) - memo[id(self)] = result - from copy import deepcopy - - for k, v in self.__dict__.items(): - setattr(result, k, deepcopy(v, memo)) - return result - @property def is_aggregate(self): return self.definition.is_aggregate From a3eba5906f5d4c912d1da3367f246a828149eef9 Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Tue, 7 Jan 2020 11:39:00 +0100 Subject: [PATCH 4/6] Replaced the __copy__ and __deepcopy__ methods in Modifier with a check in __getattr__ for these attributes that raises an AttributeError --- fireant/dataset/modifiers.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/fireant/dataset/modifiers.py b/fireant/dataset/modifiers.py index 92d7a93d..9f8ce21a 100644 --- a/fireant/dataset/modifiers.py +++ b/fireant/dataset/modifiers.py @@ -11,21 +11,10 @@ def __init__(self, wrapped): wrapped_key = super().__getattribute__("wrapped_key") setattr(self, wrapped_key, wrapped) - def __copy__(self): - cls = self.__class__ - result = cls.__new__(cls) - result.__dict__.update(self.__dict__) - return result - - def __deepcopy__(self, memo): - cls = self.__class__ - result = cls.__new__(cls) - memo[id(self)] = result - for k, v in self.__dict__.items(): - setattr(result, k, deepcopy(v, memo)) - return result - def __getattr__(self, attr): + if attr in ("__copy__", "__deepcopy__"): + raise AttributeError() + if attr in self.__dict__: return super().__getattribute__(attr) From dbcbe8048908cf34e3fb76b7404b94e4b7d6be0b Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Tue, 7 Jan 2020 13:30:47 +0100 Subject: [PATCH 5/6] ok really fixed for py35 this time --- fireant/dataset/filters.py | 11 ++------ fireant/dataset/klass.py | 6 ++--- fireant/dataset/modifiers.py | 26 ++++++++++++++++--- fireant/dataset/references.py | 7 ++--- fireant/queries/finders.py | 11 ++++---- .../{reference_helper.py => references.py} | 18 ++----------- fireant/queries/sql_transformer.py | 2 +- fireant/utils.py | 16 +++++++++++- fireant/widgets/base.py | 21 +++++---------- 9 files changed, 63 insertions(+), 55 deletions(-) rename fireant/queries/{reference_helper.py => references.py} (82%) diff --git a/fireant/dataset/filters.py b/fireant/dataset/filters.py index 042a242e..ef777a0c 100644 --- a/fireant/dataset/filters.py +++ b/fireant/dataset/filters.py @@ -1,15 +1,13 @@ -from fireant.utils import immutable from pypika import ( EmptyCriterion, Not, ) from pypika.functions import Lower +from .modifiers import FieldModifier -class Filter(object): - def __init__(self, field): - self.field = field +class Filter(FieldModifier): @property def definition(self): raise NotImplementedError() @@ -29,11 +27,6 @@ def __eq__(self, other): def __repr__(self): return str(self.definition) - @immutable - def for_(self, field): - self.field = field - # self.definition = self._make_definition(field) - class ComparatorFilter(Filter): class Operator(object): diff --git a/fireant/dataset/klass.py b/fireant/dataset/klass.py index 78fb21e8..9ee64eaf 100644 --- a/fireant/dataset/klass.py +++ b/fireant/dataset/klass.py @@ -1,6 +1,6 @@ import itertools -from fireant.utils import immutable +from fireant.utils import immutable, deepcopy from fireant.queries.builder import ( DataSetQueryBuilder, DimensionChoicesQueryBuilder, @@ -29,10 +29,10 @@ def __init__(self, items=()): for item in items: setattr(self, item.alias, item) - def __deepcopy__(self, memodict): + def __deepcopy__(self, memodict={}): for field in self: memodict[id(field)] = field - return type(self)(self._items) + return deepcopy(self, memodict) def __iter__(self): return iter(self._items) diff --git a/fireant/dataset/modifiers.py b/fireant/dataset/modifiers.py index 9f8ce21a..a361ca65 100644 --- a/fireant/dataset/modifiers.py +++ b/fireant/dataset/modifiers.py @@ -1,6 +1,7 @@ -from copy import deepcopy - -from fireant.utils import immutable +from fireant.utils import ( + deepcopy, + immutable, +) from pypika import NullValue @@ -44,12 +45,31 @@ def __repr__(self): wrapped = super().__getattribute__(wrapped_key) return "{}({})".format(self.__class__.__name__, repr(wrapped)) + def __deepcopy__(self, memodict={}): + wrapped_key = super().__getattribute__("wrapped_key") + wrapped = super().__getattribute__(wrapped_key) + memodict[id(wrapped)] = wrapped + return deepcopy(self, memodict) + @immutable def for_(self, wrapped): wrapped_key = super().__getattribute__("wrapped_key") setattr(self, wrapped_key, wrapped) +class FieldModifier: + def __init__(self, field): + self.field = field + + @immutable + def for_(self, field): + self.field = field + + def __deepcopy__(self, memodict={}): + memodict[id(self.field)] = self.field + return deepcopy(self, memodict) + + class DimensionModifier(Modifier): wrapped_key = "dimension" diff --git a/fireant/dataset/references.py b/fireant/dataset/references.py index 270fef73..85a27ad0 100644 --- a/fireant/dataset/references.py +++ b/fireant/dataset/references.py @@ -1,14 +1,15 @@ import numpy as np - from fireant import utils from fireant.utils import immutable from pypika import functions as fn from pypika.queries import QueryBuilder +from .modifiers import FieldModifier + -class Reference(object): +class Reference(FieldModifier): def __init__(self, field, reference_type, delta=False, delta_percent=False): - self.field = field + super().__init__(field) self.reference_type = reference_type self.alias = ( diff --git a/fireant/queries/finders.py b/fireant/queries/finders.py index fbbe9305..31df5d17 100644 --- a/fireant/queries/finders.py +++ b/fireant/queries/finders.py @@ -189,10 +189,10 @@ def find_field_in_modified_field(field): """ Returns the field from a modified field argument (or just the field argument if it is not modified). """ - root = field - while hasattr(root, "dimension"): - root = root.dimension - return root + modified_field = field + while hasattr(modified_field, "dimension"): + modified_field = modified_field.dimension + return modified_field interval_weekdays = { @@ -238,7 +238,8 @@ def get_dimension_time_unit_and_interval(reference): else defaults ) - return reference.field, time_unit, interval_muliplier * reference.interval + field = find_field_in_modified_field(reference.field) + return field, time_unit, interval_muliplier * reference.interval distinct_references = ordered_distinct_list(references) return groupby(distinct_references, get_dimension_time_unit_and_interval) diff --git a/fireant/queries/reference_helper.py b/fireant/queries/references.py similarity index 82% rename from fireant/queries/reference_helper.py rename to fireant/queries/references.py index 4d62f6c1..d9d95a88 100644 --- a/fireant/queries/reference_helper.py +++ b/fireant/queries/references.py @@ -1,7 +1,7 @@ -import copy from functools import partial from fireant.dataset.fields import Field + from .field_helper import make_term_for_dimension from .finders import find_field_in_modified_field @@ -13,9 +13,6 @@ def adapt_for_reference_query( return dimensions, metrics, filters ref_dimension, time_unit, interval = reference_parts - # Unpack rolled up dimensions - ref_dimension = find_field_in_modified_field(ref_dimension) - ref_metrics = _make_reference_metrics(metrics, references[0].reference_type.alias) offset_func = partial(database.date_add, date_part=time_unit, interval=interval) ref_dimensions = _make_reference_dimensions( @@ -50,15 +47,6 @@ def _make_reference_dimensions(dimensions, ref_dimension, offset_func, trunc_dat def _make_reference_metrics(metrics, ref_key): - metric_copies = [] - - for metric in [copy.deepcopy(metric) for metric in metrics]: - for pypika_field in metric.definition.fields_(): - if pypika_field.name.startswith("$"): - pypika_field.name = "{}_{}".format(pypika_field.name, ref_key) - - metric_copies.append(metric) - return [ Field( "{}_{}".format(metric.alias, ref_key), @@ -69,7 +57,7 @@ def _make_reference_metrics(metrics, ref_key): suffix=metric.suffix, precision=metric.precision, ) - for metric in metric_copies + for metric in metrics ] @@ -84,8 +72,6 @@ def _make_reference_filters(filters, ref_dimension, offset_func): :param offset_func: :return: """ - offset_ref_dimension_definition = offset_func(ref_dimension.definition) - reference_filters = [] for ref_filter in filters: if ref_filter.field is ref_dimension: diff --git a/fireant/queries/sql_transformer.py b/fireant/queries/sql_transformer.py index 96e9d725..a20f82e2 100644 --- a/fireant/queries/sql_transformer.py +++ b/fireant/queries/sql_transformer.py @@ -24,7 +24,7 @@ find_required_tables_to_join, find_totals_dimensions, ) -from .reference_helper import adapt_for_reference_query +from .references import adapt_for_reference_query from .special_cases import apply_special_cases from .totals_helper import adapt_for_totals_query diff --git a/fireant/utils.py b/fireant/utils.py index 33f7887d..763f6abf 100644 --- a/fireant/utils.py +++ b/fireant/utils.py @@ -1,3 +1,4 @@ +import copy import csv import inspect import tempfile @@ -12,7 +13,6 @@ def immutable(func): used which will deepcopy the current instance. This decorator will return the return value of the inner function or the new copy of the instance. The inner function does not need to return self. """ - import copy def _copy(self, *args, mutate=False, **kwargs): """ @@ -32,6 +32,20 @@ def _copy(self, *args, mutate=False, **kwargs): return _copy +def deepcopy(value, memodict): + cls = value.__class__ + result = cls.__new__(cls) + + memodict[id(value)] = result + + for k, v in value.__dict__.items(): + result.__dict__[k] = ( + memodict[id(v)] if id(v) in memodict else copy.deepcopy(v, memodict) + ) + + return result + + def wrap_list(value, wrapper=list): return value if isinstance(value, (tuple, list)) else wrapper([value]) diff --git a/fireant/widgets/base.py b/fireant/widgets/base.py index ab1deb51..c9ab9d44 100644 --- a/fireant/widgets/base.py +++ b/fireant/widgets/base.py @@ -10,7 +10,10 @@ reference_prefix, reference_suffix, ) -from fireant.utils import immutable +from fireant.utils import ( + deepcopy, + immutable, +) class MetricRequiredException(DataSetException): @@ -36,20 +39,10 @@ def metrics(self): for metric in getattr(group, "metrics", [group]) ] - def __deepcopy__(self, memo): - from copy import deepcopy - - cls = self.__class__ - result = cls.__new__(cls) - - memo[id(self)] = result + def __deepcopy__(self, memodict={}): for item in self.items: - memo[id(item)] = item - - for k, v in self.__dict__.items(): - setattr(result, k, deepcopy(v, memo)) - - return result + memodict[id(item)] = item + return deepcopy(self, memodict) @property def operations(self): From e9b63e4769164dc72c6f5ab26538cb9655b1d929 Mon Sep 17 00:00:00 2001 From: Timothy Heys Date: Tue, 7 Jan 2020 13:39:09 +0100 Subject: [PATCH 6/6] Added memo to deepcopy in DataSetBlender --- fireant/dataset/data_blending.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fireant/dataset/data_blending.py b/fireant/dataset/data_blending.py index 99891a9a..49f1890e 100644 --- a/fireant/dataset/data_blending.py +++ b/fireant/dataset/data_blending.py @@ -1,7 +1,10 @@ from fireant.dataset.fields import Field from fireant.dataset.klass import DataSet from fireant.queries.builder import DataSetBlenderQueryBuilder -from fireant.utils import immutable +from fireant.utils import ( + immutable, + deepcopy, +) class DataSetBlender: @@ -67,6 +70,11 @@ def __repr__(self): def __hash__(self): return hash((self.primary_dataset, self.secondary_dataset, self.fields)) + def __deepcopy__(self, memodict={}): + for field in self.field_map.values(): + memodict[id(field)] = field + return deepcopy(self, memodict) + @property def table(self): return None