fork download
  1. import urllib.request
  2. import urllib.error
  3. import json
  4.  
  5. # --- CONFIG ---
  6. WORKSPACE_ID = "your-workspace-id-here"
  7. DATASET_OLD = "your-old-dataset-id"
  8. DATASET_NEW = "your-new-dataset-id"
  9. ACCESS_TOKEN = "your-bearer-token"
  10. XMLA_BASE = "https://a...content-available-to-author-only...s.net/powerbi/api/v1.0/myorg/groups/{}/datasets".format(WORKSPACE_ID)
  11. THRESHOLD = 0.0001 # 0.01% delta
  12.  
  13. MEASURES = [
  14. {"name": "Total Revenue", "dax": 'EVALUATE ROW("val", [Total Revenue])'},
  15. {"name": "Gross Margin %", "dax": 'EVALUATE ROW("val", [Gross Margin %])'},
  16. {"name": "Active Customers", "dax": 'EVALUATE ROW("val", [Active Customers])'},
  17. {"name": "YoY Growth", "dax": 'EVALUATE ROW("val", [YoY Growth])'},
  18. ]
  19.  
  20. def query_dataset(dataset_id, dax_query):
  21. url = "{}/{}/executeQueries".format(XMLA_BASE, dataset_id)
  22. headers = {
  23. "Authorization": "Bearer " + ACCESS_TOKEN,
  24. "Content-Type": "application/json"
  25. }
  26. body = json.dumps({
  27. "queries": [{"query": dax_query}],
  28. "serializerSettings": {"includeNulls": True}
  29. }).encode("utf-8")
  30. req = urllib.request.Request(url, data=body, headers=headers, method="POST")
  31. try:
  32. with urllib.request.urlopen(req) as resp:
  33. data = json.loads(resp.read().decode("utf-8"))
  34. rows = data["results"][0]["tables"][0]["rows"]
  35. return rows[0]["[val]"]
  36. except (urllib.error.URLError, KeyError, IndexError):
  37. return None
  38.  
  39. def compare_measures():
  40. results = []
  41. for m in MEASURES:
  42. old_val = query_dataset(DATASET_OLD, m["dax"])
  43. new_val = query_dataset(DATASET_NEW, m["dax"])
  44.  
  45. if old_val is None or new_val is None:
  46. status = "ERROR"
  47. delta_str = "N/A"
  48. else:
  49. try:
  50. old_f = float(old_val)
  51. new_f = float(new_val)
  52. if old_f == 0:
  53. delta = abs(new_f)
  54. else:
  55. delta = abs((new_f - old_f) / old_f)
  56. status = "MISMATCH" if delta > THRESHOLD else "OK"
  57. delta_str = "{:.4%}".format(delta)
  58. except (ValueError, TypeError):
  59. delta_str = "N/A"
  60. status = "ERROR"
  61.  
  62. results.append({
  63. "measure": m["name"],
  64. "old": old_val,
  65. "new": new_val,
  66. "delta": delta_str,
  67. "status": status
  68. })
  69. return results
  70.  
  71. if __name__ == "__main__":
  72. print("=== DAX Measure Comparison ===\n")
  73. print("{:<20} {:<15} {:<15} {:<12} {}".format(
  74. "Measure", "Old Model", "New Model", "Delta", "Status"))
  75. print("-" * 75)
  76.  
  77. rows = compare_measures()
  78. mismatch_count = 0
  79. for r in rows:
  80. print("{:<20} {:<15} {:<15} {:<12} {}".format(
  81. r["measure"],
  82. str(r["old"]),
  83. str(r["new"]),
  84. r["delta"],
  85. r["status"]))
  86. if r["status"] == "MISMATCH":
  87. mismatch_count += 1
  88.  
  89. if mismatch_count > 0:
  90. print("\n! {} measure(s) exceed {:.2%} threshold".format(
  91. mismatch_count, THRESHOLD))
  92. else:
  93. print("\nAll measures within threshold")# your code goes here
Success #stdin #stdout 0.36s 24640KB
stdin
Standard input is empty
stdout
=== DAX Measure Comparison ===

Measure              Old Model       New Model       Delta        Status
---------------------------------------------------------------------------
Total Revenue        None            None            N/A          ERROR
Gross Margin %       None            None            N/A          ERROR
Active Customers     None            None            N/A          ERROR
YoY Growth           None            None            N/A          ERROR

All measures within threshold