@@ -472,12 +472,21 @@ class Style:
472472 "target" : "_top" ,
473473 }
474474
475- def __init__ (self , ** kw ):
475+ def __init__ (self , _prototype : "Style" = None , ** kw ):
476476 """
477477 Deep-copy class-attributes (to avoid sideffects) and apply user-overrides,
478478
479479 retargeting any :class:`Ref` on my self (from class's 'values).
480+
481+ :param _prototype:
482+ If given, class-attributes are ignored, deep-copying "public" properties
483+ only from this instance (and apply on top any `kw`).
480484 """
485+ if _prototype is None :
486+ _prototype = type (self )
487+ else :
488+ assert isinstance (_prototype , Style ), _prototype
489+
481490 values = {
482491 k : v
483492 for k , v in vars (type (self )).items ()
@@ -515,6 +524,10 @@ def remap_item(path, k, v):
515524 values = vars (self )
516525 vars (self ).update (remap (values , remap_item ))
517526
527+ def with_set (self , ** kw ) -> "Style" :
528+ """Returns a deep-clone modified by `kw`."""
529+ return type (self )(_prototype = self , ** kw )
530+
518531
519532class Plotter :
520533 """
@@ -526,14 +539,16 @@ class Plotter:
526539 controlling theming values & dictionaries for plots.
527540 """
528541
529- def __init__ (self , style = None ):
530- self .style = style or Style ()
542+ def __init__ (self , style : Style = None ):
543+ self .style : Style = style or Style ()
531544
532- def copy (self ) -> "Plotter" :
533- """deep copy of all styles"""
534- clone = type (self )(self .style )
535- clone .__dict__ = remap (vars (self ), lambda * a : True )
536- return clone
545+ def with_styles (self , ** kw ) -> "Plotter" :
546+ """
547+ Returns a cloned plotter with deep-coped styles modified as given.
548+
549+ See also :meth:`Style.with_set()`.
550+ """
551+ return type (self )(self .style .with_set (** kw ))
537552
538553 def plot (self , plot_args : PlotArgs ):
539554 dot = self .build_pydot (plot_args )
0 commit comments