@@ -1945,11 +1945,12 @@ def _init_child_props(self, child):
1945
1945
def _initialize_layout_template (self ):
1946
1946
import plotly .io as pio
1947
1947
1948
- if self ._layout_obj .template is None :
1948
+ if self ._layout_obj ._props . get ( " template" , None ) is None :
1949
1949
if pio .templates .default is not None :
1950
- self ._layout_obj .template = pio .templates .default
1951
- else :
1952
- self ._layout_obj .template = None
1950
+ with validate (False ):
1951
+ # Assume default template is already validated
1952
+ template_dict = pio .templates [pio .templates .default ]
1953
+ self ._layout_obj .template = template_dict
1953
1954
1954
1955
@property
1955
1956
def layout (self ):
@@ -3019,6 +3020,47 @@ def __init__(self, plotly_name, **kwargs):
3019
3020
# properties is modified
3020
3021
self ._change_callbacks = {}
3021
3022
3023
+ # ### Backing property for backward compatible _validator property ##
3024
+ self .__validators = None
3025
+
3026
+ def _get_validator (self , prop ):
3027
+ from .validator_cache import ValidatorCache
3028
+
3029
+ return ValidatorCache .get_validator (self ._path_str , prop )
3030
+
3031
+ @property
3032
+ def _validators (self ):
3033
+ """
3034
+ Validators used to be stored in a private _validators property. This was
3035
+ eliminated when we switched to building validators on demand using the
3036
+ _get_validator method.
3037
+
3038
+ This property returns a simple object that
3039
+
3040
+ Returns
3041
+ -------
3042
+ dict-like interface for accessing the object's validators
3043
+ """
3044
+ obj = self
3045
+ if self .__validators is None :
3046
+
3047
+ class ValidatorCompat (object ):
3048
+ def __getitem__ (self , item ):
3049
+ return obj ._get_validator (item )
3050
+
3051
+ def __contains__ (self , item ):
3052
+ return obj .__contains__ (item )
3053
+
3054
+ def __iter__ (self ):
3055
+ return iter (obj )
3056
+
3057
+ def items (self ):
3058
+ return [(k , self [k ]) for k in self ]
3059
+
3060
+ self .__validators = ValidatorCompat ()
3061
+
3062
+ return self .__validators
3063
+
3022
3064
def _process_kwargs (self , ** kwargs ):
3023
3065
"""
3024
3066
Process any extra kwargs that are not predefined as constructor params
@@ -3122,21 +3164,30 @@ def _get_child_props(self, child):
3122
3164
return None
3123
3165
else :
3124
3166
# ### Child a compound property ###
3125
- if child .plotly_name in self ._compound_props :
3126
- return self ._props .get (child .plotly_name , None )
3167
+ if child .plotly_name in self :
3168
+ from _plotly_utils .basevalidators import (
3169
+ CompoundValidator ,
3170
+ CompoundArrayValidator ,
3171
+ )
3127
3172
3128
- # ### Child an element of a compound array property ###
3129
- elif child .plotly_name in self ._compound_array_props :
3130
- children = self ._compound_array_props [child .plotly_name ]
3131
- child_ind = BaseFigure ._index_is (children , child )
3132
- assert child_ind is not None
3173
+ validator = self ._get_validator (child .plotly_name )
3133
3174
3134
- children_props = self ._props .get (child .plotly_name , None )
3135
- return (
3136
- children_props [child_ind ]
3137
- if children_props is not None and len (children_props ) > child_ind
3138
- else None
3139
- )
3175
+ if isinstance (validator , CompoundValidator ):
3176
+ return self ._props .get (child .plotly_name , None )
3177
+
3178
+ # ### Child an element of a compound array property ###
3179
+ elif isinstance (validator , CompoundArrayValidator ):
3180
+ children = self [child .plotly_name ]
3181
+ child_ind = BaseFigure ._index_is (children , child )
3182
+ assert child_ind is not None
3183
+
3184
+ children_props = self ._props .get (child .plotly_name , None )
3185
+ return (
3186
+ children_props [child_ind ]
3187
+ if children_props is not None
3188
+ and len (children_props ) > child_ind
3189
+ else None
3190
+ )
3140
3191
3141
3192
# ### Invalid child ###
3142
3193
else :
@@ -3282,7 +3333,7 @@ def _get_prop_validator(self, prop):
3282
3333
3283
3334
# Return validator
3284
3335
# ----------------
3285
- return plotly_obj ._validators [ prop ]
3336
+ return plotly_obj ._get_validator ( prop )
3286
3337
3287
3338
@property
3288
3339
def parent (self ):
@@ -3344,6 +3395,11 @@ def __getitem__(self, prop):
3344
3395
-------
3345
3396
Any
3346
3397
"""
3398
+ from _plotly_utils .basevalidators import (
3399
+ CompoundValidator ,
3400
+ CompoundArrayValidator ,
3401
+ BaseDataValidator ,
3402
+ )
3347
3403
3348
3404
# Normalize prop
3349
3405
# --------------
@@ -3361,13 +3417,33 @@ def __getitem__(self, prop):
3361
3417
if len (prop ) == 1 :
3362
3418
# Unwrap scalar tuple
3363
3419
prop = prop [0 ]
3364
- if prop not in self ._validators :
3420
+ if prop not in self ._valid_props :
3365
3421
raise KeyError (prop )
3366
3422
3367
- validator = self ._validators [prop ]
3368
- if prop in self ._compound_props :
3423
+ validator = self ._get_validator (prop )
3424
+
3425
+ if isinstance (validator , CompoundValidator ):
3426
+ if self ._compound_props .get (prop , None ) is None :
3427
+ # Init compound objects
3428
+ self ._compound_props [prop ] = validator .data_class (
3429
+ _parent = self , plotly_name = prop
3430
+ )
3431
+ # Update plotly_name value in case the validator applies
3432
+ # non-standard name (e.g. imagedefaults instead of image)
3433
+ self ._compound_props [prop ]._plotly_name = prop
3434
+
3369
3435
return validator .present (self ._compound_props [prop ])
3370
- elif prop in self ._compound_array_props :
3436
+ elif isinstance (validator , (CompoundArrayValidator , BaseDataValidator )):
3437
+ if self ._compound_array_props .get (prop , None ) is None :
3438
+ # Init list of compound objects
3439
+ if self ._props is not None :
3440
+ self ._compound_array_props [prop ] = [
3441
+ validator .data_class (_parent = self )
3442
+ for _ in self ._props .get (prop , [])
3443
+ ]
3444
+ else :
3445
+ self ._compound_array_props [prop ] = []
3446
+
3371
3447
return validator .present (self ._compound_array_props [prop ])
3372
3448
elif self ._props is not None and prop in self ._props :
3373
3449
return validator .present (self ._props [prop ])
@@ -3422,7 +3498,7 @@ def __contains__(self, prop):
3422
3498
else :
3423
3499
return False
3424
3500
else :
3425
- if obj is not None and p in obj ._validators :
3501
+ if obj is not None and p in obj ._valid_props :
3426
3502
obj = obj [p ]
3427
3503
else :
3428
3504
return False
@@ -3445,6 +3521,11 @@ def __setitem__(self, prop, value):
3445
3521
-------
3446
3522
None
3447
3523
"""
3524
+ from _plotly_utils .basevalidators import (
3525
+ CompoundValidator ,
3526
+ CompoundArrayValidator ,
3527
+ BaseDataValidator ,
3528
+ )
3448
3529
3449
3530
# Normalize prop
3450
3531
# --------------
@@ -3511,7 +3592,7 @@ def __setattr__(self, prop, value):
3511
3592
-------
3512
3593
None
3513
3594
"""
3514
- if prop .startswith ("_" ) or hasattr (self , prop ) or prop in self ._validators :
3595
+ if prop .startswith ("_" ) or hasattr (self , prop ) or prop in self ._valid_props :
3515
3596
# Let known properties and private properties through
3516
3597
super (BasePlotlyType , self ).__setattr__ (prop , value )
3517
3598
else :
@@ -3522,7 +3603,7 @@ def __iter__(self):
3522
3603
"""
3523
3604
Return an iterator over the object's properties
3524
3605
"""
3525
- res = list (self ._validators . keys () )
3606
+ res = list (self ._valid_props )
3526
3607
for prop in self ._mapped_properties :
3527
3608
res .append (prop )
3528
3609
return iter (res )
@@ -3605,8 +3686,8 @@ def __repr__(self):
3605
3686
props = {
3606
3687
p : v
3607
3688
for p , v in props .items ()
3608
- if p in self ._validators
3609
- and not isinstance (self ._validators [ p ] , LiteralValidator )
3689
+ if p in self ._valid_props
3690
+ and not isinstance (self ._get_validator ( p ) , LiteralValidator )
3610
3691
}
3611
3692
3612
3693
# Elide template
@@ -3767,7 +3848,8 @@ def _set_prop(self, prop, val):
3767
3848
3768
3849
# Import value
3769
3850
# ------------
3770
- validator = self ._validators .get (prop )
3851
+ validator = self ._get_validator (prop )
3852
+
3771
3853
try :
3772
3854
val = validator .validate_coerce (val )
3773
3855
except ValueError as err :
@@ -3832,7 +3914,7 @@ def _set_compound_prop(self, prop, val):
3832
3914
3833
3915
# Import value
3834
3916
# ------------
3835
- validator = self ._validators . get (prop )
3917
+ validator = self ._get_validator (prop )
3836
3918
val = validator .validate_coerce (val , skip_invalid = self ._skip_invalid )
3837
3919
3838
3920
# Save deep copies of current and new states
@@ -3906,7 +3988,7 @@ def _set_array_prop(self, prop, val):
3906
3988
3907
3989
# Import value
3908
3990
# ------------
3909
- validator = self ._validators . get (prop )
3991
+ validator = self ._get_validator (prop )
3910
3992
val = validator .validate_coerce (val , skip_invalid = self ._skip_invalid )
3911
3993
3912
3994
# Save deep copies of current and new states
@@ -4331,10 +4413,8 @@ def _set_subplotid_prop(self, prop, value):
4331
4413
4332
4414
# Construct and add validator
4333
4415
# ---------------------------
4334
- if prop not in self ._validators :
4335
- validator_class = self ._subplotid_validators [subplot_prop ]
4336
- validator = validator_class (plotly_name = prop )
4337
- self ._validators [prop ] = validator
4416
+ if prop not in self ._valid_props :
4417
+ self ._valid_props .add (prop )
4338
4418
4339
4419
# Import value
4340
4420
# ------------
@@ -4395,7 +4475,7 @@ def __getattr__(self, prop):
4395
4475
"""
4396
4476
prop = self ._strip_subplot_suffix_of_1 (prop )
4397
4477
if prop != "_subplotid_props" and prop in self ._subplotid_props :
4398
- validator = self ._validators [ prop ]
4478
+ validator = self ._get_validator ( prop )
4399
4479
return validator .present (self ._compound_props [prop ])
4400
4480
else :
4401
4481
return super (BaseLayoutHierarchyType , self ).__getattribute__ (prop )
0 commit comments