class IFileEditForm(IFile): """Schema for the File edit form. Replaces the Bytes `data` field with a Text field. """ data = Text( title=_(u'Data'), description=_(u'The actual content of the object.'), default=u'', missing_value=u'', required=False, )
def update(self): try: return super(FileEdit, self).update() except CharsetTooWeak as charset: self.update_status = _( "The character set you specified ($charset)" " cannot encode all characters in text.", mapping={'charset': charset}) return self.update_status except UnknownCharset as charset: self.update_status = _( "The character set you specified ($charset)" " is not supported.", mapping={'charset': charset}) return self.update_status
def getData(self): charset = extractCharset(self.context.contentType) try: return {'contentType': self.context.contentType, 'data': self.context.data.decode(charset)} except LookupError: msg = _("The character set specified in the content type" " ($charset) is not supported.", mapping={'charset': charset}) raise UserError(msg) except UnicodeDecodeError: msg = _("The character set specified in the content type" " ($charset) does not match file content.", mapping={'charset': charset}) raise UserError(msg)
def setData(self, data): charset = extractCharset(data['contentType']) try: encodeddata = data['data'].encode(charset) except LookupError: raise UnknownCharset(charset) except UnicodeEncodeError: raise CharsetTooWeak(charset) modified = [] if encodeddata != self.context.data: self.context.data = encodeddata modified.append('data') if self.context.contentType != data['contentType']: self.context.contentType = data['contentType'] modified.append('contentType') formatter = self.request.locale.dates.getFormatter( 'dateTime', 'medium') if modified: event = lifecycleevent.ObjectModifiedEvent( self.context, lifecycleevent.Attributes(IFile, *modified)) zope.event.notify(event) return _("Updated on ${date_time}", mapping={'date_time': formatter.format(datetime.utcnow())})
def setData(self, data): charset = extractCharset(data['contentType']) try: encodeddata = data['data'].encode(charset) except LookupError: raise UnknownCharset(charset) except UnicodeEncodeError: raise CharsetTooWeak(charset) modified = [] if encodeddata != self.context.data: self.context.data = encodeddata modified.append('data') if self.context.contentType != data['contentType']: self.context.contentType = data['contentType'] modified.append('contentType') formatter = self.request.locale.dates.getFormatter('dateTime', 'medium') if modified: event = lifecycleevent.ObjectModifiedEvent( self.context, lifecycleevent.Attributes(IFile, *modified)) zope.event.notify(event) return _("Updated on ${date_time}", mapping={'date_time': formatter.format(datetime.utcnow())})
def update(self): try: return super(FileEdit, self).update() except CharsetTooWeak, charset: self.update_status = _("The character set you specified ($charset)" " cannot encode all characters in text.", mapping={'charset': charset}) return self.update_status
class IFile(Interface): contentType = BytesLine( title=_(u'Content Type'), description=_(u'The content type identifies the type of data.'), default='', required=False, missing_value='') data = Bytes( title=_(u'Data'), description=_(u'The actual content of the object.'), default='', missing_value='', required=False, ) def getSize(): """Return the byte-size of the data of the object."""
def getData(self): charset = extractCharset(self.context.contentType) try: return { 'contentType': self.context.contentType, 'data': self.context.data.decode(charset) } except LookupError: msg = _( "The character set specified in the content type" " ($charset) is not supported.", mapping={'charset': charset}) raise UserError(msg) except UnicodeDecodeError: msg = _( "The character set specified in the content type" " ($charset) does not match file content.", mapping={'charset': charset}) raise UserError(msg)
def sizeForDisplay(self): '''See `ISized`''' w, h = self._image.getImageSize() if w < 0: w = '?' if h < 0: h = '?' bytes = self._image.getSize() byte_size = byteDisplay(bytes) mapping = byte_size.mapping if mapping is None: mapping = {} mapping.update({'width': str(w), 'height': str(h)}) # TODO the way this message id is defined, it won't be picked up by # i18nextract and never show up in message catalogs return _(byte_size + ' ${width}x${height}', mapping=mapping)
def sizeForDisplay(self): """See `ISized`""" w, h = self._image.getImageSize() if w < 0: w = "?" if h < 0: h = "?" bytes = self._image.getSize() byte_size = byteDisplay(bytes) mapping = byte_size.mapping if mapping is None: mapping = {} mapping.update({"width": str(w), "height": str(h)}) # TODO the way this message id is defined, it won't be picked up by # i18nextract and never show up in message catalogs return _(byte_size + " ${width}x${height}", mapping=mapping)
def update_object(self, data, contenttype): self.context.contentType = contenttype descriptor = lifecycleevent.Attributes(IFile, "contentType") # Update *only* if a new value is specified if data: self.context.data = data descriptor.attributes += ("data", ) event = lifecycleevent.ObjectModifiedEvent(self.context, descriptor) zope.event.notify(event) formatter = self.request.locale.dates.getFormatter( 'dateTime', 'medium') return _("Updated on ${date_time}", mapping={'date_time': formatter.format(datetime.utcnow())})
def update_object(self, data, contenttype): self.context.contentType = contenttype descriptor = lifecycleevent.Attributes(IFile, "contentType") # Update *only* if a new value is specified if data: self.context.data = data descriptor.attributes += "data", event = lifecycleevent.ObjectModifiedEvent(self.context, descriptor) zope.event.notify(event) formatter = self.request.locale.dates.getFormatter( 'dateTime', 'medium') return _("Updated on ${date_time}", mapping={'date_time': formatter.format(datetime.utcnow())})
class FileEdit(object): r"""File edit form mixin. Lets the user edit a text file directly via a browser form. Converts between Unicode strings used in browser forms and 8-bit strings stored internally. >>> from zope.publisher.browser import BrowserView, TestRequest >>> class FileEditView(FileEdit, BrowserView): pass >>> view = FileEditView(File(), TestRequest()) >>> view.getData() {'data': u'', 'contentType': ''} We install an event logger so we can see the events generated. >>> def eventLog(event): ... print event.__class__.__name__, event.descriptions[0].attributes >>> zope.event.subscribers.append(eventLog) >>> view.setData({'contentType': 'text/plain; charset=ISO-8859-13', ... 'data': u'text \u0105'}) # doctest:+ELLIPSIS ObjectModifiedEvent ('data', 'contentType') u'Updated on ${date_time}' >>> view.context.contentType 'text/plain; charset=ISO-8859-13' >>> view.context.data 'text \xe0' >>> view.getData()['data'] u'text \u0105' Cleanup eventlog. >>> zope.event.subscribers.remove(eventLog) You will get an error if you try to specify a charset that cannot encode all the characters >>> view.setData({'contentType': 'text/xml; charset=ISO-8859-1', ... 'data': u'text \u0105'}) Traceback (most recent call last): ... CharsetTooWeak: ISO-8859-1 You will get a different error if you try to specify an invalid charset >>> view.setData({'contentType': 'text/xml; charset=UNKNOWN', ... 'data': u'text \u0105'}) Traceback (most recent call last): ... UnknownCharset: UNKNOWN The update method catches those errors and replaces them with error messages >>> from zope.i18n import translate >>> class FakeFormView(BrowserView): ... def update(self): ... raise CharsetTooWeak('ASCII') >>> class FileEditView(FileEdit, FakeFormView): pass >>> view = FileEditView(File(), TestRequest()) >>> translate(view.update()) u'The character set you specified (ASCII) cannot encode all characters in text.' >>> translate(view.update_status) u'The character set you specified (ASCII) cannot encode all characters in text.' >>> class FakeFormView(BrowserView): ... def update(self): ... raise UnknownCharset('UNKNOWN') >>> class FileEditView(FileEdit, FakeFormView): pass >>> view = FileEditView(File(), TestRequest()) >>> translate(view.update()) u'The character set you specified (UNKNOWN) is not supported.' >>> translate(view.update_status) u'The character set you specified (UNKNOWN) is not supported.' Speaking about errors, if you trick the system and upload a file with incorrect charset designation, you will get a UserError when you visit the view: >>> view.context.contentType = 'text/plain; charset=UNKNOWN' >>> view.context.data = '\xff' >>> view.getData() Traceback (most recent call last): ... UserError: The character set specified in the content type ($charset) is not supported. >>> view.context.contentType = 'text/plain; charset=UTF-8' >>> view.context.data = '\xff' >>> view.getData() Traceback (most recent call last): ... UserError: The character set specified in the content type ($charset) does not match file content. """ error = None def getData(self): charset = extractCharset(self.context.contentType) try: return { 'contentType': self.context.contentType, 'data': self.context.data.decode(charset) } except LookupError: msg = _( "The character set specified in the content type" " ($charset) is not supported.", mapping={'charset': charset}) raise UserError(msg) except UnicodeDecodeError: msg = _( "The character set specified in the content type" " ($charset) does not match file content.", mapping={'charset': charset}) raise UserError(msg) def setData(self, data): charset = extractCharset(data['contentType']) try: encodeddata = data['data'].encode(charset) except LookupError: raise UnknownCharset(charset) except UnicodeEncodeError: raise CharsetTooWeak(charset) modified = [] if encodeddata != self.context.data: self.context.data = encodeddata modified.append('data') if self.context.contentType != data['contentType']: self.context.contentType = data['contentType'] modified.append('contentType') formatter = self.request.locale.dates.getFormatter( 'dateTime', 'medium') if modified: event = lifecycleevent.ObjectModifiedEvent( self.context, lifecycleevent.Attributes(IFile, *modified)) zope.event.notify(event) return _("Updated on ${date_time}", mapping={'date_time': formatter.format(datetime.utcnow())}) def update(self): try: return super(FileEdit, self).update() except CharsetTooWeak, charset: self.update_status = _( "The character set you specified ($charset)" " cannot encode all characters in text.", mapping={'charset': charset}) return self.update_status except UnknownCharset, charset: self.update_status = _( "The character set you specified ($charset)" " is not supported.", mapping={'charset': charset}) return self.update_status