2
2
import abc
3
3
import base64
4
4
import zipfile
5
+ import warnings
6
+
5
7
from uuid import uuid4
6
8
from typing import List , Optional , Type , Union
7
9
10
+ try :
11
+ # Python 3.8+
12
+ # pylint: disable=ungrouped-imports
13
+ from typing import TypedDict # type: ignore
14
+ except (ImportError , ModuleNotFoundError ):
15
+ # Python < 3.8
16
+ from typing_extensions import TypedDict # type: ignore
17
+
18
+
8
19
import bleach
9
20
from dash .development .base_component import Component
10
21
from dash .dependencies import Input , Output
11
22
import webviz_core_components as wcc
12
23
13
24
25
+ class ZipFileMember (TypedDict ):
26
+ filename : str # Filename to be given within the archive
27
+ content : str # String of file to be added
28
+
29
+
30
+ class EncodedFile (ZipFileMember ):
31
+ # Same keys as in ZipFileMember, with the following changes:
32
+ # - filename is now name of the actual downloaded file.
33
+ # - content is now a base64 encoded ASCII string.
34
+ # - mime_type needs to be added as well.
35
+ mime_type : str
36
+
37
+
14
38
class WebvizPluginABC (abc .ABC ):
15
39
"""All webviz plugins need to subclass this abstract base class,
16
40
e.g.
@@ -40,7 +64,6 @@ def layout(self):
40
64
TOOLBAR_BUTTONS = [
41
65
"screenshot" ,
42
66
"expand" ,
43
- "download_zip" ,
44
67
"contact_person" ,
45
68
"guided_tour" ,
46
69
]
@@ -62,6 +85,7 @@ def __init__(self, screenshot_filename: str = "webviz-screenshot.png") -> None:
62
85
63
86
self ._plugin_uuid = uuid4 ()
64
87
self ._screenshot_filename = screenshot_filename
88
+ self ._add_download_button = False
65
89
66
90
def uuid (self , element : str ) -> str :
67
91
"""Typically used to get a unique ID for some given element/component in
@@ -94,10 +118,8 @@ def _plugin_wrapper_id(self) -> str:
94
118
95
119
@property
96
120
def plugin_data_output (self ) -> Output :
97
- # pylint: disable=attribute-defined-outside-init
98
- # We do not have a __init__ method in this abstract base class
99
121
self ._add_download_button = True
100
- return Output (self ._plugin_wrapper_id , "zip_base64 " )
122
+ return Output (self ._plugin_wrapper_id , "download " )
101
123
102
124
@property
103
125
def plugin_data_requested (self ) -> Input :
@@ -110,16 +132,28 @@ def _reformat_tour_steps(steps: List[dict]) -> List[dict]:
110
132
]
111
133
112
134
@staticmethod
113
- def plugin_data_compress (content : List [dict ]) -> str :
114
- byte_io = io .BytesIO ()
115
-
116
- with zipfile .ZipFile (byte_io , "w" ) as zipped_data :
117
- for data in content :
118
- zipped_data .writestr (data ["filename" ], data ["content" ])
119
-
120
- byte_io .seek (0 )
135
+ def plugin_compressed_data (
136
+ filename : str , content : List [ZipFileMember ]
137
+ ) -> EncodedFile :
138
+ with io .BytesIO () as bytes_io :
139
+ with zipfile .ZipFile (bytes_io , "w" ) as zipped_data :
140
+ for data in content :
141
+ zipped_data .writestr (data ["filename" ], data ["content" ])
142
+
143
+ bytes_io .seek (0 )
144
+ return EncodedFile (
145
+ filename = filename ,
146
+ content = base64 .b64encode (bytes_io .read ()).decode ("ascii" ),
147
+ mime_type = "application/zip" ,
148
+ )
121
149
122
- return base64 .b64encode (byte_io .read ()).decode ("ascii" )
150
+ @staticmethod
151
+ def plugin_data_compress (content : List [ZipFileMember ]) -> EncodedFile :
152
+ warnings .warn (
153
+ "Use 'plugin_compressed_data' instead of 'plugin_data_compress'" ,
154
+ DeprecationWarning ,
155
+ )
156
+ return WebvizPluginABC .plugin_compressed_data ("webviz-data.zip" , content )
123
157
124
158
def plugin_layout (
125
159
self , contact_person : Optional [dict ] = None
@@ -145,8 +179,8 @@ def plugin_layout(
145
179
for key in contact_person :
146
180
contact_person [key ] = bleach .clean (str (contact_person [key ]))
147
181
148
- if "download_zip" in buttons and not hasattr ( self , " _add_download_button" ) :
149
- buttons .remove ( "download_zip " )
182
+ if self . _add_download_button :
183
+ buttons .append ( "download " )
150
184
151
185
if buttons :
152
186
# pylint: disable=no-member
0 commit comments