77 - Environment: set PLOTLY_RECOMMENDATIONS=1 (or "true", "yes") to enable.
88 - In code: plotly.recommendations.config.enabled = True
99
10+ Mode: plotly.recommendations.config.mode can be "warn" (default) or "error".
11+ - "warn": emit a UserWarning when a recommendation is violated.
12+ - "error": raise RecommendationError when a recommendation is violated.
13+
1014Example:
1115 import plotly.recommendations
1216 import plotly.graph_objects as go
2125import os
2226import warnings
2327
28+ _VALID_MODES = ("warn" , "error" )
29+
30+
2431# -----------------------------------------------------------------------------
25- # Global enable/disable
32+ # Exception and config
2633# -----------------------------------------------------------------------------
2734
35+
36+ class RecommendationError (ValueError ):
37+ """Raised when a recommendation is violated and config.mode is 'error'."""
38+
39+
2840def _env_enabled ():
2941 v = os .environ .get ("PLOTLY_RECOMMENDATIONS" , "" ).strip ().lower ()
3042 return v in ("1" , "true" , "yes" , "on" )
3143
3244
45+ def _env_mode ():
46+ v = os .environ .get ("PLOTLY_RECOMMENDATIONS_MODE" , "" ).strip ().lower ()
47+ return v if v in _VALID_MODES else "warn"
48+
49+
50+
3351class _RecommendationsConfig :
3452 """
3553 Global config for recommendations mode.
3654 When enabled, recommendation checkers run after Figure/trace/Layout
37- construction and may emit warnings.
55+ construction. Use config.mode to choose "warn" ( emit warnings) or "error" (raise) .
3856 """
3957
4058 def __init__ (self ):
4159 self ._enabled = _env_enabled ()
60+ self ._mode = _env_mode ()
4261
4362 @property
4463 def enabled (self ):
@@ -48,6 +67,19 @@ def enabled(self):
4867 def enabled (self , value ):
4968 self ._enabled = bool (value )
5069
70+ @property
71+ def mode (self ):
72+ return self ._mode
73+
74+ @mode .setter
75+ def mode (self , value ):
76+ if value not in _VALID_MODES :
77+ raise ValueError (
78+ "config.mode must be one of %s, got %r" % (_VALID_MODES , value )
79+ )
80+ self ._mode = value
81+
82+
5183# Singleton used by the rest of the package
5284config = _RecommendationsConfig ()
5385
@@ -133,7 +165,7 @@ def max_length(input_list, max_length):
133165 Check if input_list has length >= max_length (e.g. recommended to keep shorter).
134166 Returns a string describing the issue, or None if no issue was found.
135167 """
136- if input_list is not None and hasattr (input_list , "__len__" ) and len (input_list ) >= max_length :
168+ if input_list is not None and hasattr (input_list , "__len__" ) and len (input_list ) > max_length :
137169 return f"has length { len (input_list )} (recommended <= { max_length } )."
138170 return None
139171
@@ -185,12 +217,13 @@ def run_recommendations(obj, context):
185217 for value_tuple in zip (* value_lists ):
186218 issue = checker (* value_tuple )
187219 if issue :
220+ msg = f"{ path_def } : { issue } "
221+ if config .mode == "error" :
222+ raise RecommendationError (msg )
188223 stacklevel = stacklevel or _get_stacklevel ()
189- warnings .warn (
190- f"{ path_def } : { issue } " ,
191- UserWarning ,
192- stacklevel = stacklevel ,
193- )
224+ warnings .warn (msg , UserWarning , stacklevel = stacklevel )
225+ except RecommendationError :
226+ raise
194227 except Exception :
195228 pass
196229
0 commit comments