class User(TM1Object): """ Abstraction of a TM1 User """ def __init__(self, name: str, groups: Iterable[str], friendly_name: Optional[str] = None, password: Optional[str] = None, user_type: Union[UserType, str] = None, enabled: bool = None): self._name = name self._groups = CaseAndSpaceInsensitiveSet(*groups) self._friendly_name = friendly_name self._password = password self._enabled = enabled self._user_type = user_type # determine user_type if user_type is None: if str(UserType.Admin) in self._groups: self.user_type = UserType.Admin elif str(UserType.SecurityAdmin) in self._groups: self.user_type = UserType.SecurityAdmin elif str(UserType.DataAdmin) in self._groups: self.user_type = UserType.DataAdmin elif str(UserType.OperationsAdmin) in self._groups: self.user_type = UserType.OperationsAdmin else: self.user_type = UserType.User else: self.user_type = user_type @property def name(self) -> str: return self._name @property def user_type(self) -> UserType: return self._user_type @property def friendly_name(self) -> str: return self._friendly_name @property def password(self) -> str: if self._password: return self._password @property def is_admin(self) -> bool: return 'ADMIN' in self.groups @property def groups(self) -> List[str]: return [group for group in self._groups] @property def enabled(self) -> bool: return self._enabled @name.setter def name(self, value: str): self._name = value @friendly_name.setter def friendly_name(self, value: str): self._friendly_name = value @password.setter def password(self, value: str): self._password = value @enabled.setter def enabled(self, value: Union[bool, None]): self._enabled = value @user_type.setter def user_type(self, value: Union[str, UserType]): if not isinstance(value, str) and not isinstance(value, UserType): raise ValueError( "argument 'user_type' must be of type str or UserType") self._user_type = UserType(value) # update groups as well, since TM1 doesn't react to change in user_type property if self._user_type is not UserType.User: self.add_group(str(self._user_type)) def add_group(self, group_name: str): self._groups.add(group_name) def remove_group(self, group_name: str): self._groups.discard(group_name) @classmethod def from_json(cls, user_as_json: str): """ Alternative constructor :param user_as_json: user as JSON string :return: user, an instance of this class """ user_as_dict = json.loads(user_as_json) return cls.from_dict(user_as_dict) @classmethod def from_dict(cls, user_as_dict: Dict) -> 'User': """ Alternative constructor :param user_as_dict: user as dict :return: user, an instance of this class """ return cls(name=user_as_dict['Name'], friendly_name=user_as_dict['FriendlyName'], enabled=user_as_dict["Enabled"], user_type=user_as_dict["Type"], groups=[group["Name"] for group in user_as_dict['Groups']]) @property def body(self) -> str: return self.construct_body() def construct_body(self) -> str: """ construct body (json) from the class attributes :return: String, TM1 JSON representation of a user """ body_as_dict = collections.OrderedDict() body_as_dict['Name'] = self.name body_as_dict['FriendlyName'] = self.friendly_name or self.name body_as_dict['Enabled'] = self._enabled body_as_dict['Type'] = str(self._user_type) if self.password: body_as_dict['Password'] = self._password body_as_dict['*****@*****.**'] = [ format_url("Groups('{}')", group) for group in self.groups ] return json.dumps(body_as_dict, ensure_ascii=False)
def test_ne(self): new_set = CaseAndSpaceInsensitiveSet() new_set.add("wrong1") new_set.add("wrong2") new_set.add("wrong3") self.assertNotEqual(self.set, new_set)
def test_eq_case_and_space_sensitivity(self): new_set = CaseAndSpaceInsensitiveSet() new_set.add(self.original_values[0].upper()) new_set.add(self.original_values[1].lower()) new_set.add(self.original_values[2].lower()) self.assertEqual(self.set, new_set)
def test_eq(self): new_set = CaseAndSpaceInsensitiveSet() new_set.add(self.original_values[0]) new_set.add(self.original_values[1]) new_set.add(self.original_values[2]) self.assertEqual(self.set, new_set)
class User(TM1Object): """ Abstraction of a TM1 User """ def __init__(self, name, groups, friendly_name=None, password=None): self._name = name self._groups = CaseAndSpaceInsensitiveSet(*groups) self._friendly_name = friendly_name self._password = password @property def name(self): return self._name @property def friendly_name(self): return self._friendly_name @property def password(self): if self._password: return self._password @property def is_admin(self): return 'ADMIN' in self.groups @property def groups(self): return [group for group in self._groups] @name.setter def name(self, value): self._name = value @friendly_name.setter def friendly_name(self, value): self._friendly_name = value @password.setter def password(self, value): self._password = value def add_group(self, group_name): self._groups.add(group_name) def remove_group(self, group_name): self._groups.discard(group_name) @classmethod def from_json(cls, user_as_json): """ Alternative constructor :param user_as_json: user as JSON string :return: user, an instance of this class """ user_as_dict = json.loads(user_as_json) return cls.from_dict(user_as_dict) @classmethod def from_dict(cls, user_as_dict): """ Alternative constructor :param user_as_dict: user as dict :return: user, an instance of this class """ return cls(name=user_as_dict['Name'], friendly_name=user_as_dict['FriendlyName'], groups=[group["Name"] for group in user_as_dict['Groups']]) @property def body(self): return self.construct_body() def construct_body(self): """ construct body (json) from the class attributes :return: String, TM1 JSON representation of a user """ body_as_dict = collections.OrderedDict() body_as_dict['Name'] = self.name body_as_dict['FriendlyName'] = self.friendly_name if self.password: body_as_dict['Password'] = self._password body_as_dict['*****@*****.**'] = [ 'Groups(\'{}\')'.format(group) for group in self.groups ] return json.dumps(body_as_dict, ensure_ascii=False)
def build_dimensions(tm1: TM1Service, loans: list): dimension_name = "Time" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for year in range(2005, 2020, 1): hierarchy.add_element(element_name=str(year), element_type="Consolidated") hierarchy.add_edge(parent=total_element, component=str(year), weight=1) for month in ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"): hierarchy.add_element(element_name="{}-{}".format( month, str(year)), element_type="Numeric") hierarchy.add_edge(parent=str(year), component="{}-{}".format(month, str(year)), weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Loan" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) dimension.add_hierarchy(hierarchy) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") element_names = [loan.loan_id for loan in loans] # send elements and edges separately to avoid strange firewall connection abortion from server side for element_name in element_names: hierarchy.add_element(element_name=element_name, element_type="Numeric") update_or_create_dimension(tm1, dimension) for element_name in element_names: hierarchy.add_edge(parent=total_element, component=element_name, weight=1) update_or_create_dimension(tm1, dimension) dimension_name = "LC Rating" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for rating in ("A", "B", "C", "D", "E", "F", "G"): element_name = rating hierarchy.add_element(element_name=element_name, element_type="Consolidated") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) for sub_rating in ("1", "2", "3", "4", "5"): element_name = rating + sub_rating hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=rating, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "FICO Score" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in range(300, 851, 1): hierarchy.add_element(element_name=str(element_name), element_type="Numeric") hierarchy.add_edge(parent=total_element, component=str(element_name), weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Employment" if tm1.dimensions.exists(dimension_name=dimension_name): dimension = tm1.dimensions.get(dimension_name=dimension_name) else: dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name if hierarchy_name in dimension: hierarchy = dimension.get_hierarchy(hierarchy_name=hierarchy_name) else: hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) dimension.add_hierarchy(hierarchy) total_element = "Total " + dimension_name if total_element not in hierarchy.elements: hierarchy.add_element(element_name=total_element, element_type="Consolidated") employments = CaseAndSpaceInsensitiveSet() for loan in loans: employments.add(loan.emp_title) employments.add("None") for employment in employments: if employment and employment not in hierarchy.elements: employment = employment.strip() hierarchy.add_element(element_name=employment, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=employment, weight=1) update_or_create_dimension(tm1, dimension) dimension_name = "Term" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("36 months", "60 months"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Income" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("10000", "20000", "30000", "40000", "50000", "60000", "70000", "80000", "90000", "100000", "110000", "120000", "130000", "140000", "150000", "160000", "170000", "180000", "190000"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Purpose" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("other", "debt_consolidation", "medical", "major_purchase", "home_improvement", "credit_card", "vacation", "house", "car", "small_business", "moving", "renewable_energy", "wedding", "educational"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Loan Status" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("Current", "Fully Paid", "Late (31-120 days)", "Late (16-30 days)", "Charged Off", "In Grace Period", "Default"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "State" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") states = CaseAndSpaceInsensitiveSet() for loan in loans: states.add(loan.addr_state) states.add("None") for state in states: if state: state = state.strip() hierarchy.add_element(element_name=state, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=state, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Home Ownership" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("Rent", "Own", "Mortgage", "Any", "None"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Application Type" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in ("Individual", "Joint App"): hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Income To Loan Ratio" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for counter in range(0, 100000, 1): dti = counter / 100 element_name = "%.2f" % dti hierarchy.add_element(element_name=element_name, element_type="Numeric") hierarchy.add_edge(parent=total_element, component=element_name, weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = "Delinquency Events" dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) total_element = "Total " + dimension_name hierarchy.add_element(element_name=total_element, element_type="Consolidated") for element_name in range(0, 51): hierarchy.add_element(element_name=str(element_name), element_type="Numeric") hierarchy.add_edge(parent=total_element, component=str(element_name), weight=1) dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) dimension_name = " ".join([CUBE_NAME, "Measure"]) dimension = Dimension(name=dimension_name) hierarchy_name = dimension_name hierarchy = Hierarchy(name=hierarchy_name, dimension_name=dimension_name) for element_name in ("loan_amnt", "int_rate", "installment", "out_prncp", "total_pymnt", "last_pymnt_amnt", "total_pymnt_by_loan_amnt", "emp_length", "num_personal_inquiries", "inquiries_in_last_12m", "mths_since_last_delinq", "mths_since_recent_bc_dlq", "mths_since_recent_inq", "mths_since_recent_revol_delinq", "defaulted", "defaulted_or_delayed"): hierarchy.add_element(element_name=element_name, element_type="Numeric") for element_name in ("last_pymnt_d", ): hierarchy.add_element(element_name=element_name, element_type="String") hierarchy.add_element_attribute(name="Description", attribute_type="Alias") dimension.add_hierarchy(hierarchy) update_or_create_dimension(tm1, dimension) attributes = { ("loan_amnt", "Description"): "Listed amount of the loan", ("int_rate", "Description"): "Interest rate", ("installment", "Description"): "Monthly payment", ("out_prncp", "Description"): "Remaining outstanding amount", ("total_pymnt", "Description"): "Payments received to date", ("total_pymnt_by_loan_amnt", "Description"): "Total Payments devided by total Loan", ("last_pymnt_amnt", "Description"): "Last payment amount received", ("last_pymnt_d", "Description"): "Last month payment was received", ("defaulted", "Description"): "Loan is defaulted" } tm1.cubes.cells.write_values(cube_name="}ElementAttributes_" + dimension_name, cellset_as_dict=attributes)