Skip to content

Commit 5ccccf1

Browse files
VadimMitsenkoMariusWirtz
authored andcommitted
Fix parent_attribute handling in get_elements_dataframe for PA v12
1 parent b90509f commit 5ccccf1

2 files changed

Lines changed: 72 additions & 34 deletions

File tree

TM1py/Services/ElementService.py

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -383,38 +383,29 @@ def get_elements_dataframe(
383383
depth = 0
384384
for calculated_name, level_name in levels_dict.items():
385385
depth += 1
386-
name_or_attribute = f"Properties('{parent_attribute}')" if parent_attribute else "NAME"
387-
if not verify_version(required_version="12", version=self.version):
388-
member = f"""
389-
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{calculated_name}]
390-
AS [{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * depth}{name_or_attribute}
391-
"""
392-
else:
393-
member = f"""
394-
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{calculated_name}]
395-
AS [{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * depth}PROPERTIES('{name_or_attribute}')
396-
"""
386+
387+
# Deliberately adding a trailing space to Properties after the attribute name
388+
# to ensure the attribute "name" is accessed instead of the built-in NAME property
389+
# when the original attribute is called "Name" (this behavior is relevant starting from v12 )
390+
name_or_attribute = f"Properties('{parent_attribute} ')" if parent_attribute else "NAME"
391+
392+
member = f"""
393+
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{calculated_name}]
394+
AS [{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * depth}{name_or_attribute}
395+
"""
397396
calculated_members_definition.append(member)
398397

399398
parent_members.append(f"[{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{calculated_name}]")
400399

401400
if not skip_weights:
402-
if not verify_version(required_version="12", version=self.version):
403-
member_weight = f"""
404-
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{level_name}_Weight]
405-
AS IIF(
406-
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * (depth - 1)}Properties('MEMBER_WEIGHT') = '',
407-
0,
408-
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * (depth - 1)}Properties('MEMBER_WEIGHT'))
409-
"""
410-
else:
411-
member_weight = f"""
412-
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{level_name}_Weight]
413-
AS IIF(
414-
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * ( depth - 1)}Properties('MEMBER_WEIGHT') = '',
415-
0,
416-
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * ( depth - 1)}Properties('MEMBER_WEIGHT'))
417-
"""
401+
member_weight = f"""
402+
MEMBER [{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{level_name}_Weight]
403+
AS IIF(
404+
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * (depth - 1)}Properties('MEMBER_WEIGHT') = '',
405+
0,
406+
[{dimension_name}].[{hierarchy_name}].CurrentMember.{'Parent.' * (depth - 1)}Properties('MEMBER_WEIGHT'))
407+
"""
408+
418409
calculated_members_definition.append(member_weight)
419410

420411
weight_members.append(f"[{self.ELEMENT_ATTRIBUTES_PREFIX + dimension_name}].[{level_name}_Weight]")
@@ -517,7 +508,7 @@ def get_elements_dataframe(
517508

518509
# format the columns
519510
df_data[cols_to_format] = df_data[cols_to_format].apply(pd.to_numeric)
520-
df_data[cols_to_format] = df_data[cols_to_format].applymap(lambda x: "{:.6f}".format(x))
511+
df_data[cols_to_format] = df_data[cols_to_format].apply(lambda col: col.map(lambda x: f"{x:.6f}"))
521512

522513
# override colum types
523514
element_attributes = self.get_element_attributes(dimension_name, hierarchy_name)

Tests/ElementService_test.py

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def setUp(self):
8080
self.tm1.cubes.cells.write_value("1989/90", self.attribute_cube_name, ("1990", "Financial Year"))
8181
self.tm1.cubes.cells.write_value("1990/91", self.attribute_cube_name, ("1991", "Financial Year"))
8282
self.tm1.cubes.cells.write_value("1991/92", self.attribute_cube_name, ("1992", "Financial Year"))
83+
self.tm1.cubes.cells.write_value("All Years", self.attribute_cube_name, ("Total Years", "Financial Year"))
84+
self.tm1.cubes.cells.write_value("All Consolidations", self.attribute_cube_name, ("All Consolidations", "Financial Year"))
8385

8486
self.create_or_update_dimension_with_hierarchies()
8587

@@ -560,6 +562,48 @@ def test_get_elements_dataframe_element_type_column(self):
560562
def test_get_elements_dataframe_element_type_column_use_blob(self):
561563
self.run_test_get_elements_dataframe_element_type_column(True)
562564

565+
def run_test_get_elements_dataframe_parent_attribute(self, use_blob):
566+
df = self.tm1.elements.get_elements_dataframe(
567+
dimension_name=self.dimension_name,
568+
hierarchy_name=self.hierarchy_name,
569+
elements=["1989", "1990"],
570+
skip_consolidations=True,
571+
attributes=["Next Year", "Previous Year"],
572+
attribute_column_prefix="Attribute ",
573+
skip_parents=False,
574+
level_names=None,
575+
parent_attribute="Financial Year",
576+
skip_weights=False,
577+
use_blob=use_blob,
578+
)
579+
580+
expected_columns = (
581+
self.dimension_name,
582+
"Type",
583+
"Attribute Next Year",
584+
"Attribute Previous Year",
585+
"level001_Weight",
586+
"level000_Weight",
587+
"level001",
588+
"level000",
589+
)
590+
591+
self.assertEqual((2, 8), df.shape)
592+
self.assertEqual(expected_columns, tuple(df.columns))
593+
row = df.loc[df[self.dimension_name] == "1989"]
594+
self.assertEqual(
595+
("1989", "Numeric", "", "1988", "1.000000", "1.000000", "All Years", "All Consolidations"),
596+
tuple(row.values[0]),
597+
)
598+
599+
@skip_if_no_pandas
600+
def test_get_elements_dataframe_parent_attribute(self):
601+
self.run_test_get_elements_dataframe_parent_attribute(False)
602+
603+
@skip_if_no_pandas
604+
def test_get_elements_dataframe_parent_attribute(self):
605+
self.run_test_get_elements_dataframe_parent_attribute(True)
606+
563607
def run_test_get_elements_dataframe_not_elements(self, use_blob: bool):
564608
df = self.tm1.elements.get_elements_dataframe(
565609
dimension_name=self.dimension_name,
@@ -590,6 +634,14 @@ def run_test_get_elements_dataframe_not_elements(self, use_blob: bool):
590634

591635
self.assertTrue(df.equals(reference_df))
592636

637+
@skip_if_no_pandas
638+
def test_get_elements_dataframe_not_elements(self):
639+
self.run_test_get_elements_dataframe_not_elements(use_blob=False)
640+
641+
@skip_if_no_pandas
642+
def test_get_elements_dataframe_use_blob_not_elements(self):
643+
self.run_test_get_elements_dataframe_not_elements(use_blob=True)
644+
593645
@skip_if_no_pandas
594646
def test_get_elements_dataframe_attribute_same_name(self):
595647
self.run_test_get_elements_dataframe_attribute_same_name(False)
@@ -661,13 +713,7 @@ def run_test_get_elements_dataframe_elements_via_mdx(self, use_blob: bool):
661713

662714
self.assertTrue(df.equals(reference_df))
663715

664-
@skip_if_no_pandas
665-
def test_get_elements_dataframe_not_elements(self):
666-
self.run_test_get_elements_dataframe_not_elements(use_blob=False)
667716

668-
@skip_if_no_pandas
669-
def test_get_elements_dataframe_use_blob_not_elements(self):
670-
self.run_test_get_elements_dataframe_not_elements(use_blob=True)
671717

672718
def test_get_element_names(self):
673719
element_names = self.tm1.dimensions.hierarchies.elements.get_element_names(
@@ -831,6 +877,7 @@ def test_get_all_element_identifiers(self):
831877
"1989/90",
832878
"1990/91",
833879
"1991/92",
880+
"All Years",
834881
"Total Years",
835882
"All Consolidations",
836883
*self.years,

0 commit comments

Comments
 (0)