def __call__(self, add=None, remove=None, field=None): if add or remove: schema_field = ISchema(self.context)[field] values = list(schema_field.get(self.context)) setter = schema_field.getMutator(self.context) controller = None displayList = None try: displayList = schema_field.vocabulary.getDisplayList(\ self.context) controller = lambda value: value in displayList except AttributeError: raise AttributeError("This Widget needs a vocabulary that " "implements IVocabulary") if add: if controller(add) and add not in values: setter(values + [add]) self.context.reindexObject() return displayList.getValue(add) if remove: if remove in values: values.remove(remove) setter(values) self.context.reindexObject() return displayList.getValue(remove) return super(BrowserView, self).__call__()
def geotag(self): """ Getter """ schema = ISchema(self.context) xfield = schema['location'] accessor = xfield.getAccessor(self.context) return accessor()
def getFields(self, obj): if not self.fields: # get the blob fields to migrate from the first object for field in ISchema(obj).fields(): if IBlobField.providedBy(field): self.fields.append(field.getName()) return self.fields
def geotag(self, value): """ Setter """ schema = ISchema(self.context) xfield = schema['location'] mutator = xfield.getMutator(self.context) mutator(value)
def serialize(self, dom, parent_node, instance, options={}): values = self.get(instance) if not values: return is_ref = self.isReference(instance) for value in values: if instance.Type() == 'Folder': # allowed types are acquired from parent if instance.getConstrainTypesMode() != 1 and self.name in ['locallyAllowedTypes','immediatelyAddableTypes']: continue node = dom.createElementNS(self.namespace.xmlns, "field") name_attr = dom.createAttribute("name") name_attr.value = self.name node.setAttributeNode(name_attr) # try to get 'utf-8' encoded string if isinstance(value, unicode): value = value.encode('utf-8') elif IBaseUnit.providedBy(value): value = value.getRaw(encoding='utf-8') else: value = str(value) if is_ref: if config.HANDLE_REFS: ref_node = dom.createElementNS(self.namespace.xmlns, 'reference') uid_node = dom.createElementNS(self.namespace.xmlns, 'uid') value = dom.createTextNode(value) uid_node.append(value) ref_node.append(uid_node) node.append(ref_node) elif isinstance(value, str) and has_ctrlchars(value): value = value.encode('base64') attr = dom.createAttributeNS(self.namespace.xmlns, 'transfer_encoding') attr.value = 'base64' node.setAttributeNode(attr) value_node = dom.createCDATASection(value) node.appendChild(value_node) else: value_node = dom.createTextNode(value) node.appendChild(value_node) schema = ISchema(instance) field = schema._fields[self.name] if IObjectField.providedBy(field): mime_attr = dom.createAttribute('mimetype') mime_attr.value = field.getContentType(instance) node.setAttributeNode(mime_attr) node.normalize() parent_node.appendChild(node) return True
def at_handle_target_deletion(ref, event): """ Invalidate any pointer before object deletion """ target = ref.getTargetObject() for field in ISchema(target).fields(): if IAmWickedField.providedBy(field): wicked = utils.getWicked(field, target) wicked.unlink(ref.sourceUID) break
def video_cloud_validator(value, instance=None): """ check if cloudUrl has a youtube or vimeo link, saves the id in an annotation and save a clean link to the video for the field """ obj_schema = ISchema(instance) field = obj_schema['cloudUrl'] mutator = field.getMutator(instance) if value: youtube_id = re.compile(r'[0-9a-zA-z\-_]{8,}[A-Z]*') youtube_url = "http://www.youtube.com/watch?v=" vimeo_url = "http://vimeo.com/" annotations = IAnnotations(instance) mapping = annotations.get(KEY) if mapping is None: cloud_url = {'cloud_url': PersistentDict()} mapping = annotations[KEY] = PersistentDict(cloud_url) if 'youtu' and 'playlist' in value: # transform youtube playlist link res = youtube_id.findall(value)[1] vid_id = 'videoseries&' + 'list=' + res value = 'http://www.youtube.com/playlist?list=' + res mapping['cloud_url']['youtube'] = vid_id elif 'youtu' in value: # check youtube links with youtu since they might be # used with youtu.be our youtube.com links res = youtube_id.findall(value) if 'list' in value: vid_id = res[0] + '?list=' + res[1] else: vid_id = res[0] value = youtube_url + vid_id mapping['cloud_url']['youtube'] = vid_id elif 'vimeo' in value: vimeo = re.compile(r'[\d]{5,}') vid_id = vimeo.findall(value)[0] value = vimeo_url + vid_id cloud = mapping['cloud_url'] # remove youtube entry if found since youtube macro # is before vimeo if cloud.get('youtube'): cloud.pop('youtube') cloud['vimeo'] = vid_id else: return "Please enter a video link from Youtube or Vimeo only" mutator(value)
def Schema(self): """ Overrides field definitions in fly. Note that you want to cache the result of this method as it is called many times when rendering view / edit for the content item. """ schema = self.getCachedValue("researcher_schema") if schema is not None: return schema #print "Re-creating schema" # Create modifiable copy of schema # See Products.Archetypes.BaseObject1 schema = ISchema(self) schema = schema.copy() schema = ImplicitAcquisitionWrapper(schema, self) settings = self.getResearchSettings() for row in settings.getFieldCustomizations(): name = row.get("fieldName", None) vocab = row.get("vocabToUse", None) field = schema.get(name, None) if field and vocab and hasattr(field, "vocabulary"): # Modify field copy ion displayList = settings.getVocabulary(vocab) if displayList is not None: field.vocabulary = displayList self.setCachedValue("researcher_schema", schema) return schema
def at_handle_target_moved(obj, event): """ when a target of a link is moved, or renamed we need to notify any objects that may be caching pointers """ #@@ add more tests if IObjectRemovedEvent.providedBy(event): return refs = obj.getRefs(relationship=config.BACKLINK_RELATIONSHIP) path = '/'.join(obj.getPhysicalPath()) for target in refs: for field in ISchema(target).fields(): if IAmWickedField.providedBy(field): wicked = utils.getWicked(field, target) uid = IUID(obj) data = dict(path=path, icon=obj.getIcon(), uid=uid) wicked.cache.reset(uid, [data])
def Schema(self): """Return a (wrapped) schema instance for this object instance. """ return ImplicitAcquisitionWrapper(ISchema(self), self)
def simpleProcessForm(self, data=1, metadata=0, REQUEST=None, values=None): """Processes the schema looking for data in the form. """ # customized to process a single field instead of multiple fields is_new_object = self.checkCreationFlag() request = REQUEST or self.REQUEST _marker = [] if values: form = values else: form = request.form fieldname = form.get('specific_field') if not fieldname: raise ValueError("Please provide a specific field") field = ISchema(self)[fieldname] result = field.widget.process_form(self, field, form, empty_marker=_marker) try: # Pass validating=False to inform the widget that we # aren't in the validation phase, IOW, the returned # data will be forwarded to the storage result = field.widget.process_form(self, field, form, empty_marker=_marker, validating=False) except TypeError: # Support for old-style process_form methods result = field.widget.process_form(self, field, form, empty_marker=_marker) # Set things by calling the mutator mutator = field.getMutator(self) # __traceback_info__ = (self, field, mutator) #was this line used? result[1]['field'] = field.__name__ mapply(mutator, result[0], **result[1]) self.reindexObject() self.unmarkCreationFlag() # NOTE: at the moment, this is not very elegant # the problem is that the objects, when are editing # in a composite manner with the aggregated edit view, # will change their ids after the first save. For example # when editing the title for a Specification, it will # change its id. This means that all the URLs that are # already on the page (for example adding a PolicyQuestion) # will be invalid. To solve this particular case we make # the page reload after editing the Title. In all other cases # we want to either skip this behaviour or make those objects # have their _at_rename_after_creation set to False if self._at_rename_after_creation and is_new_object \ and fieldname == 'title': self._renameAfterCreation(check_auto_id=True) # Post create/edit hooks if is_new_object: self.at_post_create_script() event.notify(ObjectAddedEvent(self)) event.notify(ObjectInitializedEvent(self)) else: self.at_post_edit_script() event.notify(ObjectEditedEvent(self)) return
def video_cloud_validator(value, instance=None, **kwargs): """ check if cloudUrl has a youtube or vimeo link, saves the id in an annotation and save a clean link to the video for the field """ obj_schema = ISchema(instance) field = obj_schema['cloudUrl'] if 'portal_factory' in instance.absolute_url(): return if 'edit' not in kwargs['REQUEST'].URL0: return mutator = field.getMutator(instance) if value: youtube_id = re.compile(r'[0-9a-zA-z\-_]{8,}[A-Z]*') youtube_url = "http://www.youtube.com/watch?v=" vimeo_url = "http://vimeo.com/" annotations = IAnnotations(instance) mapping = annotations.get(KEY) if mapping is None: cloud_url = {'cloud_url': PersistentDict()} mapping = annotations[KEY] = PersistentDict(cloud_url) cloud = mapping['cloud_url'] if 'cmshare' in value: if value in cloud.get('cmshare', ''): return cloud['cmshare'] = value if 'download' in value \ else value + '/download' # remove youtube entry if found since youtube macro # is before vimeo if cloud.get('vimeo'): cloud.pop('vimeo') if cloud.get('youtube'): cloud.pop('youtube') if has_opencv: cap = cv2.VideoCapture(mapping['cloud_url']['cmshare']) req = kwargs['REQUEST'] sec = int( req.form.get('preview_frame_from', instance.preview_frame_from)) jump_to_msec = sec * 1000 cap.set(cv2.CAP_PROP_POS_MSEC, jump_to_msec) ret, frame = cap.read() if not ret: return # fix blue tint by converting from rgb to bgr opencvImage = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) frame_image = PIL.Image.fromarray(opencvImage) destfile = StringIO() frame_image.save(destfile, 'JPEG') destfile.seek(0) instance.setImage(destfile.getvalue()) cap.release() cv2.destroyAllWindows() elif 'youtu' and 'playlist' in value: # transform youtube playlist link res = youtube_id.findall(value)[1] vid_id = 'videoseries&' + 'list=' + res value = 'http://www.youtube-nocookie.com/playlist?list=' + res mapping['cloud_url']['youtube'] = vid_id # remove youtube entry if found since youtube macro # is before vimeo if cloud.get('vimeo'): cloud.pop('vimeo') if cloud.get('cmshare'): cloud.pop('cmshare') elif 'youtu' in value: # check youtube links with youtu since they might be # used with youtu.be our youtube.com links res = youtube_id.findall(value) if 'list' in value: vid_id = res[0] + '?list=' + res[1] else: vid_id = res[0] value = youtube_url + vid_id mapping['cloud_url']['youtube'] = vid_id # remove youtube entry if found since youtube macro # is before vimeo if cloud.get('vimeo'): cloud.pop('vimeo') if cloud.get('cmshare'): cloud.pop('cmshare') elif 'vimeo' in value: vimeo = re.compile(r'[\d]{5,}') vid_id = vimeo.findall(value)[0] value = vimeo_url + vid_id # remove youtube entry if found since youtube macro # is before vimeo if cloud.get('youtube'): cloud.pop('youtube') if cloud.get('cmshare'): cloud.pop('cmshare') cloud['vimeo'] = vid_id else: return "Please enter a video link from Cmshare, Youtube or " \ "Vimeo only" mutator(value)
def get_info_for(self, state_name): """ Get info for state_name """ #Terminology: RFS = required for state ZZZ depends_on = self.depends_on or [] extras = [] checks = self.checks.get(state_name, []) rfs_required = 0 + len(checks) #the number of fields that are RFS rfs_with_value = 0 #the fields RFS that are filled in optional_empty = 0 #fields that are not RFS and are not filled in total_fields = 0 #the grand total of fields rfs_done = 0 #the percentage of fields RFS that are filled in rfs_field_names = [] #the names of fields that are RFS but # have no value rfs_done_field_names = [] #the names of fields that are RFS and #have a value optional_with_value = [] #optional fields that have a value _debug_all_fieldnames = [] #all fieldnames #fields or conditions which have value _debug_required_fields_with_value = [] generic_adapter = queryAdapter(self.context, IRequiredFieldsForState, name=state_name) required_fields = generic_adapter and generic_adapter.fields or [] if not getattr(self.context, 'schema'): info = { 'rfs_done': 0, 'rfs_with_value': 0, 'rfs_required': 0, 'optional_empty': 0, 'total_fields': 0, 'rfs_field_names': 0, 'rfs_done_field_names': 0, 'optional_with_value': 0, 'extra': extras, 'conditions': len(checks), '_debug_all_fieldnames': [], '_debug_required_fields_with_value': [] } return for field in ISchema(self.context).values(): #we assume AT here field_name = field.getName() if field.isMetadata or (field_name in OTHER_METADATA_FIELDS): continue _debug_all_fieldnames.append(field.getName()) total_fields += 1 info = queryMultiAdapter([self.context, field], interface=IValueProvider, name=field_name) if info is None: info = getMultiAdapter( [self.context, field], interface=IValueProvider, ) has_value = info.has_value(state=state_name) if generic_adapter: is_needed = field.getName() in required_fields else: adapter = getMultiAdapter((self.context, field), interface=IFieldIsRequiredForState) is_needed = adapter(state_name) if is_needed: rfs_required += 1 if has_value: _debug_required_fields_with_value.append(field.getName()) rfs_with_value += 1 rfs_done_field_names.append( (field.getName(), field.widget.label)) else: rfs_field_names.append( (field.getName(), field.widget.label)) else: if not has_value: optional_empty += 1 else: optional_with_value.append( (field.getName(), field.widget.label)) for checker, error in checks: _debug_all_fieldnames.append("CONDITION: " + error) if checker(self.context): extras.append(('error', error)) else: rfs_with_value += 1 _debug_required_fields_with_value.append( "CONDITION CHECKS OK: " + error) #We calculate the stats for the dependencies for part in depends_on: _info = IObjectReadiness(part).get_info_for(state_name) rfs_required += _info['rfs_required'] rfs_with_value += _info['rfs_with_value'] total_fields += _info['total_fields'] rfs_field_names += [(t[0] + "_" + part.getId(), t[1]) for t in _info['rfs_field_names']] rfs_done_field_names += [(k[0] + "_" + part.getId(), k[1]) for k in _info['rfs_done_field_names']] #rfs_required or 1 #->avoids division by 0 rfs_done = int( float(rfs_with_value) / float(rfs_required or 1) * 100.0) if not rfs_required: rfs_done = 100 info = { 'rfs_done': rfs_done, 'rfs_with_value': rfs_with_value, 'rfs_required': rfs_required, 'optional_empty': optional_empty, 'total_fields': total_fields, 'rfs_field_names': rfs_field_names, 'rfs_done_field_names': rfs_done_field_names, 'optional_with_value': optional_with_value, 'extra': extras, #extra messages that will be displayed in the # portlet, in the form of tuples 'conditions': len(checks), '_debug_all_fieldnames': _debug_all_fieldnames, '_debug_required_fields_with_value': _debug_required_fields_with_value } return info