Skip to content

Commit 83a5330

Browse files
committed
fix: update changelog output and pytest golden output to match it
1 parent ec19b15 commit 83a5330

2 files changed

Lines changed: 407 additions & 402 deletions

File tree

mitreattack/diffStix/changelog_helper.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ class DomainStatistics:
6161
software: int
6262
campaigns: int
6363
mitigations: int
64+
assets: int
6465
datasources: int
65-
assets: int = 0
66+
detectionstrategies: int
67+
analytics: int
68+
datacomponents: int
6669

6770
def format_output(self) -> str:
6871
"""
@@ -79,23 +82,26 @@ def format_output(self) -> str:
7982
(self.techniques, "Techniques"),
8083
(self.subtechniques, "Sub-Techniques"),
8184
(self.groups, "Groups"),
82-
(self.software, "Pieces of Software"),
85+
(self.software, "Software"),
8386
(self.campaigns, "Campaigns"),
8487
(self.mitigations, "Mitigations"),
8588
(self.assets, "Assets"),
8689
(self.datasources, "Data Sources"),
90+
(self.detectionstrategies, "Detection Strategies"),
91+
(self.analytics, "Analytics"),
92+
(self.datacomponents, "Data Components"),
8793
]
8894

8995
# Build parts list, only including items with count > 0
9096
parts = [f"{count} {label}" for count, label in stats if count > 0]
9197

9298
# Join all parts with proper formatting
9399
if len(parts) == 0:
94-
return f"- {self.name}: No objects"
100+
return f"* {self.name}: No objects"
95101
elif len(parts) == 1:
96-
return f"- {self.name}: {parts[0]}"
102+
return f"* {self.name}: {parts[0]}"
97103
else:
98-
return f"- {self.name}: {', '.join(parts[:-1])}, and {parts[-1]}"
104+
return f"* {self.name}: {', '.join(parts[:-1])}, and {parts[-1]}"
99105

100106

101107
# TODO: Implement a custom decoder as well. Possible solution at this link
@@ -1079,23 +1085,11 @@ def _collect_domain_statistics(self, datastore: MemoryStore, domain_name: str) -
10791085
software = data.get_software(remove_revoked_deprecated=True)
10801086
campaigns = data.get_campaigns(remove_revoked_deprecated=True)
10811087
mitigations = data.get_mitigations(remove_revoked_deprecated=True)
1082-
1083-
# Try to get datasources - may fail on test data with STIX version mismatches
1084-
datasources = []
1085-
try:
1086-
datasources = data.get_datasources(remove_revoked_deprecated=True)
1087-
except Exception:
1088-
# Silently skip datasources if there are STIX version issues
1089-
pass
1090-
1091-
# ICS domain has assets
1092-
assets = 0
1093-
if domain_name == "ICS":
1094-
try:
1095-
assets = len(data.get_assets(remove_revoked_deprecated=True))
1096-
except Exception:
1097-
# Silently skip assets if there are STIX version issues
1098-
pass
1088+
assets = data.get_assets(remove_revoked_deprecated=True)
1089+
datasources = data.get_datasources(remove_revoked_deprecated=True)
1090+
detectionstrategies = data.get_detectionstrategies(remove_revoked_deprecated=True)
1091+
analytics = data.get_analytics(remove_revoked_deprecated=True)
1092+
datacomponents = data.get_datacomponents(remove_revoked_deprecated=True)
10991093

11001094
return DomainStatistics(
11011095
name=domain_name,
@@ -1106,8 +1100,11 @@ def _collect_domain_statistics(self, datastore: MemoryStore, domain_name: str) -
11061100
software=len(software),
11071101
campaigns=len(campaigns),
11081102
mitigations=len(mitigations),
1103+
assets=len(assets),
11091104
datasources=len(datasources),
1110-
assets=assets,
1105+
detectionstrategies=len(detectionstrategies),
1106+
analytics=len(analytics),
1107+
datacomponents=len(datacomponents),
11111108
)
11121109

11131110
def _collect_unique_object_counts(self, datastore_version: str) -> dict[str, int]:
@@ -1176,10 +1173,9 @@ def get_statistics_section(self, datastore_version: str = "new") -> str:
11761173
domain_stats.append(stats)
11771174

11781175
# Build the statistics section
1179-
version_label = "New" if datastore_version == "new" else "Old"
1180-
output = f"## {version_label} ATT&CK Version Statistics\n\n"
1176+
output = "## Statistics\n\n"
11811177
output += (
1182-
f"This version of ATT&CK contains {unique_counts['software']} Pieces of Software, "
1178+
f"This version of ATT&CK contains {unique_counts['software']} Software, "
11831179
f"{unique_counts['groups']} Groups, and {unique_counts['campaigns']} Campaigns.\n\n"
11841180
)
11851181
output += "Broken out by domain:\n\n"
@@ -1203,7 +1199,7 @@ def get_markdown_section_data(self, groupings, section: str, domain: str) -> str
12031199
placard_string = self.placard(stix_object=child, section=section, domain=domain)
12041200

12051201
if grouping["parentInSection"]:
1206-
sectionString += f" * {placard_string}\n"
1202+
sectionString += f" * {placard_string}\n"
12071203
else:
12081204
sectionString += f"* {grouping['parent']['name']}: {placard_string}\n"
12091205

@@ -1240,15 +1236,15 @@ def get_markdown_string(self) -> str:
12401236
logger.info("Generating markdown output")
12411237
content = ""
12421238

1243-
if self.show_key:
1244-
key_content = self.get_md_key()
1245-
content = f"{key_content}\n\n"
1246-
12471239
# Add statistics section for the new version
12481240
logger.info("Generating statistics section")
12491241
stats_section = self.get_statistics_section(datastore_version="new")
12501242
content += stats_section
12511243

1244+
if self.show_key:
1245+
key_content = self.get_md_key()
1246+
content += f"{key_content}\n"
1247+
12521248
for object_type in self.types:
12531249
domains = ""
12541250

0 commit comments

Comments
 (0)