def testChangeSetFolderReordered(self): self.setupTestFolders() if safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsToTop'): self.folder.copy_of_folder1.moveObjectsToTop(['doc3']) elif safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsByDelta'): self.folder.copy_of_folder1.moveObjectsByDelta(['doc3'], -3) else: # We don't have an orderable folder give up return self.cs.computeDiff(self.folder.folder1, self.folder.copy_of_folder1) diffs = self.cs.getDiffs() self.assertEqual(len(diffs), 14) self.assertTrue(diffs[0].same) self.assertFalse(self.cs._added) self.assertFalse(self.cs._removed) sub_cs = self.cs.getSubDiffs() self.assertEqual(len(sub_cs), 3) # The sub diffs should show no changes for i in range(len(sub_cs)): self.assertTrue(isinstance(sub_cs[i], BaseChangeSet)) sub_diffs = sub_cs[i].getDiffs() self.assertEqual(len(sub_diffs), 15) self.assertTrue(sub_diffs[0].same)
def suggestions(self): """Get suggestions from spellcheck component. """ if not safe_hasattr(self, 'solr_response'): return [] suggested_terms = [] search_terms = [ term.lower() for term in self.request.form.get('SearchableText', '').split() ] query_params = self.request.form.copy() if safe_hasattr(self.solr_response, 'spellcheck'): suggestions = self.solr_response.spellcheck.get('suggestions', []) for term in search_terms: if term in suggestions: suggestion = suggestions[term]['suggestion'] query_params['SearchableText'] = suggestion[0]['word'] query_string = '' for k, v in query_params.items(): if isinstance(v, list): query_string += '&' + '&'.join( ['%s=%s' % (k, vv) for vv in v]) else: query_string += '&%s=%s' % (k, v) suggested_terms.append( (suggestion[0]['word'], query_string)) return suggested_terms
def __init__(self, obj1, obj2, field, id1=None, id2=None, field_name=None, field_label=None, schemata=None): self.field = field self.oldValue = _getValue(obj1, field, field_name) self.newValue = _getValue(obj2, field, field_name) self.same = (self.oldValue == self.newValue) if not id1 and safe_hasattr(obj1, 'getId'): id1 = obj1.getId() if not id2 and safe_hasattr(obj2, 'getId'): id2 = obj2.getId() self.id1 = id1 self.id2 = id2 self.label = field_label or field self.schemata = schemata or 'default' fld1 = _getValue(obj1, field, field_name, convert_to_str=False) fld2 = _getValue(obj2, field, field_name, convert_to_str=False) if safe_hasattr(fld1, 'getFilename'): self.oldFilename = fld1.getFilename() else: self.oldFilename = None if safe_hasattr(fld2, 'getFilename'): self.newFilename = fld2.getFilename() else: self.newFilename = None if self.oldFilename is not None and self.newFilename is not None \ and self.same: self.same = (self.oldFilename == self.newFilename)
def importVarious(context): """ Final PFGDataGrid import steps. """ # Only run step if a flag file is present (e.g. not an extension profile) if context.readDataFile('pfgdatagrid-various.txt') is None: return site = context.getSite() ####################### # Both PloneFormGen and the target field provider are going to have # to be installed first. So, let's check. portal_skins = getToolByName(site, 'portal_skins') assert safe_hasattr(portal_skins, 'DataGridWidget'), "DataGridField must be installed prior to installing this product." assert safe_hasattr(portal_skins, 'PloneFormGen'), "PloneFormGen must be installed prior to installing this product." ####################### # Here's the code specific to making this visible to PloneFormGen classes = listTypes(config.PROJECTNAME) myTypes = [item['name'] for item in classes] portal_types = getToolByName(site, 'portal_types') for typeName in ('FormFolder', 'FieldsetFolder'): ptType = portal_types.getTypeInfo(typeName) ffact = list(ptType.allowed_content_types) ffact += myTypes ptType.manage_changeProperties(allowed_content_types=ffact)
def _getValue(ob, field, field_name, convert_to_str=True): # Check for the attribute without acquisition. If it's there, # grab it *with* acquisition, so things like ComputedAttribute # will work if IDexterityContent.providedBy(ob) and field: value = getattr(ob, field, None) elif field and safe_hasattr(aq_base(ob), field): value = getattr(ob, field) elif safe_hasattr(aq_base(ob), 'getField'): # Archetypes with an adapter extended schema needs special handling field = ob.getField(field_name) if field is None: raise AttributeError(field) value = field.getAccessor(ob) else: raise AttributeError(field) # Handle case where the field is a method try: value = value() except (AttributeError, TypeError): pass if convert_to_str: # If this is some object, convert it to a string try: if isinstance(value, Acquisition.Implicit): value = str(value) except TypeError: pass return value
def handle_enable_user_folders(obj, event): """Additional configuration when the ``enable_user_folders`` setting is updated in the ``Security```control panel. If the setting is enabled, a new user action is added with a link to the personal folder. If the setting is disabled, the action is hidden. """ if event.record.fieldName != 'enable_user_folders': return portal = getSite() value = event.newValue membership = getToolByName(portal, 'portal_membership') membership.memberareaCreationFlag = value # support the 'my folder' user action #8417 portal_actions = getToolByName(portal, 'portal_actions', None) if portal_actions is not None: object_category = getattr(portal_actions, 'user', None) if value and not safe_hasattr(object_category, 'mystuff'): # add action _add_mystuff_action(object_category) elif safe_hasattr(object_category, 'mystuff'): a = getattr(object_category, 'mystuff') a.visible = bool(value) # show/hide action
def testChangeSetFolderReordered(self): self.setupTestFolders() if safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsToTop'): self.folder.copy_of_folder1.moveObjectsToTop(['doc3']) elif safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsByDelta'): self.folder.copy_of_folder1.moveObjectsByDelta(['doc3'], -3) else: # We don't have an orderable folder give up return self.cs.computeDiff(self.folder.folder1, self.folder.copy_of_folder1) diffs = self.cs.getDiffs() self.assertEqual(len(diffs), 14) self.assertTrue(diffs[0].same) self.assertFalse(self.cs._added) self.assertFalse(self.cs._removed) sub_cs = self.cs.getSubDiffs() self.assertEqual(len(sub_cs), 3) # The sub diffs should show no changes for i in range(len(sub_cs)): self.assertTrue(isinstance(sub_cs[i], BaseChangeSet)) sub_diffs = sub_cs[i].getDiffs() self.assertEqual(len(sub_diffs), self.len_diff) self.assertTrue(sub_diffs[0].same)
def get_acquired_base_object(minisite_obj, path): obj = minisite_obj path = path.split('@@')[0] contents = path.strip('/').split('/') parent_id = contents[0] child_id = len(contents) > 1 and contents[1] or None while not IPloneSiteRoot.providedBy(obj): parent = aq_parent(aq_inner(obj)) if parent is None: break obj = parent if safe_hasattr(aq_base(obj), parent_id): if not child_id: return obj container = getattr(aq_base(obj), parent_id) if safe_hasattr(container, child_id): try: obj_url = '/'.join(obj.getPhysicalPath()) full_url = "{0}{1}".format( obj_url, path, ) api.content.get(full_url) except Unauthorized: continue except NotFound: continue else: return obj
def populate_with_object(self, obj): """Tile can be populated with images and links; in this case we're not going to take care of any modification of the original object; we just copy the data to the tile and deal with it. """ if obj.portal_type not in self.accepted_ct(): return super(BannerTile, self).populate_with_object(obj) # check permissions obj = aq_base(obj) # avoid acquisition title = obj.Title() rights = obj.Rights() if safe_hasattr(obj, "Rights") else None # if image, store a copy of its data if obj.portal_type == "Image": if safe_hasattr(obj, "getImage"): data = obj.getImage().data else: data = obj.image.data image = NamedBlobImage(data) else: image = None image_description = obj.Description() or obj.Title() remote_url = obj.getRemoteUrl() if obj.portal_type == "Link" else None data_mgr = ITileDataManager(self) data_mgr.set( { "title": title, "image": image, "image_description": image_description, "remote_url": remote_url, "rights": rights, } )
def suggestions(self): """Get suggestions from spellcheck component. """ if not safe_hasattr(self, 'solr_response'): return [] suggested_terms = [] search_terms = [term.lower() for term in self.request.form.get( 'SearchableText', '').split()] query_params = self.request.form.copy() if safe_hasattr(self.solr_response, 'spellcheck'): suggestions = self.solr_response.spellcheck.get('suggestions', []) for term in search_terms: if not isinstance(term, unicode): term = term.decode('utf-8') if term in suggestions: suggestion = suggestions[term]['suggestion'] query_params['SearchableText'] = suggestion[0]['word'] query_string = '' for k, v in query_params.items(): if isinstance(v, list): query_string += '&' + '&'.join( ['%s=%s' % (k, vv) for vv in v]) else: query_string += '&%s=%s' % (k, v) suggested_terms.append((suggestion[0]['word'], query_string)) return suggested_terms
def fgPrimeDefaults(self, request, contextObject=None): """ primes request with default """ value = None # try and look up the current state formFolder = self.formFolderObject() if formFolder.getAllowEditPrevious(): value = formFolder.getExistingValue(self.aq_base) # the field macros will try to get the field value # via Field.getEditAccessor. Unfortunately, it looks for it # as an attribute of the object, not the field. # so, communicate via the request, but don't overwrite # what's already there. if value is None: if safe_hasattr(self, 'getFgTDefault') and self.getRawFgTDefault(): if contextObject: # see note in fgvalidate value = self.getFgTDefault(expression_context=getExprContext(self, contextObject)) else: value = self.getFgTDefault() if (value is None) and safe_hasattr(self, 'getFgDefault'): value = self.getFgDefault() if value: request.form.setdefault(self.fgField.__name__, value)
def importVarious(context): """ Final PFGDataGrid import steps. """ # Only run step if a flag file is present (e.g. not an extension profile) if context.readDataFile('pfgdatagrid-various.txt') is None: return site = context.getSite() ####################### # Both PloneFormGen and the target field provider are going to have # to be installed first. So, let's check. portal_skins = getToolByName(site, 'portal_skins') assert safe_hasattr( portal_skins, 'DataGridWidget' ), "DataGridField must be installed prior to installing this product." assert safe_hasattr( portal_skins, 'PloneFormGen' ), "PloneFormGen must be installed prior to installing this product." ####################### # Here's the code specific to making this visible to PloneFormGen classes = listTypes(config.PROJECTNAME) myTypes = [item['name'] for item in classes] portal_types = getToolByName(site, 'portal_types') for typeName in ('FormFolder', 'FieldsetFolder'): ptType = portal_types.getTypeInfo(typeName) ffact = list(ptType.allowed_content_types) ffact += myTypes ptType.manage_changeProperties(allowed_content_types=ffact)
def cleanup_stored_refs(obj): """Cleanup new dx item.""" if safe_hasattr(obj, '_relatedItems'): del obj._relatedItems if safe_hasattr(obj, '_backrefs'): del obj._backrefs if safe_hasattr(obj, '_relatedItemsOrder'): del obj._relatedItemsOrder
def set_smtp_userid(self, value): if safe_hasattr(self.mail_settings, 'smtp_userid'): self.mail_settings.smtp_userid = value # SecureMailhost 1.x also uses this: if safe_hasattr(self.mail_settings, '_smtp_userid'): self.mail_settings._smtp_userid = value elif safe_hasattr(self.mail_settings, 'smtp_userid'): self.mail_settings.smtp_uid = value
def set_smtp_userid(self, value): if safe_hasattr(self.context, 'smtp_userid'): self.context.smtp_userid = value #SecureMailhost 1.x also uses this: if safe_hasattr(self.context, '_smtp_userid'): self.context._smtp_userid = value elif safe_hasattr(self.context, 'smtp_uid'): self.context.smtp_uid = value
def convert_to_object(self, obj): """ Converts object if object has getObject() attribute. """ if safe_hasattr(obj, 'getObject'): obj = obj.getObject() elif safe_hasattr(obj, 'object'): obj = obj.object return obj
def set_smtp_pass(self, value): # Don't update the value, if we don't get a new one if value is not None: if safe_hasattr(self.mail_settings, 'smtp_pass'): self.mail_settings.smtp_pass = value # SecureMailhost 1.x also uses this: if safe_hasattr(self.mail_settings, '_smtp_pass'): self.mail_settings._smtp_pass = value elif safe_hasattr(self.mail_settings, 'smtp_pwd'): self.mail_settings.smtp_pwd = value
def _has_image_field(self, obj): """Return True if the object has an image field. :param obj: [required] :type obj: content object """ if safe_hasattr(obj, 'image'): # Dexterity return True elif safe_hasattr(obj, 'Schema'): # Archetypes return 'image' in obj.Schema().keys() else: return False
def set_enable_user_folders(self, value): self.pmembership.memberareaCreationFlag = value # support the 'my folder' user action #8417 portal_actions = getToolByName(self.portal, 'portal_actions', None) if portal_actions is not None: object_category = getattr(portal_actions, 'user', None) if value and not safe_hasattr(object_category, 'mystuff'): # add action self.add_mystuff_action(object_category) elif safe_hasattr(object_category, 'mystuff'): a = getattr(object_category, 'mystuff') a.visible = bool(value) # show/hide action
def snippets(self): """Return snippets with highlighted search terms in a dict with the item's UID as key and the snippet text as value. """ if not safe_hasattr(self, 'solr_response'): return {} if safe_hasattr(self.solr_response, 'highlighting'): joined_snippets = {} for uid, snippets in self.solr_response.highlighting.items(): joined_snippets[uid] = ' '.join([' '.join(snippet) for snippet in snippets.values()]).strip() return joined_snippets return {}
def migrate_users(context, mapping, mode='move', replace=False): """Migrate Plone users.""" # Statistics moved = [] copied = [] deleted = [] uf = getToolByName(context, 'acl_users') for old_userid, new_userid in mapping.items(): users = uf.searchUsers(id=old_userid) if len(users) > 0: for user in users: plugin = uf.get(user['pluginid']) # Only ZODB User Manager is supported if (safe_hasattr(plugin, '_user_passwords') and safe_hasattr(plugin, '_login_to_userid') and safe_hasattr(plugin, '_userid_to_login')): pw = plugin._user_passwords[old_userid] login = plugin._userid_to_login[old_userid] # Do nothing if a user with new_userid already exists and # replace is False. if new_userid in plugin._user_passwords and not replace: continue if mode in ['move', 'delete']: del plugin._user_passwords[old_userid] del plugin._userid_to_login[old_userid] del plugin._login_to_userid[login] if mode in ['copy', 'move']: # If userid and login are the same or if in copy mode, # set login to new userid. if login == old_userid or mode == 'copy': login = new_userid plugin._user_passwords[new_userid] = pw plugin._login_to_userid[login] = new_userid plugin._userid_to_login[new_userid] = login if mode == 'move': moved.append(('acl_users', old_userid, new_userid)) if mode == 'copy': copied.append(('acl_users', old_userid, new_userid)) if mode == 'delete': deleted.append(('acl_users', old_userid, None)) return(dict(moved=moved, copied=copied, deleted=deleted))
def snippets(self): """Return snippets with highlighted search terms in a dict with the item's UID as key and the snippet text as value. """ if not safe_hasattr(self, 'solr_response'): return {} if safe_hasattr(self.solr_response, 'highlighting'): joined_snippets = {} for uid, snippets in self.solr_response.highlighting.items(): joined_snippets[uid] = ' '.join([ ' '.join(snippet) for snippet in snippets.values() ]).strip() return joined_snippets return {}
def htmlValue(self, REQUEST): """ return from REQUEST, this field's value, rendered as XHTML. In this case, a definition list. """ value = REQUEST.form.get(self.__name__, "No Input") if not (safe_hasattr(value, "get") and safe_hasattr(value, "len") and len(value)): return fieldsBase.BaseFormField.htmlValue(self, REQUEST) res = "<dl>\n" for i in range(len(value)): label = self.fgField.questionSet[i] response = value.get(str(i + 1), "") res = "%s<dt>%s</dt><dd>%s</dd>\n" % (res, cgi.escape(label), cgi.escape(response)) return "%s</dl>\n" % res
def stringify(self, value): """Convert value to string This method is used to generate a simple JSON representation of the object (without dereferencing objects etc.) """ # SuperModel -> UID if ISuperModel.providedBy(value): return str(value) # DateTime -> ISO8601 format elif isinstance(value, (DateTime)): return value.ISO8601() # Image/Files -> filename elif safe_hasattr(value, "filename"): return value.filename # Dict -> convert_value_to_string elif isinstance(value, dict): return {k: self.stringify(v) for k, v in value.iteritems()} # List -> convert_value_to_string if isinstance(value, (list, tuple, LazyMap)): return map(self.stringify, value) # Callables elif safe_callable(value): return self.stringify(value()) elif isinstance(value, unicode): value = value.encode("utf8") try: return str(value) except (AttributeError, TypeError, ValueError): logger.warn("Could not convert {} to string".format(repr(value))) return None
def scale(instance, data, w, h, default_format='PNG'): """ scale image""" size = int(w), int(h) original_file = StringIO(data) image = PIL.Image.open(original_file) format = image.format #does not work for sizes='inscanteMethod' since we don't have an instance here availableSizes = instance.getAvailableSizes(None) if safe_hasattr(instance, 'crop_scales'): #if our field defines crop_scales let's see if the current sizes shall be cropped if size in [availableSizes[name] for name in instance.crop_scales]: image = crop(image, size) original_mode = image.mode if original_mode == '1': image = image.convert('L') elif original_mode == 'P': image = image.convert('RGBA') image.thumbnail(size, instance.pil_resize_algo) format = format or default_format if original_mode == 'P' and format == 'GIF': image = image.convert('P') thumbnail_file = StringIO() image.save(thumbnail_file, format, quality=instance.pil_quality) thumbnail_file.seek(0) return thumbnail_file, format.lower()
def get_image_data(self, obj): """Get image data from the object used to populate the tile. :param obj: object used to populate the tile :type obj: content type instance :returns: image :rtype: NamedBlobImage instance or None """ image = None scale = self.scale # if has image, store a copy of its data if self._has_image_field(obj) and self._field_is_visible('image'): scales = obj.restrictedTraverse('@@images') image = scales.scale('image', scale) if image is not None and image != '': if isinstance(image.data, NamedBlobImage): # Dexterity image = image.data else: # Archetypes data = image.data if safe_hasattr(data, 'data'): # image data weirdness... data = data.data image = NamedBlobImage(data) return image
def __call__(self, value, *args, **kwargs): #import pdb; pdb.set_trace() field = kwargs.get('field', None) widget = getattr(field, 'widget', None) # get maxlength if kwargs.has_key('maxlength'): maxlength = kwargs.get('maxlength') elif safe_hasattr(widget, 'maxlength'): maxlength = int(widget.maxlength or 0) else: # set to given default value (default defaults to 0) maxlength = self.maxlength if maxlength == 0: return 1 nval = len(value) if nval <= maxlength: return 1 else: return ("Validation failed(%(name)s): '%(value)s' is too long. Must be no longer than %(max)s characters." % { 'name' : self.name, 'value': getattr(widget, 'label', 'Entry'), 'max' : maxlength,})
def create_or_modify_content(self, tus_upload): metadata = tus_upload.metadata() filename = metadata.get("filename", "") content_type = metadata.get("content-type", "application/octet-stream") mode = metadata.get("mode", "create") fieldname = metadata.get("fieldname") if mode == "create": type_ = metadata.get("@type") if type_ is None: ctr = getToolByName(self.context, "content_type_registry") type_ = ctr.findTypeName(filename.lower(), content_type, "") or "File" obj = create(self.context, type_) else: obj = self.context if not fieldname: info = IPrimaryFieldInfo(obj, None) if info is not None: fieldname = info.fieldname elif base_hasattr(obj, "getPrimaryField"): field = obj.getPrimaryField() fieldname = field.getName() if not fieldname: return self.error("Bad Request", "Fieldname required", 400) # Acquisition wrap temporarily for deserialization temporarily_wrapped = False if IAcquirer.providedBy(obj) and not safe_hasattr(obj, "aq_base"): obj = obj.__of__(self.context) temporarily_wrapped = True # Update field with file data deserializer = queryMultiAdapter((obj, self.request), IDeserializeFromJson) if deserializer is None: return self.error( "Not Implemented", f"Cannot deserialize type {obj.portal_type}", 501, ) try: deserializer(data={fieldname: tus_upload}, create=mode == "create") except DeserializationError as e: return self.error("Deserialization Error", str(e), 400) if temporarily_wrapped: obj = aq_base(obj) if mode == "create": if not getattr(deserializer, "notifies_create", False): notify(ObjectCreatedEvent(obj)) obj = add(self.context, obj) tus_upload.close() tus_upload.cleanup() self.request.response.setHeader("Location", obj.absolute_url())
def migrate_imagefield(src_obj, dst_obj, src_fieldname, dst_fieldname): """ migrate an image field. This field needs to be migrated with an NamedBlobImage instance. """ # get old image data and filename old_image = src_obj.getField(src_fieldname).get(src_obj) if old_image == '': return filename = safe_unicode(old_image.filename) old_image_data = old_image.data if safe_hasattr(old_image_data, 'data'): old_image_data = old_image_data.data # create the new image field namedblobimage = NamedBlobImage(data=old_image_data, filename=filename) # set new field on destination object setattr(dst_obj, dst_fieldname, namedblobimage) # handle a possible image caption field # postulate is the old caption field name is ending by 'Caption' # and the new field name is ending by '_caption' # is this postulate correct ? # should this field not be handle by itself because it will appear in the # old field list ? caption_field = src_obj.getField('%sCaption' % src_fieldname, None) if caption_field: setattr(dst_obj, ('%s_caption' % dst_fieldname), safe_unicode(caption_field.get(src_obj))) logger.info("Migrating image %s" % filename)
def _enabled_for_dexterity_types(self): """ Returns True if discussion is enabled for this conversation. This method checks five different settings in order to figure out if discussion is enable on a specific content object: 1) Check if discussion is enabled globally in the plone.app.discussion registry/control panel. 2) Check if the allow_discussion boolean flag on the content object is set. If it is set to True or False, return the value. If it set to None, try further. 3) Check if discussion is allowed for the content type. """ context = aq_inner(self.context) # Fetch discussion registry registry = queryUtility(IRegistry) settings = registry.forInterface(IDiscussionSettings, check=False) # Check if discussion is allowed globally if not settings.globally_enabled: return False # Check if discussion is allowed on the content object if safe_hasattr(context, 'allow_discussion'): if context.allow_discussion is not None: return context.allow_discussion # Check if discussion is allowed on the content type portal_types = getToolByName(self, 'portal_types') document_fti = getattr(portal_types, context.portal_type) return document_fti.getProperty('allow_discussion')
def __call__(self, value, *args, **kwargs): #import pdb; pdb.set_trace() field = kwargs.get('field', None) widget = getattr(field, 'widget', None) # get maxlength if kwargs.has_key('maxlength'): maxlength = kwargs.get('maxlength') elif safe_hasattr(widget, 'maxlength'): maxlength = int(widget.maxlength or 0) else: # set to given default value (default defaults to 0) maxlength = self.maxlength if maxlength == 0: return 1 # The char count must match the javascript char count. To do so, # we have to replace the newlines and use the unicode value of the # string to get an accurate count when special chars are present. value = value.replace('\r\n', '\n') try: nval = len(value.decode('utf-8')) except UnicodeDecodeError: nval = len(value) if nval <= maxlength: return 1 else: return ("Validation failed(%(name)s): '%(value)s' is too long. Must be no longer than %(max)s characters." % { 'name' : self.name, 'value': getattr(widget, 'label', 'Entry'), 'max' : maxlength,})
def migrate_blobimagefield(src_obj, dst_obj, src_fieldname, dst_fieldname): """ migrate an image field. Actually this field needs only to copy the existing NamedBlobImage instance to the new dst_obj, but we do some more in detail and create new fields. """ old_image = getattr(src_obj, src_fieldname) if old_image == '': return filename = safe_unicode(old_image.filename) old_image_data = old_image.data if safe_hasattr(old_image_data, 'data'): old_image_data = old_image_data.data namedblobimage = NamedBlobImage(data=old_image_data, filename=filename) # set new field on destination object setattr(dst_obj, dst_fieldname, namedblobimage) # handle a possible image caption field field = '{0}_caption'.format(src_fieldname) old_image_caption = getattr(src_obj, field, None) if old_image_caption: setattr(dst_obj, ('{0}_caption'.format(dst_fieldname)), safe_unicode(old_image_caption)) logger.info('Migrating image {0}'.format(filename))
def computeDiff(self, ob1, ob2, id1=None, id2=None): """Compute the differences between two objects and return the results as a list. Each object in the list will implement the IDifference interface""" # Try to get the portal type from obj1 first. If that fails, use obj2 pt_name = '' try: pt_name = aq_base(ob1).portal_type except AttributeError: try: pt_name = aq_base(ob2).portal_type except AttributeError: pass diff_map = self._pt_diffs.get(pt_name, {}) diffs = [] for field, klass_name in diff_map.items(): klass = self._difftypes[klass_name] f_diff = klass(ob1, ob2, field, id1=id1, id2=id2) # handle compound diff types if safe_hasattr(f_diff, '__getitem__'): diffs.extend(f_diff) else: diffs.append(f_diff) return diffs
def __call__(self, value, *args, **kwargs): field = kwargs.get("field", None) widget = getattr(field, "widget", None) # get maxlength if "maxlength" in kwargs: maxlength = kwargs.get("maxlength") elif safe_hasattr(widget, "maxlength"): maxlength = int(widget.maxlength or 0) else: # set to given default value (default defaults to 0) maxlength = self.maxlength if maxlength == 0: return 1 decoded = value.replace("\r\n", "\n").decode("utf8") nval = len(decoded) if nval <= maxlength: return 1 else: return ( "Validation failed(%(name)s): '%(value)s' is too long. Must be no longer than %(max)s characters." % {"name": self.name, "value": getattr(widget, "label", "Entry"), "max": maxlength} )
def set_vcge(obj, skos): """ Armazena valores no atributo VCGE de um objeto """ if safe_hasattr(aq_base(obj), 'skos'): obj.skos = skos return True
def SearchableText_AgendaDiaria(obj): """ Indexa os dados dos compromissos dentro desta AgendaDiaria para prover busca por texto integral """ children = obj.objectValues() SearchableText = [] for child in children: if not ICompromisso.providedBy(child): continue # Campos indexaveis SearchableText.append(child.title) SearchableText.append(child.description) SearchableText.append(child.autoridade) SearchableText.append(child.location) SearchableText.append(child.attendees) if not SearchableText: SearchableText.append(obj.autoridade) SearchableText.append(obj.location) # Alteracao da agenda update = obj.update if safe_hasattr(update, 'output'): update = update.output SearchableText.append(update) return ' '.join( [text for text in SearchableText if isinstance(text, basestring)])
def __call__(self, value, *args, **kwargs): field = kwargs.get('field', None) widget = getattr(field, 'widget', None) # get maxlength if 'maxlength' in kwargs: maxlength = kwargs.get('maxlength') elif safe_hasattr(widget, 'maxlength'): maxlength = int(widget.maxlength or 0) else: # set to given default value (default defaults to 0) maxlength = self.maxlength if maxlength == 0: return 1 decoded = value.replace('\r\n', '\n').decode('utf-8') nval = len(decoded) if nval <= maxlength: return 1 else: return ( "Validation failed(%(name)s): '%(value)s' is too long. Must be no longer than %(max)s characters." % { 'name': self.name, 'value': getattr(widget, 'label', 'Entry'), 'max': maxlength })
def __call__(self, value, *args, **kwargs): #import pdb; pdb.set_trace() field = kwargs.get('field', None) widget = getattr(field, 'widget', None) # get maxlength if kwargs.has_key('maxlength'): maxlength = kwargs.get('maxlength') elif safe_hasattr(widget, 'maxlength'): maxlength = int(widget.maxlength or 0) else: # set to given default value (default defaults to 0) maxlength = self.maxlength if maxlength == 0: return 1 nval = len(value) if nval <= maxlength: return 1 else: return ( "Validation failed(%(name)s): '%(value)s' is too long. Must be no longer than %(max)s characters." % { 'name': self.name, 'value': getattr(widget, 'label', 'Entry'), 'max': maxlength, })
def mark_file(ob, event): if safe_hasattr(ob, 'getFile'): obfile = ob.getFile() reindex = False set_track_view = False for name, adapter in getAdapters((obfile,), ITypeRecognition): iface = adapter.getIface() if adapter.isOfType(): if not iface.providedBy(ob): alsoProvides(ob, iface) reindex = True # if there is set an interface, I also want to switch the view set_track_view = True # ok, found the type. do not check any more. break else: if iface.providedBy(ob): # remove the marker if the file type changed! noLongerProvides(ob, iface) reindex = True if set_track_view: # if at least one interface is set, switch the view. ob.setLayout('track_view') else: # reset the view ob.setLayout(ob.getDefaultLayout()) # we need to reindex the object, because ObjectEditedEvent is fired # after reindexing if reindex: # TODO: just reindex object_provides? ob.reindexObject()
def setMemberProperties(self, member, REQUEST=None, **properties): # Set the member properties. When changing the e-mail # address, also update the login name. And make the e-mail # address lowercase. pas = getToolByName(self, 'acl_users') if safe_hasattr(member, 'getId'): member_id = member.getId() else: member_id = member user = pas.getUserById(member_id) update_login_name = False if 'email' in properties: new_email = properties.get('email') if new_email != new_email.lower(): new_email = new_email.lower() properties['email'] = new_email if REQUEST is not None and 'email' in REQUEST: REQUEST['email'] = new_email old_email = user.getProperty('email') if new_email != old_email: update_login_name = True user.setProperties(**properties) if update_login_name: logger.info("Updating login name from %s to %s", old_email, new_email) userfolder = pas.source_users try: userfolder.updateUser(member_id, new_email) except KeyError: raise ValueError('you are not a Plone member (you are ' 'probably registered on the root user ' 'folder, please notify an administrator if ' 'this is unexpected)')
def getContextInfo(self, context=None): if context is None: context = self.context context = aq_inner(context) info = '' context_name = context.Title() context_url = context.absolute_url() context_type = context.Type() del_url = context_url # TODO: we should check errors in the delete process, and # broadcast those to the error template in JS info = {'name': context_name, 'title': context_name, 'description': context.Description(), 'rights': context.Rights(), 'url': context_url, 'delete_url': del_url, 'delete_type': 'DELETE', } if safe_hasattr(context, 'size'): info['size'] = context.size() else: if context_type == 'File': info['size'] = context.file.getSize() elif context_type == 'Image': info['size'] = context.image.getSize() if context_type == 'Image': scales = context.restrictedTraverse('@@images') thumb = scales.scale(fieldname='image', scale='thumb') info['thumbnail_url'] = thumb.url return info
def __new__(cls, context): instance = super(NameFromFileName, cls).__new__(cls) if safe_hasattr(context, 'title') and not context.title: file_field = None for i in iterSchemata(context): fields = getFieldsInOrder(i) for name, field in fields: if isinstance(field, NamedBlobFile): file_field = field break if file_field is None: return None filename = getattr(file_field.get(context), 'filename', None) if not isinstance(filename, basestring) or not filename: return None title = filename context.title = title else: instance = super(NameFromFileName, cls).__new__(cls) title = context.title instance.title = title return instance
def computeDiff(self, ob1, ob2, id1=None, id2=None): """Compute the differences between two objects and return the results as a list. Each object in the list will implement the IDifference interface""" # Try to get the portal type from obj1 first. If that fails, use obj2 pt_name = "" try: pt_name = aq_base(ob1).portal_type except AttributeError: try: pt_name = aq_base(ob2).portal_type except AttributeError: pass diff_map = self._pt_diffs.get(pt_name, {}) diffs = [] for field, klass_name in diff_map.items(): klass = self._difftypes[klass_name] f_diff = klass(ob1, ob2, field, id1=id1, id2=id2) # handle compound diff types if safe_hasattr(f_diff, "__getitem__"): diffs.extend(f_diff) else: diffs.append(f_diff) return diffs
def brains(self): """ Brains of collections or folderish content """ if safe_hasattr(aq_base(self.context), 'queryCatalog'): return self.context.queryCatalog(batch=False)[:self.maxbreadth] else: return self.context.getFolderContents()[:self.maxbreadth]
def onSuccess(self, fields, REQUEST=None, loopstop=False): # """ # saves data. # """ if LP_SAVE_TO_CANONICAL and not loopstop: # LinguaPlone functionality: # check to see if we're in a translated # form folder, but not the canonical version. parent = self.aq_parent if safe_hasattr(parent, 'isTranslation') and \ parent.isTranslation() and not parent.isCanonical(): # look in the canonical version to see if there is # a matching (by id) save-data adapter. # If so, call its onSuccess method cf = parent.getCanonical() target = cf.get(self.getId()) if target is not None and target.meta_type == 'FormSaveDataAdapter': target.onSuccess(fields, REQUEST, loopstop=True) return from ZPublisher.HTTPRequest import FileUpload data = [] for f in fields: showFields = getattr(self, 'showFields', []) if showFields and f.id not in showFields: continue if f.isFileField(): file = REQUEST.form.get('%s_file' % f.fgField.getName()) if isinstance(file, FileUpload) and file.filename != '': file.seek(0) fdata = file.read() filename = file.filename mimetype, enc = guess_content_type(filename, fdata, None) if mimetype.find('text/') >= 0: # convert to native eols fdata = fdata.replace('\x0d\x0a', '\n').replace('\x0a', '\n').replace('\x0d', '\n') data.append('%s:%s:%s:%s' % (filename, mimetype, enc, fdata)) else: data.append('%s:%s:%s:Binary upload discarded' % (filename, mimetype, enc)) else: data.append('NO UPLOAD') elif not f.isLabel(): val = REQUEST.form.get(f.fgField.getName(), '') if not type(val) in StringTypes: # Zope has marshalled the field into # something other than a string val = str(val) data.append(val) if self.ExtraData: for f in self.ExtraData: if f == 'dt': data.append(str(DateTime())) else: data.append(getattr(REQUEST, f, '')) self._addDataRow(data)
def migrate_blobimagefield(src_obj, dst_obj, src_fieldname, dst_fieldname): """ migrate an image field. Actually this field needs only to copy the existing NamedBlobImage instance to the new dst_obj, but we do some more in detail and create new fields. """ old_image = getattr(src_obj, src_fieldname) if old_image == '': return filename = safe_unicode(old_image.filename) old_image_data = old_image.data if safe_hasattr(old_image_data, 'data'): old_image_data = old_image_data.data namedblobimage = NamedBlobImage(data=old_image_data, filename=filename) # set new field on destination object setattr(dst_obj, dst_fieldname, namedblobimage) # handle a possible image caption field field = '{0}_caption'.format(src_fieldname) old_image_caption = getattr(src_obj, field, None) if old_image_caption: setattr(dst_obj, ('{0}_caption'.format(dst_fieldname)), safe_unicode(old_image_caption)) logger.info(u'Migrating image {0}'.format(filename))
def testChangeSetFolderComplex(self): self.setupTestFolders() # Add a new sub object self.folder.copy_of_folder1.invokeFactory('Document', 'doc4', title='My Doc Title') # Delete a sub object self.folder.copy_of_folder1.manage_delObjects('doc2') # Change one object self.folder.copy_of_folder1.doc3.setTitle('My New Title') # Change the folder itself self.folder.copy_of_folder1.setTitle('My New Title') # Move the changed object if safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsToTop'): self.folder.copy_of_folder1.moveObjectsToTop(['doc3']) elif safe_hasattr(aq_base(self.folder.copy_of_folder1), 'moveObjectsByDelta'): self.folder.copy_of_folder1.moveObjectsByDelta(['doc3'], -3) else: # We don't have an orderable folder give up return self.cs.computeDiff(self.folder['folder1'], self.folder['copy_of_folder1']) diffs = self.cs.getDiffs() self.assertEqual(len(diffs), 14) self.assertFalse(diffs[0].same) self.assertEqual(diffs[0].ndiff(), '- My Folder Title%s+ My New Title' % linesep) self.assertEqual(list(self.cs._added), ['doc4']) self.assertEqual(list(self.cs._removed), ['doc2']) sub_cs = self.cs.getSubDiffs() # We only have two potentially changed objects self.assertEqual(len(sub_cs), 2) # The sub diffs should show no changes for i in range(len(sub_cs)): self.assertTrue(isinstance(sub_cs[i], BaseChangeSet)) sub_diffs = sub_cs[i].getDiffs() self.assertEqual(len(sub_diffs), self.len_diff) if sub_cs[i].getId() == 'doc3': self.assertFalse(sub_diffs[0].same) self.assertEqual(sub_diffs[0].ndiff(), '- My Title3%s+ My New Title' % linesep) else: self.assertTrue(sub_diffs[1].same)