@@ -171,10 +171,15 @@ class Config(contextlib.ContextDecorator):
171171 ... pass
172172 """
173173
174+ _context_options : ConfigParameters | None = None
174175 _original_state : str = ""
175176
176177 def __init__ (
177- self , * , restore_defaults : bool = False , ** options : Unpack [ConfigParameters ]
178+ self ,
179+ * ,
180+ restore_defaults : bool = False ,
181+ apply_on_context_enter : bool = False ,
182+ ** options : Unpack [ConfigParameters ],
178183 ) -> None :
179184 """
180185 Initialise a Config object instance for context manager usage.
@@ -187,12 +192,19 @@ def __init__(
187192 restore_defaults
188193 set all options to their default values (this is applied before
189194 setting any other options).
195+ apply_on_context_enter
196+ defer applying the options until a context is entered. This allows you
197+ to create multiple `Config` instances with different options, and then
198+ reuse them independently as context managers or function decorators
199+ with specific bundles of parameters.
190200 **options
191201 keyword args that will set the option; equivalent to calling the
192202 named "set_<option>" method with the given value.
193203
194204 Examples
195205 --------
206+ Customise Polars table formatting while in context scope:
207+
196208 >>> df = pl.DataFrame({"abc": [1.0, 2.5, 5.0], "xyz": [True, False, True]})
197209 >>> with pl.Config(
198210 ... # these options will be set for scope duration
@@ -208,24 +220,51 @@ def __init__(
208220 | 1.0 | true |
209221 | 2.5 | false |
210222 | 5.0 | true |
223+
224+ Establish several independent Config instances for use in different contexts;
225+ setting `apply_on_context_enter=True` defers setting the parameters until a
226+ context (or function, when used as a decorator) is actually entered:
227+
228+ >>> cfg_polars_verbose = pl.Config(
229+ ... verbose=True,
230+ ... apply_on_context_enter=True,
231+ ... )
232+ >>> cfg_polars_detailed_tables = pl.Config(
233+ ... tbl_rows=25,
234+ ... tbl_cols=25,
235+ ... tbl_width_chars=200,
236+ ... apply_on_context_enter=True,
237+ ... )
238+
239+ These Config instances can now be applied independently and re-used:
240+
241+ >>> @cfg_polars_verbose
242+ ... def traced_function(df: pl.DataFrame) -> pl.DataFrame:
243+ ... return polars_operations(df)
244+
245+ >>> @cfg_polars_detailed_tables
246+ ... def print_detailed_frames(*frames: pl.DataFrame) -> None:
247+ ... for df in frames:
248+ ... print(df)
211249 """
212250 # save original state _before_ any changes are made
213251 self ._original_state = self .save ()
214-
215252 if restore_defaults :
216253 self .restore_defaults ()
217254
218- for opt , value in options . items () :
219- if not hasattr ( self , opt ) and not opt . startswith ( "set_" ):
220- opt = f"set_ { opt } "
221- if not hasattr ( self , opt ) :
222- msg = f"`Config` has no option { opt !r } "
223- raise AttributeError ( msg )
224- getattr ( self , opt )( value )
255+ if apply_on_context_enter :
256+ # defer setting options; apply only on entering a new context
257+ self . _context_options = options
258+ else :
259+ # apply the given options immediately
260+ self . _set_config_params ( ** options )
261+ self . _context_options = None
225262
226263 def __enter__ (self ) -> Self :
227- """Support setting temporary Config options that are reset on scope exit."""
264+ """Support setting Config options that are reset on scope exit."""
228265 self ._original_state = self ._original_state or self .save ()
266+ if self ._context_options :
267+ self ._set_config_params (** self ._context_options )
229268 return self
230269
231270 def __exit__ (
@@ -238,6 +277,25 @@ def __exit__(
238277 self .restore_defaults ().load (self ._original_state )
239278 self ._original_state = ""
240279
280+ def __eq__ (self , other : object ) -> bool :
281+ if not isinstance (other , Config ):
282+ return False
283+ return (self ._original_state == other ._original_state ) and (
284+ self ._context_options == other ._context_options
285+ )
286+
287+ def __ne__ (self , other : object ) -> bool :
288+ return not self .__eq__ (other )
289+
290+ def _set_config_params (self , ** options : Unpack [ConfigParameters ]) -> None :
291+ for opt , value in options .items ():
292+ if not hasattr (self , opt ) and not opt .startswith ("set_" ):
293+ opt = f"set_{ opt } "
294+ if not hasattr (self , opt ):
295+ msg = f"`Config` has no option { opt !r} "
296+ raise AttributeError (msg )
297+ getattr (self , opt )(value )
298+
241299 @classmethod
242300 def load (cls , cfg : str ) -> Config :
243301 """
@@ -251,7 +309,7 @@ def load(cls, cfg: str) -> Config:
251309 See Also
252310 --------
253311 load_from_file : Load (and set) Config options from a JSON file.
254- save: Save the current set of Config options as a JSON string or file.
312+ save : Save the current set of Config options as a JSON string or file.
255313 """
256314 try :
257315 options = json .loads (cfg )
@@ -285,7 +343,7 @@ def load_from_file(cls, file: Path | str) -> Config:
285343 See Also
286344 --------
287345 load : Load (and set) Config options from a JSON string.
288- save: Save the current set of Config options as a JSON string or file.
346+ save : Save the current set of Config options as a JSON string or file.
289347 """
290348 try :
291349 options = Path (normalize_filepath (file )).read_text ()
@@ -389,7 +447,7 @@ def state(
389447 cls , * , if_set : bool = False , env_only : bool = False
390448 ) -> dict [str , str | None ]:
391449 """
392- Show the current state of all Config variables as a dict.
450+ Show the current state of all Config variables in the environment as a dict.
393451
394452 Parameters
395453 ----------
@@ -422,7 +480,11 @@ def set_ascii_tables(cls, active: bool | None = True) -> type[Config]:
422480 """
423481 Use ASCII characters to display table outlines.
424482
425- Set False to revert to the default UTF8_FULL_CONDENSED formatting style.
483+ Set False to revert to the standard UTF8_FULL_CONDENSED formatting style.
484+
485+ See Also
486+ --------
487+ set_tbl_formatting : Set the table formatting style (includes Markdown option).
426488
427489 Examples
428490 --------
@@ -969,7 +1031,7 @@ def set_tbl_column_data_type_inline(
9691031 cls , active : bool | None = True
9701032 ) -> type [Config ]:
9711033 """
972- Moves the data type inline with the column name (to the right, in parentheses).
1034+ Display the data type next to the column name (to the right, in parentheses).
9731035
9741036 Examples
9751037 --------
@@ -1151,11 +1213,11 @@ def set_tbl_hide_column_names(cls, active: bool | None = True) -> type[Config]:
11511213 @classmethod
11521214 def set_tbl_hide_dtype_separator (cls , active : bool | None = True ) -> type [Config ]:
11531215 """
1154- Hide the '---' separator between the column names and column types.
1216+ Hide the '---' separator displayed between the column names and column types.
11551217
11561218 See Also
11571219 --------
1158- set_tbl_column_data_type_inline
1220+ set_tbl_column_data_type_inline : Display the data type inline with the colname.
11591221
11601222 Examples
11611223 --------
0 commit comments