Skip to content

Commit 40830fe

Browse files
authored
fixed regex escape (#464)
1 parent 3779b08 commit 40830fe

File tree

1 file changed

+26
-26
lines changed

1 file changed

+26
-26
lines changed

src/sempy_labs/_model_bpa_rules.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def model_bpa_rules(
7575
"Check if dynamic row level security (RLS) is necessary",
7676
lambda obj, tom: any(
7777
re.search(
78-
pattern, re.escape(obj.FilterExpression), flags=re.IGNORECASE
78+
pattern, obj.FilterExpression, flags=re.IGNORECASE
7979
)
8080
for pattern in ["USERPRINCIPALNAME()", "USERNAME()"]
8181
),
@@ -228,12 +228,12 @@ def model_bpa_rules(
228228
or obj.Expression.replace(" ", "").endswith("+0")
229229
or re.search(
230230
r"DIVIDE\s*\(\s*[^,]+,\s*[^,]+,\s*0\s*\)",
231-
re.escape(obj.Expression),
231+
obj.Expression,
232232
flags=re.IGNORECASE,
233233
)
234234
or re.search(
235235
r"IFERROR\s*\(\s*[^,]+,\s*0\s*\)",
236-
re.escape(obj.Expression),
236+
obj.Expression,
237237
flags=re.IGNORECASE,
238238
),
239239
"Adding 0 to a measure in order for it not to show a blank value may negatively impact performance.",
@@ -254,7 +254,7 @@ def model_bpa_rules(
254254
"Reduce usage of calculated columns that use the RELATED function",
255255
lambda obj, tom: obj.Type == TOM.ColumnType.Calculated
256256
and re.search(
257-
r"related\s*\(", re.escape(obj.Expression), flags=re.IGNORECASE
257+
r"related\s*\(", obj.Expression, flags=re.IGNORECASE
258258
),
259259
"Calculated columns do not compress as well as data columns and may cause longer processing times. As such, calculated columns should be avoided if possible. One scenario where they may be easier to avoid is if they use the RELATED function.",
260260
"https://www.sqlbi.com/articles/storage-differences-between-calculated-columns-and-calculated-tables",
@@ -310,8 +310,8 @@ def model_bpa_rules(
310310
"Warning",
311311
"Date/calendar tables should be marked as a date table",
312312
lambda obj, tom: (
313-
re.search(r"date", re.escape(obj.Name), flags=re.IGNORECASE)
314-
or re.search(r"calendar", re.escape(obj.Name), flags=re.IGNORECASE)
313+
re.search(r"date", obj.Name, flags=re.IGNORECASE)
314+
or re.search(r"calendar", obj.Name, flags=re.IGNORECASE)
315315
)
316316
and str(obj.DataCategory) != "Time",
317317
"This rule looks for tables that contain the words 'date' or 'calendar' as they should likely be marked as a date table.",
@@ -422,7 +422,7 @@ def model_bpa_rules(
422422
r"USERELATIONSHIP\s*\(\s*.+?(?=])\]\s*,\s*'*"
423423
+ re.escape(obj.Name)
424424
+ r"'*\[",
425-
re.escape(m.Expression),
425+
m.Expression,
426426
flags=re.IGNORECASE,
427427
)
428428
for m in tom.all_measures()
@@ -437,7 +437,7 @@ def model_bpa_rules(
437437
"Warning",
438438
"Avoid using the IFERROR function",
439439
lambda obj, tom: re.search(
440-
r"iferror\s*\(", re.escape(obj.Expression), flags=re.IGNORECASE
440+
r"iferror\s*\(", obj.Expression, flags=re.IGNORECASE
441441
),
442442
"Avoid using the IFERROR function as it may cause performance degradation. If you are concerned about a divide-by-zero error, use the DIVIDE function as it naturally resolves such errors as blank (or you can customize what should be shown in case of such an error).",
443443
"https://www.elegantbi.com/post/top10bestpractices",
@@ -448,7 +448,7 @@ def model_bpa_rules(
448448
"Warning",
449449
"Use the TREATAS function instead of INTERSECT for virtual relationships",
450450
lambda obj, tom: re.search(
451-
r"intersect\s*\(", re.escape(obj.Expression), flags=re.IGNORECASE
451+
r"intersect\s*\(", obj.Expression, flags=re.IGNORECASE
452452
),
453453
"The TREATAS function is more efficient and provides better performance than the INTERSECT function when used in virutal relationships.",
454454
"https://www.sqlbi.com/articles/propagate-filters-using-treatas-in-dax",
@@ -460,7 +460,7 @@ def model_bpa_rules(
460460
"The EVALUATEANDLOG function should not be used in production models",
461461
lambda obj, tom: re.search(
462462
r"evaluateandlog\s*\(",
463-
re.escape(obj.Expression),
463+
obj.Expression,
464464
flags=re.IGNORECASE,
465465
),
466466
"The EVALUATEANDLOG function is meant to be used only in development/test environments and should not be used in production models.",
@@ -482,8 +482,8 @@ def model_bpa_rules(
482482
"Warning",
483483
"No two measures should have the same definition",
484484
lambda obj, tom: any(
485-
re.sub(r"\s+", "", re.escape(obj.Expression))
486-
== re.sub(r"\s+", "", re.escape(m.Expression))
485+
re.sub(r"\s+", "", obj.Expression)
486+
== re.sub(r"\s+", "", m.Expression)
487487
and obj.Name != m.Name
488488
for m in tom.all_measures()
489489
),
@@ -496,7 +496,7 @@ def model_bpa_rules(
496496
"Avoid addition or subtraction of constant values to results of divisions",
497497
lambda obj, tom: re.search(
498498
r"DIVIDE\s*\((\s*.*?)\)\s*[+-]\s*1|\/\s*.*(?=[-+]\s*1)",
499-
re.escape(obj.Expression),
499+
obj.Expression,
500500
flags=re.IGNORECASE,
501501
),
502502
"Adding a constant value may lead to performance degradation.",
@@ -508,12 +508,12 @@ def model_bpa_rules(
508508
"Avoid using '1-(x/y)' syntax",
509509
lambda obj, tom: re.search(
510510
r"[0-9]+\s*[-+]\s*[\(]*\s*SUM\s*\(\s*\'*[A-Za-z0-9 _]+\'*\s*\[[A-Za-z0-9 _]+\]\s*\)\s*/",
511-
re.escape(obj.Expression),
511+
obj.Expression,
512512
flags=re.IGNORECASE,
513513
)
514514
or re.search(
515515
r"[0-9]+\s*[-+]\s*DIVIDE\s*\(",
516-
re.escape(obj.Expression),
516+
obj.Expression,
517517
flags=re.IGNORECASE,
518518
),
519519
"Instead of using the '1-(x/y)' or '1+(x/y)' syntax to achieve a percentage calculation, use the basic DAX functions (as shown below). Using the improved syntax will generally improve the performance. The '1+/-...' syntax always returns a value whereas the solution without the '1+/-...' does not (as the value may be 'blank'). Therefore the '1+/-...' syntax may return more rows/columns which may result in a slower query speed. Let's clarify with an example: Avoid this: 1 - SUM ( 'Sales'[CostAmount] ) / SUM( 'Sales'[SalesAmount] ) Better: DIVIDE ( SUM ( 'Sales'[SalesAmount] ) - SUM ( 'Sales'[CostAmount] ), SUM ( 'Sales'[SalesAmount] ) ) Best: VAR x = SUM ( 'Sales'[SalesAmount] ) RETURN DIVIDE ( x - SUM ( 'Sales'[CostAmount] ), x )",
@@ -525,12 +525,12 @@ def model_bpa_rules(
525525
"Filter measure values by columns, not tables",
526526
lambda obj, tom: re.search(
527527
r"CALCULATE\s*\(\s*[^,]+,\s*FILTER\s*\(\s*\'*[A-Za-z0-9 _]+\'*\s*,\s*\[[^\]]+\]",
528-
re.escape(obj.Expression),
528+
obj.Expression,
529529
flags=re.IGNORECASE,
530530
)
531531
or re.search(
532532
r"CALCULATETABLE\s*\(\s*[^,]*,\s*FILTER\s*\(\s*\'*[A-Za-z0-9 _]+\'*\s*,\s*\[",
533-
re.escape(obj.Expression),
533+
obj.Expression,
534534
flags=re.IGNORECASE,
535535
),
536536
"Instead of using this pattern FILTER('Table',[Measure]>Value) for the filter parameters of a CALCULATE or CALCULATETABLE function, use one of the options below (if possible). Filtering on a specific column will produce a smaller table for the engine to process, thereby enabling faster performance. Using the VALUES function or the ALL function depends on the desired measure result.\nOption 1: FILTER(VALUES('Table'[Column]),[Measure] > Value)\nOption 2: FILTER(ALL('Table'[Column]),[Measure] > Value)",
@@ -543,12 +543,12 @@ def model_bpa_rules(
543543
"Filter column values with proper syntax",
544544
lambda obj, tom: re.search(
545545
r"CALCULATE\s*\(\s*[^,]+,\s*FILTER\s*\(\s*'*[A-Za-z0-9 _]+'*\s*,\s*'*[A-Za-z0-9 _]+'*\[[A-Za-z0-9 _]+\]",
546-
re.escape(obj.Expression),
546+
obj.Expression,
547547
flags=re.IGNORECASE,
548548
)
549549
or re.search(
550550
r"CALCULATETABLE\s*\([^,]*,\s*FILTER\s*\(\s*'*[A-Za-z0-9 _]+'*\s*,\s*'*[A-Za-z0-9 _]+'*\[[A-Za-z0-9 _]+\]",
551-
re.escape(obj.Expression),
551+
obj.Expression,
552552
flags=re.IGNORECASE,
553553
),
554554
"Instead of using this pattern FILTER('Table','Table'[Column]=\"Value\") for the filter parameters of a CALCULATE or CALCULATETABLE function, use one of the options below. As far as whether to use the KEEPFILTERS function, see the second reference link below.\nOption 1: KEEPFILTERS('Table'[Column]=\"Value\")\nOption 2: 'Table'[Column]=\"Value\"",
@@ -561,7 +561,7 @@ def model_bpa_rules(
561561
"Use the DIVIDE function for division",
562562
lambda obj, tom: re.search(
563563
r"\]\s*\/(?!\/)(?!\*)\" or \"\)\s*\/(?!\/)(?!\*)",
564-
re.escape(obj.Expression),
564+
obj.Expression,
565565
flags=re.IGNORECASE,
566566
),
567567
'Use the DIVIDE function instead of using "/". The DIVIDE function resolves divide-by-zero cases. As such, it is recommended to use to avoid errors.',
@@ -606,7 +606,7 @@ def model_bpa_rules(
606606
+ r"'*\["
607607
+ re.escape(obj.ToColumn.Name)
608608
+ r"\]",
609-
re.escape(m.Expression),
609+
m.Expression,
610610
flags=re.IGNORECASE,
611611
)
612612
for m in tom.all_measures()
@@ -667,7 +667,7 @@ def model_bpa_rules(
667667
"Warning",
668668
"Provide format string for 'Date' columns",
669669
lambda obj, tom: (
670-
re.search(r"date", re.escape(obj.Name), flags=re.IGNORECASE)
670+
re.search(r"date", obj.Name, flags=re.IGNORECASE)
671671
)
672672
and (obj.DataType == TOM.DataType.DateTime)
673673
and (obj.FormatString != "mm/dd/yyyy"),
@@ -767,9 +767,9 @@ def model_bpa_rules(
767767
"Info",
768768
"Month (as a string) must be sorted",
769769
lambda obj, tom: (
770-
re.search(r"month", re.escape(obj.Name), flags=re.IGNORECASE)
770+
re.search(r"month", obj.Name, flags=re.IGNORECASE)
771771
)
772-
and not (re.search(r"months", re.escape(obj.Name), flags=re.IGNORECASE))
772+
and not (re.search(r"months", obj.Name, flags=re.IGNORECASE))
773773
and (obj.DataType == TOM.DataType.String)
774774
and len(str(obj.SortByColumn)) == 0,
775775
"This rule highlights month columns which are strings and are not sorted. If left unsorted, they will sort alphabetically (i.e. April, August...). Make sure to sort such columns so that they sort properly (January, February, March...).",
@@ -789,7 +789,7 @@ def model_bpa_rules(
789789
"Warning",
790790
'Provide format string for "Month" columns',
791791
lambda obj, tom: re.search(
792-
r"month", re.escape(obj.Name), flags=re.IGNORECASE
792+
r"month", obj.Name, flags=re.IGNORECASE
793793
)
794794
and obj.DataType == TOM.DataType.DateTime
795795
and obj.FormatString != "MMMM yyyy",
@@ -829,7 +829,7 @@ def model_bpa_rules(
829829
["Table", "Column", "Measure", "Partition", "Hierarchy"],
830830
"Warning",
831831
"Object names must not contain special characters",
832-
lambda obj, tom: re.search(r"[\t\r\n]", re.escape(obj.Name)),
832+
lambda obj, tom: re.search(r"[\t\r\n]", obj.Name),
833833
"Object names should not include tabs, line breaks, etc.",
834834
),
835835
],

0 commit comments

Comments
 (0)