Esempio n. 1
0
    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))
Esempio n. 2
0
    def update(self, hierarchy: Hierarchy, **kwargs) -> List[Response]:
        """ update a hierarchy. It's a two step process: 
        1. Update Hierarchy
        2. Update Element-Attributes

        Function caters for Bug with Edge Creation:
        https://www.ibm.com/developerworks/community/forums/html/topic?id=75f2b99e-6961-4c71-9364-1d5e1e083eff

        :param hierarchy: instance of TM1py.Hierarchy
        :return: list of responses
        """
        # functions returns multiple responses
        responses = list()
        # 1. Update Hierarchy
        url = format_url("/api/v1/Dimensions('{}')/Hierarchies('{}')",
                         hierarchy.dimension_name, hierarchy.name)
        # Workaround EDGES: Handle Issue, that Edges cant be created in one batch with the Hierarchy in certain versions
        hierarchy_body = hierarchy.body_as_dict
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            del hierarchy_body["Edges"]
        responses.append(
            self._rest.PATCH(url, json.dumps(hierarchy_body), **kwargs))

        # 2. Update Attributes
        responses.append(
            self.update_element_attributes(hierarchy=hierarchy, **kwargs))

        # Workaround EDGES
        if self.version[0:8] in self.EDGES_WORKAROUND_VERSIONS:
            from TM1py.Services import ProcessService
            process_service = ProcessService(self._rest)
            ti_function = "HierarchyElementComponentAdd('{}', '{}', '{}', '{}', {});"
            ti_statements = [
                ti_function.format(hierarchy.dimension_name, hierarchy.name,
                                   edge[0], edge[1],
                                   hierarchy.edges[(edge[0], edge[1])])
                for edge in hierarchy.edges
            ]
            responses.append(
                process_service.execute_ti_code(lines_prolog=ti_statements,
                                                **kwargs))

        return responses
Esempio n. 3
0
    def write_to_message_log(self, level: str, message: str, **kwargs) -> None:
        """
        :param level: string, FATAL, ERROR, WARN, INFO, DEBUG
        :param message: string
        :return:
        """

        valid_levels = CaseAndSpaceInsensitiveSet(
            {'FATAL', 'ERROR', 'WARN', 'INFO', 'DEBUG'})
        if level not in valid_levels:
            raise ValueError(f"Invalid level: '{level}'")

        from TM1py.Services import ProcessService
        process_service = ProcessService(self._rest)
        process = Process(name="",
                          prolog_procedure="LogOutput('{}', '{}');".format(
                              level, message))
        success, status, _ = process_service.execute_process_with_return(
            process, **kwargs)

        if not success:
            raise RuntimeError(
                f"Failed to write to TM1 Message Log through unbound process. Status: '{status}'"
            )
Esempio n. 4
0
    def __init__(self, **kwargs):
        self._tm1_rest = RestService(**kwargs)

        # instantiate all Services
        self.annotations = AnnotationService(self._tm1_rest)
        self.cells = CellService(self._tm1_rest)
        self.chores = ChoreService(self._tm1_rest)
        self.cubes = CubeService(self._tm1_rest)
        self.dimensions = DimensionService(self._tm1_rest)
        self.elements = ElementService(self._tm1_rest)
        self.hierarchies = HierarchyService(self._tm1_rest)
        self.monitoring = MonitoringService(self._tm1_rest)
        self.power_bi = PowerBiService(self._tm1_rest)
        self.processes = ProcessService(self._tm1_rest)
        self.security = SecurityService(self._tm1_rest)
        self.server = ServerService(self._tm1_rest)
        self.subsets = SubsetService(self._tm1_rest)
        self.applications = ApplicationService(self._tm1_rest)
        self.views = ViewService(self._tm1_rest)
Esempio n. 5
0
 def _instantiate_services(self):
     self.annotations = AnnotationService(self._tm1_rest)
     self.cells = CellService(self._tm1_rest)
     self.chores = ChoreService(self._tm1_rest)
     self.cubes = CubeService(self._tm1_rest)
     self.dimensions = DimensionService(self._tm1_rest)
     self.elements = ElementService(self._tm1_rest)
     self.git = GitService(self._tm1_rest)
     self.hierarchies = HierarchyService(self._tm1_rest)
     self.monitoring = MonitoringService(self._tm1_rest)
     self.power_bi = PowerBiService(self._tm1_rest)
     self.processes = ProcessService(self._tm1_rest)
     self.security = SecurityService(self._tm1_rest)
     self.server = ServerService(self._tm1_rest)
     self.subsets = SubsetService(self._tm1_rest)
     self.applications = ApplicationService(self._tm1_rest)
     self.views = ViewService(self._tm1_rest)
     self.sandboxes = SandboxService(self._tm1_rest)
     self.git = GitService(self._tm1_rest)
Esempio n. 6
0
 def save_data(self, **kwargs) -> Response:
     from TM1py.Services import ProcessService
     ti = "SaveDataAll;"
     process_service = ProcessService(self._rest)
     return process_service.execute_ti_code(ti, **kwargs)
Esempio n. 7
0
 def save_data(self):
     from TM1py.Services import ProcessService
     ti = "SaveDataAll;"
     process_service = ProcessService(self._rest)
     process_service.execute_ti_code(ti)
Esempio n. 8
0
 def security_refresh(self):
     from TM1py.Services import ProcessService
     ti = "SecurityRefresh;"
     process_service = ProcessService(self._rest)
     process_service.execute_ti_code(ti)
Esempio n. 9
0
 def security_refresh(self, **kwargs) -> Response:
     from TM1py.Services import ProcessService
     ti = "SecurityRefresh;"
     process_service = ProcessService(self._rest)
     return process_service.execute_ti_code(ti, **kwargs)
Esempio n. 10
0
 def __init__(self, rest):
     super().__init__(rest)
     self._process_service = ProcessService(rest)
Esempio n. 11
0
class SubsetService(ObjectService):
    """ Service to handle Object Updates for TM1 Subsets (dynamic and static)
    
    """
    def __init__(self, rest):
        super().__init__(rest)
        self._process_service = ProcessService(rest)

    def create(self, subset, private=True):
        """ create subset on the TM1 Server

            :param subset: TM1py.Subset, the subset that shall be created
            :param private: boolean

            :return:
                string: the response
        """
        subsets = "PrivateSubsets" if private else "Subsets"
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/{}' \
            .format(subset.dimension_name, subset.dimension_name, subsets)
        response = self._rest.POST(request, subset.body)
        return response

    def get(self, dimension_name, subset_name, private=True):
        """ get a subset from the TM1 Server

            :param dimension_name: string, name of the dimension
            :param subset_name: string, name of the subset
            :param private: Boolean

            :return: instance of TM1py.Subset
        """
        subsets = "PrivateSubsets" if private else "Subsets"
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/{}(\'{}\')?$expand=' \
                  'Hierarchy($select=Dimension),' \
                  'Elements($select=Name)&$select=*,Alias'.format(dimension_name, dimension_name, subsets, subset_name)
        response = self._rest.GET(request=request)
        return Subset.from_json(response)

    def get_all_names(self, dimension_name, hierarchy_name, private=True):
        """ get names of all private or public subsets in a hierarchy

        :param dimension_name:
        :param hierarchy_name:
        :param private: Boolean
        :return: List of Strings
        """
        subsets = "PrivateSubsets" if private else "Subsets"
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/{}?$select=Name' \
            .format(dimension_name, hierarchy_name, subsets)
        response = self._rest.GET(request=request)
        subsets = json.loads(response)['value']
        return [subset['Name'] for subset in subsets]

    def update(self, subset, private=True):
        """ update a subset on the TM1 Server

        :param subset: instance of TM1py.Subset.
        :param private: Boolean
        :return: response
        """

        if private:
            # Just delete it and rebuild it, since there are no dependencies
            return self._update_private(subset)

        else:
            # Update it. Clear Elements with evil workaround
            return self._update_public(subset)

    def _update_private(self, subset):
        """ update a private subset on the TM1 Server

        :param subset: instance of TM1py.Subset
        :return: response
        """
        # Delete it
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/PrivateSubsets(\'{}\')' \
            .format(subset.dimension_name, subset.dimension_name, subset.name)
        self._rest.DELETE(request, '')
        # Rebuild it
        return self.create(subset, True)

    def _update_public(self, subset):
        """ Update a public subset on the TM1 Server

        :param subset: instance of TM1py.Subset
        :return: response
        """
        # clear elements of subset. evil workaround! Should be done through delete on the Elements Collection
        # (which is currently not supported 10.2.2 FP6)
        ti = "SubsetDeleteAllElements(\'{}\', \'{}\');".format(subset.dimension_name, subset.name)
        self._process_service.execute_ti_code(lines_prolog=ti, lines_epilog='')
        # update subset
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/Subsets(\'{}\')' \
            .format(subset.dimension_name, subset.dimension_name, subset.name)
        return self._rest.PATCH(request=request, data=subset.body)

    def delete(self, dimension_name, subset_name, private=True):
        """ Delete an existing subset on the TM1 Server

        :param dimension_name: String, name of the dimension
        :param subset_name: String, name of the subset
        :param private: Boolean
        :return:
        """
        subsets = "PrivateSubsets" if private else "Subsets"
        request = '/api/v1/Dimensions(\'{}\')/Hierarchies(\'{}\')/{}(\'{}\')' \
            .format(dimension_name, dimension_name, subsets, subset_name)
        response = self._rest.DELETE(request=request, data='')
        return response

    def exists(self, dimension_name, hierarchy_name, subset_name):
        """checks if subset exists as private and / or public

        :param dimension_name: 
        :param hierarchy_name:
        :param subset_name: 
        :return: 2 booleans: (Private subset exsits, Public subset exists)
        """
        subset_types = collections.OrderedDict()
        subset_types['PrivateSubsets'] = False
        subset_types['Subsets'] = False

        for subset_type in subset_types:
            try:
                self._rest.GET("/api/v1/Dimensions('{}')/Hierarchies('{}')/{}('{}')"
                               .format(dimension_name, hierarchy_name, subset_type, subset_name))
                subset_types[subset_type] = True
            except TM1pyException as e:
                if e._status_code != 404:
                    raise e
        return tuple(subset_types.values())