1# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX 2# All rights reserved. 3# 4# This software is provided without warranty under the terms of the BSD 5# license included in LICENSE.txt and may be redistributed only under 6# the conditions described in the aforementioned license. The license 7# is also available online at http://www.enthought.com/licenses/BSD.txt 8# 9# Thanks for using Enthought open source! 10 11from codecs import decode, encode 12from functools import partial 13from typing import Any as TAny, Callable as TCallable, NamedTuple 14 15from traits.api import Any, HasStrictTraits, Interface 16 17 18class DataFormat(NamedTuple): 19 """ Information about a mimetype and serializers. 20 21 Simple namedtuple-based class that stores the mimetype, serializer and 22 deserializer together. 23 """ 24 25 #: The mimetype of the data. 26 mimetype: str 27 28 #: A callable that serializes this format. It should take an python 29 #: object of a supported type, and return a bytestring. 30 serialize: TCallable[[TAny], bytes] 31 32 #: A callable that deserializes this format. It should take a 33 #: bytestring and return the extracted object. 34 deserialize: TCallable[[bytes], TAny] 35 36 37def text_format(encoding='utf-8', mimetype='text/plain'): 38 """ DataFormat factory for text mimetypes. 39 """ 40 return DataFormat( 41 mimetype=mimetype, 42 serialize=partial(encode, encoding=encoding), 43 deserialize=partial(decode, encoding=encoding), 44 ) 45 46 47class IDataWrapper(Interface): 48 """ Wrapper around polymorphic toolkit data object containing mimedata. 49 50 To support clipboard and drag and drop operations, toolkits need a way 51 of generically representing data in multiple formats. This is a wrapper 52 class that provides a toolkit independent intreface to these classes 53 which allow the exchange of data, with types specified by MIME types. 54 """ 55 56 #: The toolkit data object. 57 toolkit_data = Any() 58 59 def mimetypes(self): 60 """ Return a set of mimetypes holding data. 61 62 Returns 63 ------- 64 mimetypes : set of str 65 The set of mimetypes currently storing data in the toolkit data 66 object. 67 """ 68 pass 69 70 def has_format(self, format): 71 """ Whether or not a particular format has available data. 72 73 Parameters 74 ---------- 75 format : DataFormat 76 A data format object. 77 78 Returns 79 ------- 80 has_format : bool 81 Whether or not there is data associated with that format in the 82 underlying toolkit object. 83 """ 84 raise NotImplementedError() 85 86 def get_format(self, format): 87 """ The decoded data associted with the format. 88 89 Parameters 90 ---------- 91 format : DataFormat 92 A data format object. 93 94 Returns 95 ------- 96 data : any 97 The data decoded for the given format. 98 """ 99 raise NotImplementedError() 100 101 def set_format(self, format, data): 102 """ Encode and set data for the format. 103 104 Parameters 105 ---------- 106 format : DataFormat 107 A data format object. 108 data : any 109 The data to be encoded and stored. 110 """ 111 raise NotImplementedError() 112 113 def get_mimedata(self, mimetype): 114 """ Get raw data for the given media type. 115 116 Parameters 117 ---------- 118 mimetype : str 119 The mime media type to be extracted. 120 121 Returns 122 ------- 123 mimedata : bytes 124 The mime media data as bytes. 125 """ 126 raise NotImplementedError() 127 128 def set_mimedata(self, mimetype, mimedata): 129 """ Set raw data for the given media type. 130 131 Parameters 132 ---------- 133 mimetype : str 134 The mime media type to be extracted. 135 mimedata : bytes 136 The mime media data encoded as bytes.. 137 """ 138 raise NotImplementedError() 139 140 141class MDataWrapper(HasStrictTraits): 142 """ Mixin class for DataWrappers. 143 144 This provides standard methods for using DataFormat objects, but not the 145 low-level communication with the underlying toolkit. 146 """ 147 148 def has_format(self, format): 149 """ Whether or not a particular format has available data. 150 151 Parameters 152 ---------- 153 format : DataFormat 154 A data format object. 155 156 Returns 157 ------- 158 has_format : bool 159 Whether or not there is data associated with that format in the 160 underlying toolkit object. 161 """ 162 return format.mimetype in self.mimetypes() 163 164 def get_format(self, format): 165 """ The decoded data associted with the format. 166 167 Parameters 168 ---------- 169 format : DataFormat 170 A data format object. 171 172 Returns 173 ------- 174 data : any 175 The data decoded for the given format. 176 """ 177 return format.deserialize(self.get_mimedata(format.mimetype)) 178 179 def set_format(self, format, data): 180 """ Encode and set data for the format. 181 182 Parameters 183 ---------- 184 format : DataFormat 185 A data format object. 186 data : any 187 The data to be encoded and stored. 188 """ 189 self.set_mimedata(format.mimetype, format.serialize(data)) 190