18
18
import pathlib
19
19
import random
20
20
import re
21
- import statistics
22
21
from struct import error as StructError , pack , unpack_from
23
22
import sys
24
23
from types import CodeType , TracebackType
37
36
38
37
from awesomeversion import AwesomeVersion
39
38
import jinja2
40
- from jinja2 import pass_context , pass_environment , pass_eval_context
39
+ from jinja2 import pass_context , pass_eval_context
41
40
from jinja2 .runtime import AsyncLoopContext , LoopContext
42
41
from jinja2 .sandbox import ImmutableSandboxedEnvironment
43
42
from jinja2 .utils import Namespace
@@ -2047,121 +2046,11 @@ def returns(value):
2047
2046
return wrapper
2048
2047
2049
2048
2050
- def logarithm (value , base = math .e , default = _SENTINEL ):
2051
- """Filter and function to get logarithm of the value with a specific base."""
2052
- try :
2053
- base_float = float (base )
2054
- except (ValueError , TypeError ):
2055
- if default is _SENTINEL :
2056
- raise_no_default ("log" , base )
2057
- return default
2058
- try :
2059
- value_float = float (value )
2060
- return math .log (value_float , base_float )
2061
- except (ValueError , TypeError ):
2062
- if default is _SENTINEL :
2063
- raise_no_default ("log" , value )
2064
- return default
2065
-
2066
-
2067
- def sine (value , default = _SENTINEL ):
2068
- """Filter and function to get sine of the value."""
2069
- try :
2070
- return math .sin (float (value ))
2071
- except (ValueError , TypeError ):
2072
- if default is _SENTINEL :
2073
- raise_no_default ("sin" , value )
2074
- return default
2075
-
2076
-
2077
- def cosine (value , default = _SENTINEL ):
2078
- """Filter and function to get cosine of the value."""
2079
- try :
2080
- return math .cos (float (value ))
2081
- except (ValueError , TypeError ):
2082
- if default is _SENTINEL :
2083
- raise_no_default ("cos" , value )
2084
- return default
2085
-
2086
-
2087
- def tangent (value , default = _SENTINEL ):
2088
- """Filter and function to get tangent of the value."""
2089
- try :
2090
- return math .tan (float (value ))
2091
- except (ValueError , TypeError ):
2092
- if default is _SENTINEL :
2093
- raise_no_default ("tan" , value )
2094
- return default
2095
-
2096
-
2097
- def arc_sine (value , default = _SENTINEL ):
2098
- """Filter and function to get arc sine of the value."""
2099
- try :
2100
- return math .asin (float (value ))
2101
- except (ValueError , TypeError ):
2102
- if default is _SENTINEL :
2103
- raise_no_default ("asin" , value )
2104
- return default
2105
-
2106
-
2107
- def arc_cosine (value , default = _SENTINEL ):
2108
- """Filter and function to get arc cosine of the value."""
2109
- try :
2110
- return math .acos (float (value ))
2111
- except (ValueError , TypeError ):
2112
- if default is _SENTINEL :
2113
- raise_no_default ("acos" , value )
2114
- return default
2115
-
2116
-
2117
- def arc_tangent (value , default = _SENTINEL ):
2118
- """Filter and function to get arc tangent of the value."""
2119
- try :
2120
- return math .atan (float (value ))
2121
- except (ValueError , TypeError ):
2122
- if default is _SENTINEL :
2123
- raise_no_default ("atan" , value )
2124
- return default
2125
-
2126
-
2127
- def arc_tangent2 (* args , default = _SENTINEL ):
2128
- """Filter and function to calculate four quadrant arc tangent of y / x.
2129
-
2130
- The parameters to atan2 may be passed either in an iterable or as separate arguments
2131
- The default value may be passed either as a positional or in a keyword argument
2132
- """
2133
- try :
2134
- if 1 <= len (args ) <= 2 and isinstance (args [0 ], (list , tuple )):
2135
- if len (args ) == 2 and default is _SENTINEL :
2136
- # Default value passed as a positional argument
2137
- default = args [1 ]
2138
- args = args [0 ]
2139
- elif len (args ) == 3 and default is _SENTINEL :
2140
- # Default value passed as a positional argument
2141
- default = args [2 ]
2142
-
2143
- return math .atan2 (float (args [0 ]), float (args [1 ]))
2144
- except (ValueError , TypeError ):
2145
- if default is _SENTINEL :
2146
- raise_no_default ("atan2" , args )
2147
- return default
2148
-
2149
-
2150
2049
def version (value ):
2151
2050
"""Filter and function to get version object of the value."""
2152
2051
return AwesomeVersion (value )
2153
2052
2154
2053
2155
- def square_root (value , default = _SENTINEL ):
2156
- """Filter and function to get square root of the value."""
2157
- try :
2158
- return math .sqrt (float (value ))
2159
- except (ValueError , TypeError ):
2160
- if default is _SENTINEL :
2161
- raise_no_default ("sqrt" , value )
2162
- return default
2163
-
2164
-
2165
2054
def timestamp_custom (value , date_format = DATE_STR_FORMAT , local = True , default = _SENTINEL ):
2166
2055
"""Filter to convert given timestamp to format."""
2167
2056
try :
@@ -2315,118 +2204,6 @@ def fail_when_undefined(value):
2315
2204
return value
2316
2205
2317
2206
2318
- def min_max_from_filter (builtin_filter : Any , name : str ) -> Any :
2319
- """Convert a built-in min/max Jinja filter to a global function.
2320
-
2321
- The parameters may be passed as an iterable or as separate arguments.
2322
- """
2323
-
2324
- @pass_environment
2325
- @wraps (builtin_filter )
2326
- def wrapper (environment : jinja2 .Environment , * args : Any , ** kwargs : Any ) -> Any :
2327
- if len (args ) == 0 :
2328
- raise TypeError (f"{ name } expected at least 1 argument, got 0" )
2329
-
2330
- if len (args ) == 1 :
2331
- if isinstance (args [0 ], Iterable ):
2332
- return builtin_filter (environment , args [0 ], ** kwargs )
2333
-
2334
- raise TypeError (f"'{ type (args [0 ]).__name__ } ' object is not iterable" )
2335
-
2336
- return builtin_filter (environment , args , ** kwargs )
2337
-
2338
- return pass_environment (wrapper )
2339
-
2340
-
2341
- def average (* args : Any , default : Any = _SENTINEL ) -> Any :
2342
- """Filter and function to calculate the arithmetic mean.
2343
-
2344
- Calculates of an iterable or of two or more arguments.
2345
-
2346
- The parameters may be passed as an iterable or as separate arguments.
2347
- """
2348
- if len (args ) == 0 :
2349
- raise TypeError ("average expected at least 1 argument, got 0" )
2350
-
2351
- # If first argument is iterable and more than 1 argument provided but not a named
2352
- # default, then use 2nd argument as default.
2353
- if isinstance (args [0 ], Iterable ):
2354
- average_list = args [0 ]
2355
- if len (args ) > 1 and default is _SENTINEL :
2356
- default = args [1 ]
2357
- elif len (args ) == 1 :
2358
- raise TypeError (f"'{ type (args [0 ]).__name__ } ' object is not iterable" )
2359
- else :
2360
- average_list = args
2361
-
2362
- try :
2363
- return statistics .fmean (average_list )
2364
- except (TypeError , statistics .StatisticsError ):
2365
- if default is _SENTINEL :
2366
- raise_no_default ("average" , args )
2367
- return default
2368
-
2369
-
2370
- def median (* args : Any , default : Any = _SENTINEL ) -> Any :
2371
- """Filter and function to calculate the median.
2372
-
2373
- Calculates median of an iterable of two or more arguments.
2374
-
2375
- The parameters may be passed as an iterable or as separate arguments.
2376
- """
2377
- if len (args ) == 0 :
2378
- raise TypeError ("median expected at least 1 argument, got 0" )
2379
-
2380
- # If first argument is a list or tuple and more than 1 argument provided but not a named
2381
- # default, then use 2nd argument as default.
2382
- if isinstance (args [0 ], Iterable ):
2383
- median_list = args [0 ]
2384
- if len (args ) > 1 and default is _SENTINEL :
2385
- default = args [1 ]
2386
- elif len (args ) == 1 :
2387
- raise TypeError (f"'{ type (args [0 ]).__name__ } ' object is not iterable" )
2388
- else :
2389
- median_list = args
2390
-
2391
- try :
2392
- return statistics .median (median_list )
2393
- except (TypeError , statistics .StatisticsError ):
2394
- if default is _SENTINEL :
2395
- raise_no_default ("median" , args )
2396
- return default
2397
-
2398
-
2399
- def statistical_mode (* args : Any , default : Any = _SENTINEL ) -> Any :
2400
- """Filter and function to calculate the statistical mode.
2401
-
2402
- Calculates mode of an iterable of two or more arguments.
2403
-
2404
- The parameters may be passed as an iterable or as separate arguments.
2405
- """
2406
- if not args :
2407
- raise TypeError ("statistical_mode expected at least 1 argument, got 0" )
2408
-
2409
- # If first argument is a list or tuple and more than 1 argument provided but not a named
2410
- # default, then use 2nd argument as default.
2411
- if len (args ) == 1 and isinstance (args [0 ], Iterable ):
2412
- mode_list = args [0 ]
2413
- elif isinstance (args [0 ], list | tuple ):
2414
- mode_list = args [0 ]
2415
- if len (args ) > 1 and default is _SENTINEL :
2416
- default = args [1 ]
2417
- elif len (args ) == 1 :
2418
- raise TypeError (f"'{ type (args [0 ]).__name__ } ' object is not iterable" )
2419
- else :
2420
- mode_list = args
2421
-
2422
- try :
2423
- return statistics .mode (mode_list )
2424
- except (TypeError , statistics .StatisticsError ):
2425
- if default is _SENTINEL :
2426
- raise_no_default ("statistical_mode" , args )
2427
- return default
2428
-
2429
-
2430
2207
def forgiving_float (value , default = _SENTINEL ):
2431
2208
"""Try to convert value to a float."""
2432
2209
try :
@@ -2549,21 +2326,6 @@ def regex_findall(value, find="", ignorecase=False):
2549
2326
return _regex_cache (find , flags ).findall (value )
2550
2327
2551
2328
2552
- def bitwise_and (first_value , second_value ):
2553
- """Perform a bitwise and operation."""
2554
- return first_value & second_value
2555
-
2556
-
2557
- def bitwise_or (first_value , second_value ):
2558
- """Perform a bitwise or operation."""
2559
- return first_value | second_value
2560
-
2561
-
2562
- def bitwise_xor (first_value , second_value ):
2563
- """Perform a bitwise xor operation."""
2564
- return first_value ^ second_value
2565
-
2566
-
2567
2329
def struct_pack (value : Any | None , format_string : str ) -> bytes | None :
2568
2330
"""Pack an object into a bytes object."""
2569
2331
try :
@@ -3065,45 +2827,29 @@ def __init__(
3065
2827
self .add_extension ("jinja2.ext.do" )
3066
2828
self .add_extension ("homeassistant.helpers.template.extensions.Base64Extension" )
3067
2829
self .add_extension ("homeassistant.helpers.template.extensions.CryptoExtension" )
2830
+ self .add_extension ("homeassistant.helpers.template.extensions.MathExtension" )
3068
2831
3069
- self .globals ["acos" ] = arc_cosine
3070
2832
self .globals ["as_datetime" ] = as_datetime
3071
2833
self .globals ["as_function" ] = as_function
3072
2834
self .globals ["as_local" ] = dt_util .as_local
3073
2835
self .globals ["as_timedelta" ] = as_timedelta
3074
2836
self .globals ["as_timestamp" ] = forgiving_as_timestamp
3075
- self .globals ["asin" ] = arc_sine
3076
- self .globals ["atan" ] = arc_tangent
3077
- self .globals ["atan2" ] = arc_tangent2
3078
- self .globals ["average" ] = average
3079
2837
self .globals ["bool" ] = forgiving_boolean
3080
2838
self .globals ["combine" ] = combine
3081
- self .globals ["cos" ] = cosine
3082
2839
self .globals ["difference" ] = difference
3083
- self .globals ["e" ] = math .e
3084
2840
self .globals ["flatten" ] = flatten
3085
2841
self .globals ["float" ] = forgiving_float
3086
2842
self .globals ["iif" ] = iif
3087
2843
self .globals ["int" ] = forgiving_int
3088
2844
self .globals ["intersect" ] = intersect
3089
2845
self .globals ["is_number" ] = is_number
3090
- self .globals ["log" ] = logarithm
3091
- self .globals ["max" ] = min_max_from_filter (self .filters ["max" ], "max" )
3092
- self .globals ["median" ] = median
3093
2846
self .globals ["merge_response" ] = merge_response
3094
- self .globals ["min" ] = min_max_from_filter (self .filters ["min" ], "min" )
3095
2847
self .globals ["pack" ] = struct_pack
3096
- self .globals ["pi" ] = math .pi
3097
2848
self .globals ["set" ] = _to_set
3098
2849
self .globals ["shuffle" ] = shuffle
3099
- self .globals ["sin" ] = sine
3100
2850
self .globals ["slugify" ] = slugify
3101
- self .globals ["sqrt" ] = square_root
3102
- self .globals ["statistical_mode" ] = statistical_mode
3103
2851
self .globals ["strptime" ] = strptime
3104
2852
self .globals ["symmetric_difference" ] = symmetric_difference
3105
- self .globals ["tan" ] = tangent
3106
- self .globals ["tau" ] = math .pi * 2
3107
2853
self .globals ["timedelta" ] = timedelta
3108
2854
self .globals ["tuple" ] = _to_tuple
3109
2855
self .globals ["typeof" ] = typeof
@@ -3113,25 +2859,16 @@ def __init__(
3113
2859
self .globals ["version" ] = version
3114
2860
self .globals ["zip" ] = zip
3115
2861
3116
- self .filters ["acos" ] = arc_cosine
3117
2862
self .filters ["add" ] = add
3118
2863
self .filters ["apply" ] = apply
3119
2864
self .filters ["as_datetime" ] = as_datetime
3120
2865
self .filters ["as_function" ] = as_function
3121
2866
self .filters ["as_local" ] = dt_util .as_local
3122
2867
self .filters ["as_timedelta" ] = as_timedelta
3123
2868
self .filters ["as_timestamp" ] = forgiving_as_timestamp
3124
- self .filters ["asin" ] = arc_sine
3125
- self .filters ["atan" ] = arc_tangent
3126
- self .filters ["atan2" ] = arc_tangent2
3127
- self .filters ["average" ] = average
3128
- self .filters ["bitwise_and" ] = bitwise_and
3129
- self .filters ["bitwise_or" ] = bitwise_or
3130
- self .filters ["bitwise_xor" ] = bitwise_xor
3131
2869
self .filters ["bool" ] = forgiving_boolean
3132
2870
self .filters ["combine" ] = combine
3133
2871
self .filters ["contains" ] = contains
3134
- self .filters ["cos" ] = cosine
3135
2872
self .filters ["difference" ] = difference
3136
2873
self .filters ["flatten" ] = flatten
3137
2874
self .filters ["float" ] = forgiving_float_filter
@@ -3142,8 +2879,6 @@ def __init__(
3142
2879
self .filters ["intersect" ] = intersect
3143
2880
self .filters ["is_defined" ] = fail_when_undefined
3144
2881
self .filters ["is_number" ] = is_number
3145
- self .filters ["log" ] = logarithm
3146
- self .filters ["median" ] = median
3147
2882
self .filters ["multiply" ] = multiply
3148
2883
self .filters ["ord" ] = ord
3149
2884
self .filters ["ordinal" ] = ordinal
@@ -3156,12 +2891,8 @@ def __init__(
3156
2891
self .filters ["regex_search" ] = regex_search
3157
2892
self .filters ["round" ] = forgiving_round
3158
2893
self .filters ["shuffle" ] = shuffle
3159
- self .filters ["sin" ] = sine
3160
2894
self .filters ["slugify" ] = slugify
3161
- self .filters ["sqrt" ] = square_root
3162
- self .filters ["statistical_mode" ] = statistical_mode
3163
2895
self .filters ["symmetric_difference" ] = symmetric_difference
3164
- self .filters ["tan" ] = tangent
3165
2896
self .filters ["timestamp_custom" ] = timestamp_custom
3166
2897
self .filters ["timestamp_local" ] = timestamp_local
3167
2898
self .filters ["timestamp_utc" ] = timestamp_utc
0 commit comments