@@ -229,7 +229,7 @@ def get_attributes_dicts(object_name, parent_object_names=()):
229
229
return attributes_dicts
230
230
231
231
232
- def get_valid_attributes (object_name , parent_object_names = () ):
232
+ def _get_valid_attributes (object_name , parent_object_names ):
233
233
attributes = get_attributes_dicts (object_name , parent_object_names )
234
234
# These are for documentation and quick lookups. They're just strings.
235
235
valid_attributes = set ()
@@ -245,6 +245,11 @@ def get_valid_attributes(object_name, parent_object_names=()):
245
245
return valid_attributes
246
246
247
247
248
+ def get_valid_attributes (object_name , parent_object_names = ()):
249
+ # Enforce that parent_object_names is hashable (a tuple).
250
+ return _get_valid_attributes (object_name , tuple (parent_object_names ))
251
+
252
+
248
253
def get_deprecated_attributes (object_name , parent_object_names = ()):
249
254
attributes = get_attributes_dicts (object_name , parent_object_names )
250
255
# These are for documentation and quick lookups. They're just strings.
@@ -340,21 +345,9 @@ def attribute_path_to_object_names(attribute_container_path):
340
345
return tuple (object_names )
341
346
342
347
343
- def get_role (object_name , attribute , value = None , parent_object_names = ()):
344
- """
345
- Values have types associated with them based on graph_reference.
346
-
347
- 'data' type values are always kept
348
- 'style' values are kept if they're sequences (but not strings)
349
-
350
- :param (str) object_name: The name of the object containing 'attribute'.
351
- :param (str) attribute: The attribute we want the `role` of.
352
- :param (*) value: If the value is an array, the return can be different.
353
- :param parent_object_names: An iterable of obj names from graph reference.
354
- :returns: (str) This will be 'data', 'style', or 'info'.
355
-
356
- """
357
- if object_name in TRACE_NAMES and attribute == 'type' :
348
+ def _get_role (object_name , attribute , value_type , parent_object_names = ()):
349
+ """Private, more easily memoized version of get_role."""
350
+ if attribute == 'type' and object_name in TRACE_NAMES :
358
351
return 'info'
359
352
attributes_dicts = get_attributes_dicts (object_name , parent_object_names )
360
353
matches = []
@@ -372,12 +365,8 @@ def get_role(object_name, attribute, value=None, parent_object_names=()):
372
365
for match in matches :
373
366
role = match ['role' ]
374
367
array_ok = match .get ('arrayOk' )
375
- if value is not None and array_ok :
376
- iterable = hasattr (value , '__iter__' )
377
- stringy = isinstance (value , six .string_types )
378
- dicty = isinstance (value , dict )
379
- if iterable and not stringy and not dicty :
380
- role = 'data'
368
+ if array_ok and value_type == 'array' :
369
+ role = 'data'
381
370
roles .append (role )
382
371
383
372
# TODO: this is ambiguous until the figure is in place...
@@ -388,6 +377,36 @@ def get_role(object_name, attribute, value=None, parent_object_names=()):
388
377
return role
389
378
390
379
380
+ def get_role (object_name , attribute , value = None , parent_object_names = ()):
381
+ """
382
+ Values have types associated with them based on graph_reference.
383
+
384
+ 'data' type values are always kept
385
+ 'style' values are kept if they're sequences (but not strings)
386
+
387
+ :param (str) object_name: The name of the object containing 'attribute'.
388
+ :param (str) attribute: The attribute we want the `role` of.
389
+ :param (*) value: If the value is an array, the return can be different.
390
+ :param parent_object_names: An iterable of obj names from graph reference.
391
+ :returns: (str) This will be 'data', 'style', or 'info'.
392
+
393
+ """
394
+ if value is None :
395
+ value_type = 'none'
396
+ elif isinstance (value , dict ):
397
+ value_type = 'dict'
398
+ elif isinstance (value , six .string_types ):
399
+ value_type = 'string'
400
+ elif hasattr (value , '__iter__' ):
401
+ value_type = 'array'
402
+ else :
403
+ value_type = 'unknown'
404
+
405
+ # Enforce that parent_object_names is hashable (a tuple).
406
+ return _get_role (object_name , attribute , value_type ,
407
+ tuple (parent_object_names ))
408
+
409
+
391
410
def _is_valid_sub_path (path , parent_paths ):
392
411
"""
393
412
Check if a sub path is valid given an iterable of parent paths.
0 commit comments