def update(self, dimension: Dimension, **kwargs): """ Update an existing dimension :param dimension: instance of TM1py.Dimension :return: None """ # delete hierarchies that have been removed from the dimension object hierarchies_to_be_removed = CaseAndSpaceInsensitiveSet( *self.hierarchies.get_all_names(dimension.name, **kwargs)) for hierarchy in dimension.hierarchy_names: hierarchies_to_be_removed.discard(hierarchy) # update all Hierarchies except for the implicitly maintained 'Leaves' Hierarchy for hierarchy in dimension: if not case_and_space_insensitive_equals(hierarchy.name, "Leaves"): if self.hierarchies.exists(hierarchy.dimension_name, hierarchy.name, **kwargs): self.hierarchies.update(hierarchy, **kwargs) else: self.hierarchies.create(hierarchy, **kwargs) for hierarchy_name in hierarchies_to_be_removed: if not case_and_space_insensitive_equals(hierarchy_name, "Leaves"): self.hierarchies.delete(dimension_name=dimension.name, hierarchy_name=hierarchy_name, **kwargs)
def remove_hierarchy(self, hierarchy_name: str): if case_and_space_insensitive_equals(hierarchy_name, "leaves"): raise ValueError("'Leaves' hierarchy must not be removed from dimension") for num, hierarchy in enumerate(self._hierarchies): if case_and_space_insensitive_equals(hierarchy.name, hierarchy_name): del self._hierarchies[num] return
def update_default_member(self, dimension_name, hierarchy_name=None, member_name=""): """ Update the default member of a hierarchy. Currently implemented through TI, since TM1 API does not supports default member updates yet. :param dimension_name: :param hierarchy_name: :param member_name: :return: """ from TM1py import ProcessService, CellService if hierarchy_name and not case_and_space_insensitive_equals( dimension_name, hierarchy_name): dimension = "{}:{}".format(dimension_name, hierarchy_name) else: dimension = dimension_name cells = {(dimension, 'hierarchy0', 'defaultMember'): member_name} CellService(self._rest).write_values( cube_name="}HierarchyProperties", cellset_as_dict=cells, dimensions=('}Dimensions', '}Hierarchies', '}HierarchyProperties')) return ProcessService(self._rest).execute_ti_code( lines_prolog="RefreshMdxHierarchy('{}');".format(dimension_name))
def create(self, dimension: Dimension, **kwargs) -> Response: """ Create a dimension :param dimension: instance of TM1py.Dimension :return: response """ # If Dimension exists. throw Exception if self.exists(dimension.name): raise RuntimeError("Dimension '{}' already exists".format( dimension.name)) # If not all subsequent calls successful -> undo everything that has been done in this function try: # Create Dimension, Hierarchies, Elements, Edges. url = "/api/v1/Dimensions" response = self._rest.POST(url, dimension.body, **kwargs) # Create ElementAttributes for hierarchy in dimension: if not case_and_space_insensitive_equals( hierarchy.name, "Leaves"): self.hierarchies.update_element_attributes( hierarchy, **kwargs) except TM1pyException as e: # undo everything if problem in step 1 or 2 if self.exists(dimension.name, **kwargs): self.delete(dimension.name) raise e return response
def get_hierarchy(self, hierarchy_name): for hierarchy in self._hierarchies: if case_and_space_insensitive_equals(hierarchy.name, hierarchy_name): return hierarchy raise ValueError("Hierarchy: {} not found in dimension: {}".format( hierarchy_name, self.name))
def test_get_current_user(self): me = self.tm1.security.get_current_user() self.assertTrue( case_and_space_insensitive_equals(me.name, self.config['tm1srv01']['User'])) user = self.tm1.security.get_user(self.config['tm1srv01']['User']) self.assertEqual(me, user)
def get_dimension_names_for_writing(self, cube_name): from TM1py.Services import CubeService cube_service = CubeService(self._rest) dimensions = cube_service.get_dimension_names(cube_name) # do not return sandbox dimension as first dimension, as it can't be used in address tuple for writing if case_and_space_insensitive_equals(dimensions[0], self.SANDBOX_DIMENSION): return dimensions[1:] return dimensions
def update(self, dimension: Dimension, **kwargs): """ Update an existing dimension :param dimension: instance of TM1py.Dimension :return: None """ # delete hierarchies that have been removed from the dimension object hierarchies_to_be_removed = CaseAndSpaceInsensitiveSet( *self.hierarchies.get_all_names(dimension.name, **kwargs)) for hierarchy in dimension.hierarchy_names: hierarchies_to_be_removed.discard(hierarchy) # update all Hierarchies except for the implicitly maintained 'Leaves' Hierarchy for hierarchy in dimension: if not case_and_space_insensitive_equals(hierarchy.name, "Leaves"): if self.hierarchies.exists(hierarchy.dimension_name, hierarchy.name, **kwargs): self.hierarchies.update(hierarchy, **kwargs) else: self.hierarchies.create(hierarchy, **kwargs) # Edge case: elements in leaves hierarchy that do not exist in other hierarchies if "Leaves" in dimension: existing_leaves = CaseAndSpaceInsensitiveSet( self.hierarchies.elements.get_leaf_element_names( dimension.name, "Leaves")) leaves_to_create = list() for leaf in dimension.get_hierarchy("Leaves"): if leaf.name not in existing_leaves: leaves_to_create.append(leaf) if leaves_to_create: self.hierarchies.elements.add_elements( dimension_name=dimension.name, hierarchy_name="Leaves", elements=leaves_to_create) for hierarchy_name in hierarchies_to_be_removed: if not case_and_space_insensitive_equals(hierarchy_name, "Leaves"): self.hierarchies.delete(dimension_name=dimension.name, hierarchy_name=hierarchy_name, **kwargs)
def _construct_body(self, include_leaves_hierarchy=False) -> Dict: body_as_dict = collections.OrderedDict() body_as_dict["Name"] = self._name body_as_dict["UniqueName"] = self.unique_name body_as_dict["Attributes"] = self._attributes body_as_dict["Hierarchies"] = [ hierarchy.body_as_dict for hierarchy in self.hierarchies if not case_and_space_insensitive_equals(hierarchy.name, "Leaves") or include_leaves_hierarchy ] return body_as_dict
def get_ancestors(self, element_name: str, recursive: bool = False) -> Set[Element]: ancestors = set() for (parent, component) in self._edges: if not case_and_space_insensitive_equals(component, element_name): continue ancestor: Element = self.elements[parent] ancestors.add(ancestor) if recursive: ancestors = ancestors.union( self.get_ancestors(ancestor.name, True)) return ancestors
def get_descendant_edges(self, element_name: str, recursive: bool = False) -> Dict: descendant_edges = dict() for (parent, component), weight in self._edges.items(): if not case_and_space_insensitive_equals(parent, element_name): continue descendant_edges[parent, component] = weight descendant: Element = self.elements[component] if recursive and descendant.element_type == Element.Types.CONSOLIDATED: descendant_edges.update( self.get_descendant_edges(descendant.name, True)) return descendant_edges
def get_descendants(self, element_name: str, recursive: bool = False, leaves_only=False) -> Set[Element]: descendants = set() for (parent, component) in self._edges: if not case_and_space_insensitive_equals(parent, element_name): continue descendant: Element = self.elements[component] if not leaves_only: descendants.add(descendant) else: if descendant.element_type == Element.Types.NUMERIC: descendants.add(descendant) if recursive and descendant.element_type == Element.Types.CONSOLIDATED: descendants = descendants.union( self.get_descendants(descendant.name, True)) return descendants
def remove_element_attribute(self, name: str): self._element_attributes = [ element_attribute for element_attribute in self.element_attributes if not case_and_space_insensitive_equals(element_attribute.name, name) ]
def contains_hierarchy(self, hierarchy_name): for hierarchy in self._hierarchies: if case_and_space_insensitive_equals(hierarchy.name, hierarchy_name): return True return False