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 diff --git a/fireant/dataset/fields.py b/fireant/dataset/fields.py index 7210c80b..178ecd95 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): @@ -177,7 +177,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 +285,4 @@ def get_sql(self, **kwargs): @immutable def share(self): self._share = True + return self 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 9fbee890..9ee64eaf 100644 --- a/fireant/dataset/klass.py +++ b/fireant/dataset/klass.py @@ -1,11 +1,11 @@ import itertools +from fireant.utils import immutable, deepcopy from fireant.queries.builder import ( DataSetQueryBuilder, DimensionChoicesQueryBuilder, DimensionLatestQueryBuilder, ) -from fireant.utils import immutable class _Container(object): @@ -29,6 +29,11 @@ def __init__(self, items=()): for item in items: setattr(self, item.alias, item) + def __deepcopy__(self, memodict={}): + for field in self: + memodict[id(field)] = field + return deepcopy(self, memodict) + def __iter__(self): return iter(self._items) @@ -45,10 +50,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 +73,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..a361ca65 100644 --- a/fireant/dataset/modifiers.py +++ b/fireant/dataset/modifiers.py @@ -1,4 +1,7 @@ -from fireant.utils import immutable +from fireant.utils import ( + deepcopy, + immutable, +) from pypika import NullValue @@ -10,6 +13,9 @@ def __init__(self, wrapped): setattr(self, wrapped_key, wrapped) def __getattr__(self, attr): + if attr in ("__copy__", "__deepcopy__"): + raise AttributeError() + if attr in self.__dict__: return super().__getattribute__(attr) @@ -39,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 607c1605..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 = ( @@ -36,7 +37,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..8cfd31ef 100644 --- a/fireant/queries/builder/dataset_blender_query_builder.py +++ b/fireant/queries/builder/dataset_blender_query_builder.py @@ -5,11 +5,12 @@ 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_field_in_modified_field, find_metrics_for_widgets, ) from fireant.reference_helpers import reference_alias @@ -37,13 +38,20 @@ def _flatten_blend_datasets(dataset) -> List: return zip(*_flatten_blend_datasets(blender)) -def _replace_field(dimension, field_map, omit_umapped=False): - if hasattr(dimension, "dimension"): +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(dimension.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: @@ -73,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 @@ -87,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 @@ -96,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/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..8eff0e6d 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_field_in_modified_field 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: + node = field + while hasattr(node, "dimension"): + node = node.dimension + yield node + + +def _validate_fields(fields, dataset): + 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 + + 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..31df5d17 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,14 @@ 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} - - 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 + modified_field = field + while hasattr(modified_field, "dimension"): + modified_field = modified_field.dimension + return modified_field interval_weekdays = { @@ -249,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/reference_helper.py deleted file mode 100644 index 703f6056..00000000 --- a/fireant/queries/reference_helper.py +++ /dev/null @@ -1,95 +0,0 @@ -import copy -from functools import partial - -from fireant.dataset.fields import Field -from fireant.dataset.modifiers import Rollup -from .field_helper import make_term_for_dimension - - -def adapt_for_reference_query( - dataset, 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_metrics = _make_reference_metrics( - dataset, 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 - ) - 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) - - ref_definition = make_term_for_dimension( - ref_dimension_copy, database.trunc_date - ) - ref_dimension_copy.definition = offset_func(ref_definition) - return ref_dimension_copy - - return [ - replace_reference_dimension(dimension) - if dimension is ref_dimension - else dimension - for dimension in dimensions - ] - - -def _make_reference_metrics(dataset, 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), - metric.definition, - label=metric.label, - prefix=metric.prefix, - suffix=metric.suffix, - precision=metric.precision, - ) - for metric in metric_copies - ] - - -def _make_reference_filters(filters, ref_dimension, offset_func): - """ - Copies and replaces the reference dimension's definition in all of the filters applied to a dataset query. - - This is used to shift the dimension filters to fit the reference window. - - :param filters: - :param ref_dimension: - :param offset_func: - :return: - """ - offset_ref_dimension_definition = offset_func(ref_dimension.definition) - - 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 - reference_filters.append(ref_filter) - - return reference_filters diff --git a/fireant/queries/references.py b/fireant/queries/references.py new file mode 100644 index 00000000..d9d95a88 --- /dev/null +++ b/fireant/queries/references.py @@ -0,0 +1,83 @@ +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 + + +def adapt_for_reference_query( + reference_parts, database, dimensions, metrics, filters, references +): + if reference_parts is None: + return dimensions, metrics, filters + + ref_dimension, time_unit, interval = reference_parts + 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( + 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 _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, + ) + + 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, offset_func, trunc_date) + if ref_dimension is find_field_in_modified_field(dimension) + else dimension + for dimension in dimensions + ] + + +def _make_reference_metrics(metrics, ref_key): + return [ + Field( + "{}_{}".format(metric.alias, ref_key), + metric.definition, + data_type=metric.data_type, + label=metric.label, + prefix=metric.prefix, + suffix=metric.suffix, + precision=metric.precision, + ) + for metric in metrics + ] + + +def _make_reference_filters(filters, ref_dimension, offset_func): + """ + Copies and replaces the reference dimension's definition in all of the filters applied to a dataset query. + + This is used to shift the dimension filters to fit the reference window. + + :param filters: + :param ref_dimension: + :param offset_func: + :return: + """ + reference_filters = [] + for ref_filter in filters: + 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..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 @@ -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..763f6abf 100644 --- a/fireant/utils.py +++ b/fireant/utils.py @@ -1,11 +1,51 @@ -import inspect +import copy 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. + """ + + 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 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]) @@ -148,33 +188,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..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,6 +39,11 @@ def metrics(self): for metric in getattr(group, "metrics", [group]) ] + def __deepcopy__(self, memodict={}): + for item in self.items: + memodict[id(item)] = item + return deepcopy(self, memodict) + @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 + ] + )