Skip to content

Commit 380f7fc

Browse files
committed
Added dict-style pop method to Figure and graph objects
1 parent b55c3f8 commit 380f7fc

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

Diff for: packages/python/plotly/plotly/basedatatypes.py

+66
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,37 @@ def update(self, dict1=None, **kwargs):
498498
self[k] = v
499499
return self
500500

501+
def pop(self, key, *args):
502+
"""
503+
Remove the value associated with the specified key and return it
504+
505+
Parameters
506+
----------
507+
key: str
508+
Property name
509+
dflt
510+
The default value to return if key was not found in figure
511+
512+
Returns
513+
-------
514+
value
515+
The removed value that was previously associated with key
516+
517+
Raises
518+
------
519+
KeyError
520+
If key is not in object and no dflt argument specified
521+
"""
522+
# Handle default
523+
if key not in self and args:
524+
return args[0]
525+
elif key in self:
526+
val = self[key]
527+
self[key] = None
528+
return val
529+
else:
530+
raise KeyError(key)
531+
501532
# Data
502533
# ----
503534
@property
@@ -520,6 +551,10 @@ def data(self, new_data):
520551
'a list or tuple that contains a permutation of a '
521552
'subset of itself.\n')
522553

554+
# ### Treat None as empty ###
555+
if new_data is None:
556+
new_data = ()
557+
523558
# ### Check valid input type ###
524559
if not isinstance(new_data, (list, tuple)):
525560
err_msg = (err_header + ' Received value with type {typ}'
@@ -3503,6 +3538,37 @@ def update(self, dict1=None, **kwargs):
35033538

35043539
return self
35053540

3541+
def pop(self, key, *args):
3542+
"""
3543+
Remove the value associated with the specified key and return it
3544+
3545+
Parameters
3546+
----------
3547+
key: str
3548+
Property name
3549+
dflt
3550+
The default value to return if key was not found in object
3551+
3552+
Returns
3553+
-------
3554+
value
3555+
The removed value that was previously associated with key
3556+
3557+
Raises
3558+
------
3559+
KeyError
3560+
If key is not in object and no dflt argument specified
3561+
"""
3562+
# Handle default
3563+
if key not in self and args:
3564+
return args[0]
3565+
elif key in self:
3566+
val = self[key]
3567+
self[key] = None
3568+
return val
3569+
else:
3570+
raise KeyError(key)
3571+
35063572
@property
35073573
def _in_batch_mode(self):
35083574
"""

Diff for: packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_figure.py

+15
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,18 @@ def test_scalar_trace_as_data(self):
146146

147147
fig = go.Figure(data=dict(type='waterfall', y=[2, 1, 3]))
148148
self.assertEqual(fig.data, (go.Waterfall(y=[2, 1, 3]),))
149+
150+
def test_pop_data(self):
151+
fig = go.Figure(data=go.Waterfall(y=[2, 1, 3]))
152+
self.assertEqual(fig.pop('data'), (go.Waterfall(y=[2, 1, 3]),))
153+
self.assertEqual(fig.data, ())
154+
155+
def test_pop_layout(self):
156+
fig = go.Figure(layout=go.Layout(width=1000))
157+
self.assertEqual(fig.pop('layout'), go.Layout(width=1000))
158+
self.assertEqual(fig.layout, go.Layout())
159+
160+
def test_pop_invalid_key(self):
161+
fig = go.Figure(layout=go.Layout(width=1000))
162+
with self.assertRaises(KeyError):
163+
fig.pop('bogus')

Diff for: packages/python/plotly/plotly/tests/test_core/test_graph_objs/test_graph_objs.py

+37
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,40 @@ def test_legacy_title_props_remapped(self):
115115
self.assertIn('titlefont', obj)
116116
self.assertIn('titlefont.family', obj)
117117
self.assertIn('titlefont', iter(obj))
118+
119+
120+
class TestPop(TestCase):
121+
def setUp(self):
122+
self.layout = go.Layout(
123+
width=1000,
124+
title={'text': 'the title', 'font': {'size': 20}},
125+
annotations=[{}, {}],
126+
xaxis2={'range': [1, 2]}
127+
)
128+
129+
def test_pop_valid_simple_prop(self):
130+
self.assertEqual(self.layout.width, 1000)
131+
self.assertEqual(self.layout.pop('width'), 1000)
132+
self.assertIsNone(self.layout.width)
133+
134+
def test_pop_valid_compound_prop(self):
135+
val = self.layout.title
136+
self.assertEqual(self.layout.pop('title'), val)
137+
self.assertEqual(self.layout.title, go.layout.Title())
138+
139+
def test_pop_valid_array_prop(self):
140+
val = self.layout.annotations
141+
self.assertEqual(self.layout.pop('annotations'), val)
142+
self.assertEqual(self.layout.annotations, ())
143+
144+
def test_pop_valid_subplot_prop(self):
145+
val = self.layout.xaxis2
146+
self.assertEqual(self.layout.pop('xaxis2'), val)
147+
self.assertEqual(self.layout.xaxis2, go.layout.XAxis())
148+
149+
def test_pop_invalid_prop_key_error(self):
150+
with self.assertRaises(KeyError):
151+
self.layout.pop('bogus')
152+
153+
def test_pop_invalid_prop_with_default(self):
154+
self.assertEqual(self.layout.pop('bogus', 42), 42)

0 commit comments

Comments
 (0)