def testForceUnicode(self): self.assertEquals(u"aaa", util.force_unicode("aaa")) self.assertEquals(u"12", util.force_unicode(12)) self.assertEquals(u"\u0430\u0431\u0432", util.force_unicode("\xd0\xb0\xd0\xb1\xd0\xb2")) self.assertEquals(u'\u30e6\u30cb\u30b3\u30fc\u30c9', util.force_unicode(u'\u30e6\u30cb\u30b3\u30fc\u30c9'))
def testForceUnicode(self): self.assertEquals(u"aaa", util.force_unicode("aaa")) self.assertEquals(u"12", util.force_unicode(12)) self.assertEquals(u"\u0430\u0431\u0432", util.force_unicode("\xd0\xb0\xd0\xb1\xd0\xb2")) self.assertEquals( u'\u30e6\u30cb\u30b3\u30fc\u30c9', util.force_unicode(u'\u30e6\u30cb\u30b3\u30fc\u30c9'))
def append(self, tag): """Appends a tag if it doesn't already exist.""" tag = util.force_unicode(tag) if tag in self._tags: return self._operation_queue.wavelet_modify_tag( self._wave_id, self._wavelet_id, tag) self._tags.append(tag)
def remove(self, tag): """Removes a tag if it exists.""" tag = util.force_unicode(tag) if not tag in self._tags: return self._operation_queue.wavelet_modify_tag( self._wave_id, self._wavelet_id, tag, modify_how='remove') self._tags.remove(tag)
def append(self, tag): """Appends a tag if it doesn't already exist.""" tag = util.force_unicode(tag) if tag in self._tags: return self._operation_queue.wavelet_modify_tag(self._wave_id, self._wavelet_id, tag) self._tags.append(tag)
def remove(self, tag): """Removes a tag if it exists.""" tag = util.force_unicode(tag) if not tag in self._tags: return self._operation_queue.wavelet_modify_tag(self._wave_id, self._wavelet_id, tag, modify_how='remove') self._tags.remove(tag)
def _decode_data(self, data, charset): """ Decode string data. :returns: unicode string """ try: return util.force_unicode(data, charset) except UnicodeDecodeError: raise BadRequest('wrong charset')
def append_markup(self, markup): """Interpret the markup text as xhtml and append the result to the doc. Args: markup: The markup'ed text to append. """ markup = util.force_unicode(markup) self._operation_queue.document_append_markup(self.wave_id, self.wavelet_id, self.blip_id, markup) self._content += util.parse_markup(markup)
def run_chain(chain, content): """Run content through a filter chain. Works with either a string or a sequence of filters""" if chain == None: #pragma: no cover return content if not hasattr(chain,'__iter__'): #Not a sequence, must be a string, parse it chain = parse_chain(chain) for fn in chain: f = load_filter(fn) logger.debug("Applying filter: "+fn) content = f.run(content) logger.debug("Content:"+content) return util.force_unicode(content)
def run_chain(chain, content): """Run content through a filter chain. Works with either a string or a sequence of filters""" if chain is None: #pragma: no cover return content if not hasattr(chain, '__iter__'): #Not a sequence, must be a string, parse it chain = parse_chain(chain) for fn in chain: f = load_filter(fn) logger.debug("Applying filter: " + fn) content = f.run(content) logger.debug("Content: " + content) return util.force_unicode(content)
def reply(self, initial_content=None): """Replies to the conversation in this wavelet. Args: initial_content: If set, start with this (string) content. Returns: A transient version of the blip that contains the reply. """ if not initial_content: initial_content = u'\n' initial_content = util.force_unicode(initial_content) blip_data = self._operation_queue.wavelet_append_blip( self.wave_id, self.wavelet_id, initial_content) instance = blip.Blip(blip_data, self._blips, self._operation_queue) self._blips._add(instance) return instance
def _set_title(self, title): title = util.force_unicode(title) if title.find('\n') != -1: raise errors.Error('Wavelet title should not contain a newline ' + 'character. Specified: ' + title) self._operation_queue.wavelet_set_title(self.wave_id, self.wavelet_id, title) self._title = title # Adjust the content of the root blip, if it is available in the context. if self._root_blip: content = '\n' splits = self._root_blip._content.split('\n', 2) if len(splits) == 3: content += splits[2] self._root_blip._content = '\n' + title + content
def _execute(self, modify_how, what, bundled_annotations=None): """Executes this BlipRefs object. Args: modify_how: What to do. Any of the operation declared at the top. what: Depending on the operation. For delete, has to be None. For the others it is a singleton, a list or a function returning what to do; for ANNOTATE tuples of (key, value), for the others either string or elements. If what is a function, it takes three parameters, the content of the blip, the beginning of the matching range and the end. bundled_annotations: Annotations to apply immediately. Raises: IndexError when trying to access content outside of the blip. ValueError when called with the wrong values. Returns: self for chainability. """ blip = self._blip if modify_how != BlipRefs.DELETE: if type(what) != list: what = [what] next_index = 0 matched = [] # updated_elements is used to store the element type of the # element to update updated_elements = [] # For now, if we find one markup, we'll use it everywhere. next = None hit_found = False for start, end in self._hits(): hit_found = True if start < 0: start += len(blip) if end == 0: end += len(blip) if end < 0: end += len(blip) if len(blip) == 0: if start != 0 or end != 0: raise IndexError('Start and end have to be 0 for empty document') elif start < 0 or end < 1 or start >= len(blip) or end > len(blip): raise IndexError('Position outside the document') if modify_how == BlipRefs.DELETE: for i in range(start, end): if i in blip._elements: del blip._elements[i] blip._delete_annotations(start, end) blip._shift(end, start - end) blip._content = blip._content[:start] + blip._content[end:] else: if callable(what): next = what(blip._content, start, end) matched.append(next) else: next = what[next_index] next_index = (next_index + 1) % len(what) if isinstance(next, str): next = util.force_unicode(next) if modify_how == BlipRefs.ANNOTATE: key, value = next blip.annotations._add_internal(key, value, start, end) elif modify_how == BlipRefs.CLEAR_ANNOTATION: blip.annotations._delete_internal(next, start, end) elif modify_how == BlipRefs.UPDATE_ELEMENT: el = blip._elements.get(start) if not element: raise ValueError('No element found at index %s' % start) # the passing around of types this way feels a bit dirty: updated_elements.append(element.Element.from_json({'type': el.type, 'properties': next})) for k, b in next.items(): setattr(el, k, b) else: if modify_how == BlipRefs.INSERT: end = start elif modify_how == BlipRefs.INSERT_AFTER: start = end elif modify_how == BlipRefs.REPLACE: pass else: raise ValueError('Unexpected modify_how: ' + modify_how) if isinstance(next, element.Element): text = ' ' else: text = next # in the case of a replace, and the replacement text is shorter, # delete the delta. if start != end and len(text) < end - start: blip._delete_annotations(start + len(text), end) blip._shift(end, len(text) + start - end) blip._content = blip._content[:start] + text + blip._content[end:] if bundled_annotations: end_annotation = start + len(text) blip._delete_annotations(start, end_annotation) for key, value in bundled_annotations: blip.annotations._add_internal(key, value, start, end_annotation) if isinstance(next, element.Element): blip._elements[start] = next # No match found, return immediately without generating op. if not hit_found: return operation = blip._operation_queue.document_modify(blip.wave_id, blip.wavelet_id, blip.blip_id) for param, value in self._params.items(): operation.set_param(param, value) modify_action = {'modifyHow': modify_how} if modify_how == BlipRefs.DELETE: pass elif modify_how == BlipRefs.UPDATE_ELEMENT: modify_action['elements'] = updated_elements elif (modify_how == BlipRefs.REPLACE or modify_how == BlipRefs.INSERT or modify_how == BlipRefs.INSERT_AFTER): if callable(what): what = matched if what: if not isinstance(next, element.Element): modify_action['values'] = [util.force_unicode(value) for value in what] else: modify_action['elements'] = what elif modify_how == BlipRefs.ANNOTATE: modify_action['values'] = [x[1] for x in what] modify_action['annotationKey'] = what[0][0] elif modify_how == BlipRefs.CLEAR_ANNOTATION: modify_action['annotationKey'] = what[0] if bundled_annotations: modify_action['bundledAnnotations'] = [ {'key': key, 'value': value} for key, value in bundled_annotations] operation.set_param('modifyAction', modify_action) return self
def _execute(self, modify_how, what, bundled_annotations=None): """Executes this BlipRefs object. Args: modify_how: What to do. Any of the operation declared at the top. what: Depending on the operation. For delete, has to be None. For the others it is a singleton, a list or a function returning what to do; for ANNOTATE tuples of (key, value), for the others either string or elements. If what is a function, it takes three parameters, the content of the blip, the beginning of the matching range and the end. bundled_annotations: Annotations to apply immediately. Raises: IndexError when trying to access content outside of the blip. ValueError when called with the wrong values. Returns: self for chainability. """ blip = self._blip if modify_how != BlipRefs.DELETE: if not isinstance(what, list): what = [what] next_index = 0 matched = [] # updated_elements is used to store the element type of the # element to update updated_elements = [] # For now, if we find one markup, we'll use it everywhere. next = None hit_found = False for start, end in self._hits(): hit_found = True if start < 0: start += len(blip) if end == 0: end += len(blip) if end < 0: end += len(blip) if len(blip) == 0: if start != 0 or end != 0: raise IndexError('Start and end have to be 0 for empty document') elif start < 0 or end < 1 or start >= len(blip) or end > len(blip): raise IndexError('Position outside the document') if modify_how == BlipRefs.DELETE: for i in range(start, end): if i in blip._elements: del blip._elements[i] blip._delete_annotations(start, end) blip._shift(end, start - end) blip._content = blip._content[:start] + blip._content[end:] else: if callable(what): next = what(blip._content, start, end) matched.append(next) else: next = what[next_index] next_index = (next_index + 1) % len(what) if isinstance(next, str): next = util.force_unicode(next) if modify_how == BlipRefs.ANNOTATE: key, value = next blip.annotations._add_internal(key, value, start, end) elif modify_how == BlipRefs.CLEAR_ANNOTATION: blip.annotations._delete_internal(next, start, end) elif modify_how == BlipRefs.UPDATE_ELEMENT: el = blip._elements.get(start) if not el: raise ValueError('No element found at index %s' % start) # the passing around of types this way feels a bit dirty: updated_elements.append(element.Element.from_json({'type': el.type, 'properties': next})) for k, b in next.items(): setattr(el, k, b) else: if modify_how == BlipRefs.INSERT: end = start elif modify_how == BlipRefs.INSERT_AFTER: start = end elif modify_how == BlipRefs.REPLACE: pass else: raise ValueError('Unexpected modify_how: ' + modify_how) if isinstance(next, element.Element): text = ' ' else: text = next # in the case of a replace, and the replacement text is shorter, # delete the delta. if start != end and len(text) < end - start: blip._delete_annotations(start + len(text), end) blip._shift(end, len(text) + start - end) blip._content = blip._content[:start] + text + blip._content[end:] if bundled_annotations: end_annotation = start + len(text) blip._delete_annotations(start, end_annotation) for key, value in bundled_annotations: blip.annotations._add_internal(key, value, start, end_annotation) if isinstance(next, element.Element): blip._elements[start] = next # No match found, return immediately without generating op. if not hit_found: return operation = blip._operation_queue.document_modify(blip.wave_id, blip.wavelet_id, blip.blip_id) for param, value in self._params.items(): operation.set_param(param, value) modify_action = {'modifyHow': modify_how} if modify_how == BlipRefs.DELETE: pass elif modify_how == BlipRefs.UPDATE_ELEMENT: modify_action['elements'] = updated_elements elif (modify_how == BlipRefs.REPLACE or modify_how == BlipRefs.INSERT or modify_how == BlipRefs.INSERT_AFTER): if callable(what): what = matched if what: if not isinstance(next, element.Element): modify_action['values'] = [util.force_unicode(value) for value in what] else: modify_action['elements'] = what elif modify_how == BlipRefs.ANNOTATE: modify_action['values'] = [x[1] for x in what] modify_action['annotationKey'] = what[0][0] elif modify_how == BlipRefs.CLEAR_ANNOTATION: modify_action['annotationKey'] = what[0] if bundled_annotations: modify_action['bundledAnnotations'] = [ {'key': key, 'value': value} for key, value in bundled_annotations] operation.set_param('modifyAction', modify_action) return self