@@ -282,7 +282,7 @@ def plot(figure_or_data, validate=True, **plot_options):
282
282
_set_grid_column_references (figure , grid )
283
283
payload ["figure" ] = figure
284
284
285
- file_info = _create_or_overwrite (payload , "plot" )
285
+ file_info = _create_or_update (payload , "plot" )
286
286
287
287
# Compute viewing URL
288
288
if sharing == "secret" :
@@ -1094,7 +1094,7 @@ def upload(
1094
1094
if parent_path != "" :
1095
1095
payload ["parent_path" ] = parent_path
1096
1096
1097
- file_info = _create_or_overwrite (payload , "grid" )
1097
+ file_info = _create_or_overwrite_grid (payload )
1098
1098
1099
1099
cols = file_info ["cols" ]
1100
1100
fid = file_info ["fid" ]
@@ -1445,10 +1445,73 @@ def get_grid(grid_url, raw=False):
1445
1445
return Grid (parsed_content , fid )
1446
1446
1447
1447
1448
- def _create_or_overwrite (data , filetype ):
1448
+ def _create_or_update (data , filetype ):
1449
1449
"""
1450
- Create or overwrite (if file exists) and grid, plot, spectacle,
1451
- or dashboard object
1450
+ Create or update (if file exists) and plot, spectacle, or dashboard
1451
+ object
1452
+ Parameters
1453
+ ----------
1454
+ data: dict
1455
+ update/create API payload
1456
+ filetype: str
1457
+ One of 'plot', 'grid', 'spectacle_presentation', or 'dashboard'
1458
+ Returns
1459
+ -------
1460
+ dict
1461
+ File info from API response
1462
+ """
1463
+ api_module = getattr (v2 , filetype + "s" )
1464
+
1465
+ # lookup if pre-existing filename already exists
1466
+ if "parent_path" in data :
1467
+ filename = data ["parent_path" ] + "/" + data ["filename" ]
1468
+ else :
1469
+ filename = data .get ("filename" , None )
1470
+
1471
+ if filename :
1472
+ try :
1473
+ lookup_res = v2 .files .lookup (filename )
1474
+ if isinstance (lookup_res .content , bytes ):
1475
+ content = lookup_res .content .decode ("utf-8" )
1476
+ else :
1477
+ content = lookup_res .content
1478
+
1479
+ matching_file = json .loads (content )
1480
+
1481
+ if matching_file ["filetype" ] == filetype :
1482
+ fid = matching_file ["fid" ]
1483
+ res = api_module .update (fid , data )
1484
+ else :
1485
+ raise _plotly_utils .exceptions .PlotlyError (
1486
+ """
1487
+ '{filename}' is already a {other_filetype} in your account.
1488
+ While you can overwrite {filetype}s with the same name, you can't overwrite
1489
+ files with a different type. Try deleting '{filename}' in your account or
1490
+ changing the filename.""" .format (
1491
+ filename = filename ,
1492
+ filetype = filetype ,
1493
+ other_filetype = matching_file ["filetype" ],
1494
+ )
1495
+ )
1496
+
1497
+ except exceptions .PlotlyRequestError :
1498
+ res = api_module .create (data )
1499
+ else :
1500
+ res = api_module .create (data )
1501
+
1502
+ # Check response
1503
+ res .raise_for_status ()
1504
+
1505
+ # Get resulting file content
1506
+ file_info = res .json ()
1507
+ file_info = file_info .get ("file" , file_info )
1508
+
1509
+ return file_info
1510
+
1511
+
1512
+ def _create_or_overwrite_grid (data , max_retries = 3 ):
1513
+ """
1514
+ Create or overwrite (if file exists) a grid
1452
1515
1453
1516
Parameters
1454
1517
----------
@@ -1462,7 +1525,7 @@ def _create_or_overwrite(data, filetype):
1462
1525
dict
1463
1526
File info from API response
1464
1527
"""
1465
- api_module = getattr ( v2 , filetype + "s" )
1528
+ api_module = v2 . grids
1466
1529
1467
1530
# lookup if pre-existing filename already exists
1468
1531
if "parent_path" in data :
@@ -1484,21 +1547,27 @@ def _create_or_overwrite(data, filetype):
1484
1547
1485
1548
# Delete fid
1486
1549
# This requires sending file to trash and then deleting it
1487
- res = api_module .trash (fid )
1550
+ res = api_module .destroy (fid )
1488
1551
res .raise_for_status ()
1489
1552
1490
- res = api_module .permanent_delete (fid )
1491
- res .raise_for_status ()
1492
1553
except exceptions .PlotlyRequestError as e :
1493
1554
# Raise on trash or permanent delete
1494
1555
# Pass through to try creating the file anyway
1495
1556
pass
1496
1557
1497
1558
# Create file
1498
- res = api_module .create (data )
1499
- res .raise_for_status ()
1559
+ try :
1560
+ res = api_module .create (data )
1561
+ except exceptions .PlotlyRequestError as e :
1562
+ if max_retries > 0 and "already exists" in e .message :
1563
+ # Retry _create_or_overwrite
1564
+ time .sleep (1 )
1565
+ return _create_or_overwrite_grid (data , max_retries = max_retries - 1 )
1566
+ else :
1567
+ raise
1500
1568
1501
1569
# Get resulting file content
1570
+ res .raise_for_status ()
1502
1571
file_info = res .json ()
1503
1572
file_info = file_info .get ("file" , file_info )
1504
1573
@@ -1586,7 +1655,7 @@ def upload(cls, dashboard, filename, sharing="public", auto_open=True):
1586
1655
"world_readable" : world_readable ,
1587
1656
}
1588
1657
1589
- file_info = _create_or_overwrite (data , "dashboard" )
1658
+ file_info = _create_or_update (data , "dashboard" )
1590
1659
1591
1660
url = file_info ["web_url" ]
1592
1661
@@ -1683,7 +1752,7 @@ def upload(cls, presentation, filename, sharing="public", auto_open=True):
1683
1752
"world_readable" : world_readable ,
1684
1753
}
1685
1754
1686
- file_info = _create_or_overwrite (data , "spectacle_presentation" )
1755
+ file_info = _create_or_update (data , "spectacle_presentation" )
1687
1756
1688
1757
url = file_info ["web_url" ]
1689
1758
0 commit comments