def apply_filters(self, attributes=None, metrics=None, attr_elements=None): """Apply filters on the report's objects, so only selected attributes, metrics and attributes' elements will be retrieved from Intelligence Server. Args: attributes (list or None, optional): ids of attributes to be included in the filter. If list is empty, no attributes will be selected and metric data will be aggregated. metrics (list or None, optional): ids of metrics to be included in the filter. If list is empty, no metrics will be selected. attr_elements (list or None, optional): attributes' elements to be included in the filter. """ if self.cross_tab: self.cross_tab_filter = {'attributes': attributes, 'metrics': metrics, 'attr_elements': attr_elements} elif not all(element is None for element in [attributes, metrics, attr_elements]): if attr_elements: # If parameter attr_elements is applied then fetch all attribute elements self.attr_elements if self._attr_elements and not self._filter.attr_elems: self._filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) if attributes: self._filter.select(object_id=attributes) if attributes == []: self._filter.attr_selected = [] if metrics: self._filter.select(object_id=metrics) if metrics == []: self._filter.metr_selected = [] if attr_elements is not None: self._filter.select(object_id=attr_elements)
def __init__(self, connection, cube_id, parallel=True, progress_bar=True): """Initialize an instance of a cube. Args: connection: MicroStrategy connection object returned by `microstrategy.Connection()`. cube_id (str): Identifier of a pre-existing cube containing the required data. parallel (bool, optional): If True (default), utilize optimal number of threads to increase the download speed. If False, this feature will be disabled. progress_bar(bool, optional): If True (default), show the download progress bar. """ self._connection = connection self._cube_id = cube_id self.parallel = parallel self.progress_bar = progress_bar self._size_limit = 10000000 # this sets desired chunk size in bytes self._initial_limit = 1000 # initial limit for the cube_instance request # load dataset information self.__info() self.__definition() # load attribute elements self.__OFFSET = 0 self._attr_elements = [] self._filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) self._dataframe = None self._dataframes = [] self._table_definition = {}
def test_view_filter_same_attrib_two_element(self): """Test that choosing 2 att elems from same attribute should return matching view filter in body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(self.element_sel_same_list) vf = f._view_filter() self.assertIn("operator", vf) self.assertEqual( vf["operator"], "In") # should be In because elems are for same parent attr self.assertIn("operands", vf) att, elems = vf["operands"] self.assertEqual(att["type"], "attribute") self.assertEqual(elems["type"], "elements") for obj_id in self.element_sel_same_list: self.assertEqual(att["id"], f.attr_elems.get(obj_id)["attribute_id"]) for elem, obj_id in zip(elems["elements"], self.element_sel_same_list): self.assertEqual(elem["id"], obj_id)
def apply_filters(self, attributes=None, metrics=None, attr_elements=None): """Apply filters on the report's objects, so only selected attributes, metrics and attributes' elements will be retrieved from Intelligence Server. Args: attributes (list, optional): attributes to be included in the filter. metrics (list, optional): metrics to be included in the filter. attr_elements (list, optional): attributes' elements to be included in the filter. """ if any([attributes, metrics, attr_elements]): if not self._attr_elements and attr_elements: self.__attr_elements() if self._attr_elements and not self._filter.attr_elems: self._filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) if attributes: self._filter.select(object_id=attributes) if attributes == []: self._filter.attr_selected = [] if metrics: self._filter.select(object_id=metrics) if metrics == []: self._filter.metr_selected = [] if attr_elements is not None: self._filter.select(object_id=attr_elements)
def __init__(self, connection, report_id): """ Initialize an instance of a report Args: connection: MicroStrategy connection object returned by `microstrategy.Connection()`. report_id (str): Identifier of a pre-existing report containing the required data. """ init_pbar = tqdm( desc='Initializing an instance of a report. Please wait...', bar_format='{desc}', leave=False, ncols=285) self._connection = connection self._report_id = report_id # load report information self.__definition() # load attribute elements self.__OFFSET = 0 self.__attr_elements() self._filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) self._dataframe = None init_pbar.close()
def apply_filters(self, attributes=None, metrics=None, attr_elements=None): """Apply filters on the cube data so only the chosen attributes, metrics, and attribute elements are retrieved from the Intelligence Server. Args: attributes (list or None, optional): ids of attributes to be included in the filter. If list is empty, no attributes will be selected and metric data will be aggregated. metrics (list or None, optional): ids of metrics to be included in the filter. If list is empty, no metrics will be selected. attr_elements (list or None, optional): attributes' elements to be included in the filter. """ if not all(element is None for element in [attributes, metrics, attr_elements]): if attr_elements: self.attr_elements if self._attr_elements and not self._filter.attr_elems: self._filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) if attributes: self._filter.select(object_id=attributes) if attributes == []: self._filter.attr_selected = [] if metrics: self._filter.select(object_id=metrics) if metrics == []: self._filter.metr_selected = [] if attr_elements is not None: self._filter.select(object_id=attr_elements)
def test_select_attr_elem_id(self): """Test adding an object via id or list of ids adds the ids to filter property.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(element_id=self.element_sel) self.assertIn(self.element_sel, f.attr_elem_selected)
def test_view_filter_none(self): """Test that adding no attributes elements yields None view filter.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) # should be none if none are obj_id vf = f._view_filter() self.assertIsNone(vf)
def test_select_invalid_object_id(self): """Tests adding an invalid object id does not add the object id to selected filters.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) with self.assertRaises(ValueError): f._select(object_id=self.invalid_id) self.assertEqual(f.attr_elem_selected, [])
def test_select_attr_elem_id_list(self): """Test adding an object via list of ids adds the ids to filter property.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(element_id=self.element_sel_list) for obj_id in self.element_sel_list: self.assertIn(obj_id, f.attr_elem_selected)
def test_select_attribute_id(self): """Test adding an object adds the id to filter property.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(object_id=self.attribute_sel) self.assertIn([self.attribute_sel], f.attr_selected) self.assertEqual(f.attr_elem_selected, [])
def test_init_attribute_elements(self): """Test that when not loading attribute elements, filter's attribute elements are None.""" f = Filter(attributes=self.attributes, metrics=self.metrics) self.assertIsNotNone(f.attr_elems) self.assertEqual(f.attr_elem_selected, []) f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) self.assertIsNotNone(f.attr_elems) self.assertEqual(f.attr_elem_selected, [])
def test_view_filter_not_none(self): """Test that adding no attributes elements yields None view filter.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) # should not be none if some are obj_id f._select_attr_el(self.element_sel) vf = f._view_filter() self.assertIsNotNone(vf)
def test_requested_objects_two_metric(self): """Test that choosing 2 met should return matching requested object in body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(self.metric_sel_list) ro = f._requested_objects() self.assertIn("metrics", ro) self.assertCountEqual([m['id'] for m in ro['metrics']], [m['id'] for m in self.metrics])
def test_requested_objects_one_attribute(self): """Test that choosing 1 att should return matching requested object in body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(self.attribute_sel) ro = f._requested_objects() self.assertIn("attributes", ro) self.assertCountEqual([a['id'] for a in ro['attributes']], [a['id'] for a in self.attributes])
def test_requested_objects_empty_lists(self): """Test that empty lists are properly parsed into requestedObjects.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f.attr_selected = [] f.metr_selected = [] ro = f._requested_objects() self.assertIn("attributes", ro) self.assertIn("metrics", ro) self.assertEqual(ro["attributes"], []) self.assertEqual(ro["metrics"], [])
def _get_definition(self): """Get the definition of a cube, including attributes and metrics. Implements GET /v2/cubes/<cube_id>. """ if self._id is not None: _definition = cubes.cube_definition(connection=self._connection, id=self._id).json() full_attributes = _definition["definition"]["availableObjects"][ "attributes"] full_metrics = _definition["definition"]["availableObjects"][ "metrics"] self._attributes = [{ 'name': attr['name'], 'id': attr['id'] } for attr in full_attributes] self._metrics = [{ 'name': metr['name'], 'id': metr['id'] } for metr in full_metrics] self._table_names = self.__multitable_definition().keys() row_counts = [ 'Row Count - {}'.format(table_name) for table_name in self._table_names ] self._row_counts = list( filter(lambda x: x['name'] in row_counts, self._metrics)) self.__remove_row_count() # for lazy fetch properties self.__definition_retrieved = True self.__filter = Filter(attributes=self._attributes, metrics=self._metrics, row_count_metrics=self._row_counts)
def _filter(self): if not self.__definition_retrieved: self._get_definition() if self.__filter is None: self.__filter = Filter(attributes=self._attributes, metrics=self._metrics, attr_elements=self._attr_elements) return self.__filter
def __init__(self, connection, cube_id, instance_id=None, parallel=True, progress_bar=True): """Initialize an instance of a cube. Args: connection: MicroStrategy connection object returned by `connection.Connection()`. cube_id (str): Identifier of a pre-existing cube containing the required data. instance_id (str): Identifier of an instance if cube instance has been already initialized, NULL by default. parallel (bool, optional): If True (default), utilize optimal number of threads to increase the download speed. If False, this feature will be disabled. progress_bar(bool, optional): If True (default), show the download progress bar. """ if not connection.project_id: helper.exception_handler( "Please provide a project id or project name when creating the Connection object.", ConnectionError) self._connection = connection self._cube_id = cube_id self.instance_id = instance_id self.parallel = parallel self.progress_bar = True if progress_bar and config.progress_bar else False self._size_limit = 10000000 # this sets desired chunk size in bytes self._initial_limit = 1000 # initial limit for the cube_instance request self._table_definition = {} self._dataframe = None self._dataframes = [] self._attr_elements = None # load dataset information self.__info() self.__definition() self.__remove_row_count() self.__filter = Filter(attributes=self.attributes, metrics=self.metrics, row_count_metrics=self._row_counts)
def from_dict(cls, source: dict, connection: "Connection") -> "_Cube": """Initialize a single Cube object from a dictionary with cube details retrieved from I-Server.""" cube = super().from_dict(source, connection) cube.__filter = Filter(attributes=cube._attributes, metrics=cube._metrics, row_count_metrics=cube._row_counts) return cube
def __init__(self, connection: "Connection", report_id: str, instance_id: str = None, parallel: bool = True, progress_bar: bool = True): """Initialize an instance of a report. Args: connection: MicroStrategy connection object returned by `connection.Connection()`. report_id (str): Identifier of a pre-existing report containing the required data. instance_id (str): Identifier of an instance if report instance has been already initialized, NULL by default. parallel (bool, optional): If True (default), utilize optimal number of threads to increase the download speed. If False, this feature will be disabled. progress_bar(bool, optional): If True (default), show the download progress bar. """ if not connection.application_id: helper.exception_handler(( "Please provide an application id or application name when creating the" "Connection object."), ConnectionError) self._connection = connection self._report_id = report_id self.instance_id = instance_id self.parallel = parallel self.progress_bar = True if progress_bar and config.progress_bar else False self._subtotals = None self.cross_tab = False self.cross_tab_filter = {} self._size_limit = 10000000 # this sets desired chunk size in bytes self._initial_limit = 1000 # initial limit for the report_instance request self._dataframe = None self._attr_elements = None # load report information self.__definition() self.__filter = Filter(attributes=self.attributes, metrics=self.metrics)
def test_view_filter_same_attrib_one_element(self): """Test that choosing 1 att elem should return matching view filter in body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(self.element_sel) vf = f._view_filter() self.assertIn("operator", vf) self.assertEqual(vf["operator"], "In") self.assertIn("operands", vf) att, elems = vf["operands"] self.assertEqual(att["type"], "attribute") self.assertEqual(att["id"], f.attr_elems.get(self.element_sel)["attribute_id"]) self.assertEqual(elems["type"], "elements") for elem, obj_id in zip(elems["elements"], self.element_sel): self.assertEqual(elem["id"], self.element_sel)
def test_view_filter_multi_attrib_element(self): """Test that choosing att elem across attributes forms a correct view filter body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(self.element_sel_list) vf = f._view_filter() self.assertEqual( vf["operator"], "And") # should be And because elements span parent attributes self.assertIn("operator", vf) self.assertIn("operands", vf) self.assertIsInstance(vf["operands"], list) for operand in vf["operands"]: self.assertIn("operator", operand) self.assertIn("operands", operand) self.assertEqual( operand["operator"], "In") # should be In because elems are for same parent attr att, elems = operand["operands"] self.assertEqual(att["type"], "attribute") self.assertEqual(elems["type"], "elements") for obj_id in elems["elements"]: self.assertEqual( att["id"], f.attr_elems.get(obj_id["id"])["attribute_id"]) for elem, obj_id in zip(elems["elements"], elems["elements"]): self.assertEqual(elem["id"], obj_id["id"])
def test_init_object_ids(self): """Test that each object id is loaded in filter object properties.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) for a in self.attributes: self.assertIn(a["id"], f.attributes) for m in self.metrics: self.assertIn(m["id"], f.metrics) for ae in self.elements: for elem in ae["elements"]: self.assertIn(elem["id"], f.attr_elems)
def test_init_filter_structure(self): """Test that init populates the correct instance properties.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) # assert types self.assertIsInstance(f.attributes, dict) self.assertIsInstance(f.metrics, dict) self.assertIsInstance(f.attr_elems, dict) # these should be empty self.assertEqual(len(f.attr_selected), len(f.attributes)) self.assertEqual(len(f.metr_selected), len(f.metrics)) self.assertEqual(f.attr_elem_selected, [])
def test_filter_body_attribute_element_list(self): """Test for presence of attribute element ids in the filter body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(self.element_sel_list) vf = f._view_filter() fb = f._filter_body() self.assertDictEqual(fb["viewFilter"], vf)
def test_filter_body_metric_list(self): """Test for presence of metric ids in the filter body.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(self.metric_sel_list) ro = f._requested_objects() fb = f._filter_body() self.assertListEqual(fb["requestedObjects"]["metrics"], ro["metrics"])
def test_clear(self): """Test that clearing filters works.""" obj_id = self.attribute_sel_list + self.metric_sel_list el_id = self.element_sel_list f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(obj_id) f._select_attr_el(el_id) self.assertIsNotNone(f.attr_selected) self.assertIsNotNone(f.metr_selected) self.assertIsNotNone(f.attr_elem_selected) # reset f._clear() self.assertEqual(f.attr_elem_selected, [])
def test_requested_objects_both_list(self): """Test that adding lists of attributes and metrics yields requested objects with correct elements. """ f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select(self.attribute_sel_list) f._select(self.metric_sel_list) ro = f._requested_objects() self.assertIn("attributes", ro) self.assertIn("metrics", ro) self.assertCountEqual([a['id'] for a in ro['attributes']], [a['id'] for a in self.attributes]) self.assertCountEqual([m['id'] for m in ro['metrics']], [m['id'] for m in self.metrics])
def test_select_duplicate_attr_elem_id(self): """Tests adding a duplicate id does not add the second id to the selected filter.""" f = Filter(attributes=self.attributes, metrics=self.metrics, attr_elements=self.elements) f._select_attr_el(element_id=self.element_sel) # add a duplicate with self.assertWarns(Warning): f._select_attr_el(element_id=self.element_sel) # object id be here self.assertIn(self.element_sel, f.attr_elem_selected) self.assertEqual(len(f.attr_elem_selected), 1)