widget_upload.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # Copyright(c) Jupyter Development Team.
  2. # Distributed under the terms of the Modified BSD License.
  3. """FileUpload class.
  4. Represents a file upload button.
  5. """
  6. from traitlets import (
  7. observe, default, Unicode, Dict, List, Int, Bool, Bytes, CaselessStrEnum
  8. )
  9. from .widget_description import DescriptionWidget
  10. from .valuewidget import ValueWidget
  11. from .widget_core import CoreWidget
  12. from .widget_button import ButtonStyle
  13. from .widget import register, widget_serialization
  14. from .trait_types import bytes_serialization, InstanceDict
  15. def content_from_json(value, widget):
  16. """
  17. deserialize file content
  18. """
  19. from_json = bytes_serialization['from_json']
  20. output = [from_json(e, None) for e in value]
  21. return output
  22. @register
  23. class FileUpload(DescriptionWidget, ValueWidget, CoreWidget):
  24. """
  25. Upload file(s) from browser to Python kernel as bytes
  26. """
  27. _model_name = Unicode('FileUploadModel').tag(sync=True)
  28. _view_name = Unicode('FileUploadView').tag(sync=True)
  29. _counter = Int().tag(sync=True)
  30. accept = Unicode(help='File types to accept, empty string for all').tag(sync=True)
  31. multiple = Bool(help='If True, allow for multiple files upload').tag(sync=True)
  32. disabled = Bool(help='Enable or disable button').tag(sync=True)
  33. icon = Unicode('upload', help="Font-awesome icon name, without the 'fa-' prefix.").tag(sync=True)
  34. button_style = CaselessStrEnum(
  35. values=['primary', 'success', 'info', 'warning', 'danger', ''], default_value='',
  36. help="""Use a predefined styling for the button.""").tag(sync=True)
  37. style = InstanceDict(ButtonStyle).tag(sync=True, **widget_serialization)
  38. metadata = List(Dict(), help='List of file metadata').tag(sync=True)
  39. data = List(Bytes(), help='List of file content (bytes)').tag(
  40. sync=True, from_json=content_from_json
  41. )
  42. error = Unicode(help='Error message').tag(sync=True)
  43. value = Dict(read_only=True)
  44. @observe('_counter')
  45. def on_incr_counter(self, change):
  46. """
  47. counter increment triggers the update of trait value
  48. """
  49. res = {}
  50. msg = 'Error: length of metadata and data must be equal'
  51. assert len(self.metadata) == len(self.data), msg
  52. for metadata, content in zip(self.metadata, self.data):
  53. name = metadata['name']
  54. res[name] = {'metadata': metadata, 'content': content}
  55. self.set_trait('value', res)
  56. @default('description')
  57. def _default_description(self):
  58. return 'Upload'