class PhotoGallery(CodeSource): """A photo gallery to show thumbnails and the original pictures within a Silva document. """ silvaconf.zmi_addable(True) silvaconf.factory('manage_addPhotoGalleryForm') silvaconf.factory('manage_addPhotoGallery') meta_type = 'Silva Photo Gallery Source' security = ClassSecurityInfo() _is_initialized = True def __init__(self, id): super(PhotoGallery, self).__init__(id) self._script_id = 'view' self._data_encoding = 'UTF-8' self._description = self.__doc__ self._is_initialized = False security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'refresh') def refresh(self): """reload the form and pt""" if 'view' in self.objectIds(): self.manage_delObjects(['view']) self._set_form() self._set_views() return 'refreshed form and pagetemplate' def _set_form(self): self.parameters = ZMIForm('form', 'Properties Form') with open(os.path.join(_home, 'photo_gallery_form.form')) as form: XMLToForm(form.read(), self.parameters) def _set_views(self): with open(os.path.join(_home, 'photo_gallery_view.pt')) as template: self._setObject('view', ZopePageTemplate('view', template.read())) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'includeResources') def includeResources(self): need(IPhotoGalleryResources) return u'' security.declareProtected(SilvaPermissions.AccessContentsInformation, 'getPhotos') def getPhotos(self, model): """Returns a sorted list of photos found in the container. """ return model.get_container().get_non_publishables(IImage) security.declarePublic('getCaption') def getCaption(self, caption): lenCaption = 42 if len(caption) < lenCaption: return caption return caption[:lenCaption-3].rstrip() + '...'
class Article(VersionedContent): meta_type = 'My Article' silvaconf.versionClass(ArticleVersion) silvaconf.factory('manage_addMyArticle') customCreation = False # For test only
class SimpleMember(Member, Security, ZMIObject): """Silva Simple Member""" grok.implements(interfaces.IEditableMember) security = ClassSecurityInfo() meta_type = 'Silva Simple Member' silvaconf.icon('icons/member.png') silvaconf.factory('manage_addSimpleMemberForm') silvaconf.factory('manage_addSimpleMember') # BBB _avatar = None def __init__(self, id): self.id = id self._title = id self._fullname = None self._email = None self._avatar = None self._creation_datetime = self._modification_datetime = DateTime() self._is_approved = 0 security.declarePrivate('allowed_roles') def allowed_roles(self): return roleinfo.ASSIGNABLE_ROLES security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'set_fullname') def set_fullname(self, fullname): """set the full name""" self._fullname = fullname security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'set_email') def set_email(self, email): """ set the email address. (does not test, if email address is valid) """ self._email = email security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'set_avatar') def set_avatar(self, avatar): """Set the email address to be used by gravatar""" self._avatar = avatar security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'approve') def approve(self): """Approve the member""" self._is_approved = 1 # ACCESSORS security.declareProtected(SilvaPermissions.AccessContentsInformation, 'userid') def userid(self): """userid """ return self.id security.declareProtected(SilvaPermissions.AccessContentsInformation, 'fullname') def fullname(self): """fullname """ if self._fullname is None: return self.id return self._fullname security.declareProtected(SilvaPermissions.AccessContentsInformation, 'email') def email(self): """email """ return self._email security.declareProtected(SilvaPermissions.AccessContentsInformation, 'extra') def extra(self, name): """Return bit of extra information, keyed by name. """ #For CachedMember accessing of the avatar tag #Should be 'avatar_tag:SIZE' -- ie, 'avatar_tag:32' if name.startswith("avatar_tag"): return self.avatar_tag(name.split(':')[1]) return None security.declareProtected(SilvaPermissions.AccessContentsInformation, 'avatar') def avatar(self): """Return the email address to be used by gravatar. Return '' if no address has been specified. """ return self._avatar if self._avatar is not None else self._email security.declareProtected(SilvaPermissions.AccessContentsInformation, 'is_approved') def is_approved(self): """is_approved """ return self._is_approved
class Root(Publication): """Root of Silva site. """ security = ClassSecurityInfo() meta_type = "Silva Root" # We do not want to register Root automaticaly. grok.implements(IRoot) silvaconf.icon('icons/root.png') silvaconf.zmi_addable(True) silvaconf.factory('manage_addRootForm') silvaconf.factory('manage_addRoot') _smi_skin = 'silva.ui.interfaces.ISilvaUITheme' _properties = Publication._properties + ({ 'id': '_smi_skin', 'label': 'Skin SMI', 'type': 'string', 'mode': 'w' }, ) def __init__(self, id): super(Root, self).__init__(id) # if we add a new root, version starts out as the software version self._content_version = self.get_silva_software_version() # MANIPULATORS security.declareProtected(SilvaPermissions.AccessContentsInformation, 'validate_wanted_quota') def validate_wanted_quota(self, value, REQUEST=None): """Validate the wanted quota is correct the current publication. """ if value < 0: # Quota can't be negative. return False if not value: # 0 or means no quota. return True # Quota can't be be bigger than the site quota. if self.service_extensions._site_quota: if self.service_extensions._site_quota < value: return False return True security.declareProtected(SilvaPermissions.ApproveSilvaContent, 'to_folder') def to_folder(self): """Don't do anything here. Can't do this with root. """ raise ContentError(_("Root cannot be converted to folder."), self) security.declareProtected(SilvaPermissions.ApproveSilvaContent, 'to_publication') def to_publication(self): """Don't do anything here. Can't do this with root. """ raise ContentError(_("Root cannot be converted to publication."), self) security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'add_silva_addable_forbidden') def add_silva_addable_forbidden(self, meta_type): """Add a meta_type that is forbidden from use in this site. """ addables_forbidden = getattr(self.aq_base, '_addables_forbidden', {}) addables_forbidden[meta_type] = 0 self._addables_forbidden = addables_forbidden security.declareProtected(SilvaPermissions.ChangeSilvaAccess, 'clear_silva_addables_forbidden') def clear_silva_addables_forbidden(self): """Clear out all forbidden addables; everything allowed now. """ self._addables_forbidden = {} # ACCESSORS security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_root') def get_root(self): """Get root of site. Can be used with acquisition get the 'nearest' Silva root. """ return self.aq_inner security.declareProtected(SilvaPermissions.ReadSilvaContent, 'is_silva_addable_forbidden') def is_silva_addable_forbidden(self, meta_type): """Return true if addable is forbidden to be used in this site. """ if not hasattr(self.aq_base, '_addables_forbidden'): return False return meta_type in self._addables_forbidden security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_current_quota') def get_current_quota(self): """Return the current quota value on the publication. """ site = getUtility(IExtensionService).get_site_quota() binding = getUtility(IMetadataService).getMetadata(self) try: local = int(binding.get('silva-quota', element_id='quota') or 0) if local < 0: local = 0 except KeyError: local = 0 if site and local: return min(site, local) if site: return site return local security.declarePublic('get_silva_software_version') def get_silva_software_version(self): """The version of the Silva software. """ return extensionRegistry.get_extension('Silva').version security.declareProtected(SilvaPermissions.ReadSilvaContent, 'get_silva_content_version') def get_silva_content_version(self): """Return the version of Silva content. This version is usually the same as the software version, but can be different in case the content was not yet updated. """ return getattr(self, '_content_version', 'before 0.9.2') security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_real_container') def get_real_container(self): """Get the container, even if we're a container. If we're the root object, returns None. Can be used with acquisition to get the 'nearest' container. """ return None
class Image(Asset): __doc__ = _("""Web graphics (gif, jpg, png) can be uploaded and inserted in documents, or used as viewable assets. """) security = ClassSecurityInfo() meta_type = "Silva Image" grok.implements(interfaces.IImage) re_WidthXHeight = re.compile(r'^([0-9]+|\*)[Xx]([0-9\*]+|\*)$') re_percentage = re.compile(r'^([0-9\.]+)\%$') re_box = re.compile(r'^([0-9]+)[Xx]([0-9]+)-([0-9]+)[Xx]([0-9]+)') thumbnail_size = Size(120, 120) image = None hires_image = None thumbnail_image = None web_scale = '100%' web_crop = '' web_format = Format.JPEG web_formats = (Format.JPEG, Format.GIF, Format.PNG) _web2ct = { Format.JPEG: 'image/jpeg', Format.GIF: 'image/gif', Format.PNG: 'image/png', } silvaconf.priority(-3) silvaconf.icon('icons/image.gif') silvaconf.factory('manage_addImage') security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_web_presentation_properties') def set_web_presentation_properties(self, web_format, web_scale, web_crop): """Sets format and scaling for web presentation. web_format (str): either JPEG or PNG (or whatever other format makes sense, must be recognised by PIL). web_scale (str): WidthXHeight or nn.n%. web_crop (str): X1xY1-X2xY2, crop-box or empty for no cropping. Automaticaly updates cached web presentation image. """ update = False if self.hires_image is None: update = True self.hires_image = self.image self.image = None # Set web format. if web_format not in ('unknown', '') and self.web_format != web_format: if web_format in self.web_formats: self.web_format = web_format update = True else: raise ValueError('Unknown image format %s' % web_format) # check if web_scale can be parsed: try: self.get_canonical_web_scale(web_scale) except ValueError: # if not, we set web_scale back to default value web_scale = '100%' if self.web_scale != web_scale: self.web_scale = web_scale update = True # check if web_crop can be parsed: self.get_crop_box(web_crop) if self.web_crop != web_crop: # if web_crop is None it should be replaced by an empty string self.web_crop = web_crop and web_crop or '' update = True if update and self.hires_image is not None: self._create_derived_images() security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_image') def set_image(self, file): """Set the image object. """ validate_image(file) self._image_factory('hires_image', file) # Image change, reset scale, crop box: they can be invalid for # this new image. format = self.get_format() if format in self.web_formats: self.web_format = format self.web_scale = '100%' self.web_crop = '' self._create_derived_images() # XXX Should be on event self.update_quota() security.declareProtected(SilvaPermissions.View, 'get_image') def get_image(self, hires=True, webformat=False): """Return image data. """ if hires: if self.hires_image is not None: if webformat: # Create web format of original image. with ImageFile(self.hires_image) as working: data = working.save(self.web_format) if data is not None: return data.getvalue() # Original format of the original image is the orginal. return self.hires_image.get_file() return None if self.image is not None: if webformat: # Webformat of the cropped/resized image is already computed. return self.image.get_file() # Original format of the cropped/resize image is not possible. raise ValueError( _(u"Low resolution image in original format is " u"not supported")) return None security.declareProtected(SilvaPermissions.View, 'get_canonical_web_scale') def get_canonical_web_scale(self, scale=None): """returns (width, height) of web image""" if scale is None: scale = self.web_scale m = self.re_WidthXHeight.match(scale) if m is None: m = self.re_percentage.match(scale) if m is None: msg = _( "'${scale}' is not a valid scale identifier. " "Probably a percent symbol is missing.", mapping={'scale': scale}) raise ValueError(msg) cropbox = Rect.parse(self.web_crop) if cropbox: width, height = cropbox.size else: width, height = self.get_dimensions() percentage = float(m.group(1)) / 100.0 width = int(width * percentage) height = int(height * percentage) else: img_w, img_h = self.get_dimensions() width = m.group(1) height = m.group(2) if width == height == '*': msg = _( "'${scale} is not a valid scale identifier. " "At least one number is required.", mapping={'scale': scale}) raise ValueError(msg) if width == '*': height = int(height) width = img_w * height / img_h elif height == '*': width = int(width) height = img_h * width / img_w else: width = int(width) return width, height security.declareProtected(SilvaPermissions.View, 'get_crop_box') def get_crop_box(self, crop=None): """return crop box""" crop = crop or self.web_crop if crop is None or crop.strip() == '': return None rect = Rect.parse(crop) if rect is None: msg = _("'${crop} is not a valid crop identifier", mapping={'crop': crop}) raise ValueError(msg) with ImageFile(self.hires_image) as image: Crop(rect).validate(image) return (rect.lower_edge.x, rect.lower_edge.y, rect.higher_edge.x, rect.higher_edge.y) security.declareProtected(SilvaPermissions.View, 'get_dimensions') def get_dimensions(self, thumbnail=False, hires=False): """Returns width, heigt of (hi res) image. Raises ValueError if there is no way of determining the dimenstions, Return 0, 0 if there is no image, Returns width, height otherwise. """ data = None if thumbnail: data = self.thumbnail_image elif hires: data = self.hires_image else: data = self.image if data is None: return Size(0, 0) try: with ImageFile(data) as image: return image.get_size() except (ValueError, TypeError): return Size(0, 0) security.declareProtected(SilvaPermissions.View, 'tag') def tag(self, hires=False, thumbnail=False, request=None, preview=False, **extra_attributes): warnings.warn( 'tag have been replaced with get_html_tag. ' 'It will be removed, please update your code.', DeprecationWarning, stacklevel=2) return self.get_html_tag(hires=hires, thumbnail=thumbnail, request=request, preview=preview, **extra_attributes) security.declareProtected(SilvaPermissions.View, 'get_html_tag') def get_html_tag(self, preview=False, request=None, hires=False, thumbnail=False, **extra_attributes): """ return xhtml tag Since 'class' is a Python reserved word, it cannot be passed in directly in keyword arguments which is a problem if you are trying to use 'tag()' to include a CSS class. The tag() method will accept a 'css_class' argument that will be converted to 'class' in the output tag to work around this. """ url = self.get_download_url(request=request, preview=preview, hires=hires, thumbnail=thumbnail) title = self.get_title_or_id() width, height = self.get_dimensions(thumbnail=thumbnail, hires=hires) if extra_attributes.has_key('css_class'): extra_attributes['class'] = extra_attributes['css_class'] del extra_attributes['css_class'] extra_html_attributes = [ u'{name}="{value}"'.format(name=escape(name, 1), value=escape(value, 1)) for name, value in extra_attributes.iteritems() ] return u'<img src="{src}" width="{width}" height="{height}" ' \ u'alt="{alt}" {extra_attributes} />'.format( src=url, width=str(width), height=str(height), alt=escape(title, 1), extra_attributes=u" ".join(extra_html_attributes)) security.declareProtected(SilvaPermissions.View, 'url') def url(self, hires=False, thumbnail=False, request=None, preview=False): warnings.warn( 'url have been replaced with get_download_url. ' 'It will be removed, please update your code.', DeprecationWarning, stacklevel=2) return self.get_download_url(hires=hires, thumbnail=thumbnail, request=request, preview=preview) security.declareProtected(SilvaPermissions.View, 'get_download_url') def get_download_url(self, preview=False, request=None, hires=False, thumbnail=False): "return url of image" if request is None: request = self.REQUEST url = getMultiAdapter((self, request), IContentURL).url(preview=preview) more = '?' if hires: url += '?hires' more = '&' elif thumbnail: url += '?thumbnail' more = '&' if preview: # In case of preview we add something that change at the # end of the url to prevent caching from the browser. url += more + str(int(time.time())) return url security.declareProtected(SilvaPermissions.View, 'get_web_format') def get_web_format(self): """Return file format of web presentation image """ try: with ImageFile(self.image) as image: return image.get_format() except (ValueError, TypeError): return 'unknown' security.declareProtected(SilvaPermissions.View, 'get_web_scale') def get_web_scale(self): """Return scale percentage / WxH of web presentation image """ return str(self.web_scale) security.declareProtected(SilvaPermissions.View, 'get_web_crop') def get_web_crop(self): """Return crop identifier """ return str(self.web_crop) security.declareProtected(SilvaPermissions.View, 'get_orientation') def get_orientation(self): """Returns translated Image orientation (string). """ width, height = self.get_dimensions() if width == height: return _("square") elif width > height: return _("landscape") return _("portrait") security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'get_file_system_path') def get_file_system_path(self): """return path on filesystem for containing image""" if self.hires_image is not None: return self.hires_image.get_file_system_path() return None security.declareProtected(SilvaPermissions.View, 'get_format') def get_format(self): """Returns image format. """ try: with ImageFile(self.hires_image) as image: return image.get_format() except (ValueError, TypeError): return 'unknown' security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_filename') def get_filename(self): if self.hires_image is None: return self.getId() return self.hires_image.get_filename() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_mime_type') def get_mime_type(self): if self.hires_image is None: return 'application/octet-stream' return self.hires_image.get_mime_type() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_content_type') def get_content_type(self): if self.hires_image is None: return 'application/octet-stream' return self.hires_image.get_content_type() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_file_size') def get_file_size(self): if self.hires_image is None: return 0 return self.hires_image.get_file_size() ########## ## private def _create_derived_images(self): self._create_web_presentation() self._create_thumbnail() def _create_web_presentation(self): try: transformer = Transformer() cropbox = self.get_crop_box() if cropbox is not None: crop_rect = Rect.from_points(Point(cropbox[0], cropbox[1]), Point(cropbox[2], cropbox[3])) transformer.append(Crop(crop_rect)) if self.web_scale != '100%': spec = WHResizeSpec.parse(self.web_scale) if spec is None: spec = PercentResizeSpec.parse(self.web_scale) if spec is not None: transformer.append(Resize(spec)) image_io = transformer.transform(self.hires_image, self.web_format) if image_io: content_type = self._web2ct[self.web_format] self._image_factory('image', image_io, content_type) else: self.image = self.hires_image except IOError as error: logger.error("Web presentation creation failed for %s with %s" % ('/'.join(self.getPhysicalPath()), str(error))) if str(error.args[0]) == "cannot read interlaced PNG files": self.image = self.hires_image return raise ValueError(str(error)) except ValueError as error: logger.error("Web presentation creation failed for %s with %s" % ('/'.join(self.getPhysicalPath()), str(error))) self.image = self.hires_image return def _create_thumbnail(self): try: transformer = Transformer(ThumbnailResize(self.thumbnail_size)) thumb = transformer.transform(self.image or self.hires_image, self.web_format) if thumb: content_type = self._web2ct[self.web_format] self._image_factory('thumbnail_image', thumb, content_type) except IOError as error: logger.info("Thumbnail creation failed for %s with %s" % ('/'.join(self.getPhysicalPath()), str(error))) if str(error.args[0]) == "cannot read interlaced PNG files": self.thumbnail_image = None return else: raise ValueError(str(error)) except ValueError, e: logger.info("Thumbnail creation failed for %s with %s" % ('/'.join(self.getPhysicalPath()), str(e))) # no thumbnail self.thumbnail_image = None return
class CodeSource(EditableExternalSource, Folder, ZMIObject): grok.implements(ICodeSource) # register icon and factories silvaconf.icon('www/codesource.png') silvaconf.factory('manage_addCodeSourceForm') silvaconf.factory('manage_addCodeSource') silvaconf.zmi_addable(True) meta_type = "Silva Code Source" security = ClassSecurityInfo() _data_encoding = 'UTF-8' _fs_location = None _script_layers = [] # ZMI Tabs manage_options = ( { 'label': 'Edit', 'action': 'editCodeSource' }, { 'label': 'Parameters', 'action': 'parameters/manage_main' }, ) + Folder.manage_options management_page_charset = 'utf-8' security.declareProtected(SilvaPermissions.ViewManagementScreens, 'editCodeSource') editCodeSource = PageTemplateFile('www/codeSourceEdit', globals(), __name__='editCodeSource') def __init__(self, id, script_id=None, fs_location=None): super(CodeSource, self).__init__(id) self._script_id = script_id self._fs_location = fs_location security.declareProtected(SilvaPermissions.ViewManagementScreens, 'test_source') def test_source(self): # return a list of problems or None errors = [] # in real life the parent of the form is the document. We try # to do the same here. root = self.get_root() if root.get_default(): root = root.get_default() if self.parameters is not None: try: self.parameters.test_form( context=root, bad_fields=['context', 'content', 'model', 'script']) except ValueError as error: errors.extend(error.args) if not self.title: errors.append(u'Missing required source title.') if not self._script_id: errors.append(u'Missing required renderer id.') else: ids = self.objectIds() scripts = [self._script_id] + map(itemgetter(0), self._script_layers) for script_id in scripts: if script_id not in ids: errors.append( u'Missing renderer %s. Please a script or template with this id.' % (script_id)) if errors: return errors return None security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_icon') def get_icon(self): return self._getOb('icon.png', None) # ACCESSORS security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_script_id') def get_script_id(self): return self._script_id security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_script_layers') def get_script_layers(self): result = [] skin = grok.skin.bind(default=lambda l: l.__identifier__) for script_id, layer in self._script_layers: result.append(":".join((script_id, skin.get(layer)))) return '\n'.join(result) security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_fs_location') def get_fs_location(self): return self._fs_location security.declareProtected(SilvaPermissions.AccessContentsInformation, 'to_html') def to_html(self, content, request, **parameters): """Render HTML for code source """ script = None if self._script_layers: # If there are script_layer, check them first. for script_id, layer in self._script_layers: if layer.providedBy(request): break else: # No matching layer, default. script_id = self._script_id else: # No script_layer, default one. script_id = self._script_id if script_id is not None: script = self._getOb(script_id, None) if script_id is None or script is None: # Missing script return None parameters['REQUEST'] = request if IVersion.providedBy(content): parameters['version'] = content parameters['model'] = content.get_silva_object() else: parameters['version'] = None parameters['model'] = content __traceback_supplement__ = (CodeSourceErrorSupplement, self, parameters) result = script(**parameters) if isinstance(result, unicode): return result return unicode(result, self.get_data_encoding(), 'replace') # MANAGERS security.declareProtected(SilvaPermissions.ViewManagementScreens, 'set_script_id') def set_script_id(self, script_id): self._script_id = script_id security.declareProtected(SilvaPermissions.ViewManagementScreens, 'set_script_layers') def set_script_layers(self, script_layers): found = [] for lineno, line in enumerate(script_layers.strip().splitlines()): entries = line.strip().split(':', 1) if len(entries) != 2: raise ValueError( u'Invalid script layers: invalid form on line %d' % (lineno)) script_id, layer_identifier = entries layer = queryUtility(IBrowserSkinType, name=layer_identifier) if layer is None: raise ValueError( u'Invalid script layer: layer %s not found on line %d' % (layer_identifier, lineno)) found.append((script_id, layer)) self._script_layers = found def _get_installable(self, location=None): """Return the installable source associated with this code source. """ if location is None: location = self.get_fs_location() if location is None: return None service = queryUtility(ICodeSourceService) if service is None: # XXX pre-migration Silva 3.0 service = self.service_codesources candidates = list(service.get_installable_source(location=location)) if len(candidates) == 1: return candidates[0] return None security.declareProtected(SilvaPermissions.ViewManagementScreens, 'manage_getFileSystemLocations') def manage_getFileSystemLocations(self): service = queryUtility(ICodeSourceService) if service is None: # XXX pre-migration Silva 3.0 service = self.service_codesources return map(lambda source: source.location, service.get_installable_source(identifier=self.id)) security.declareProtected(SilvaPermissions.ViewManagementScreens, 'manage_updateCodeSource') def manage_updateCodeSource(self, purge=False, REQUEST=None): """Update a code source from the filesystem. """ installable = self._get_installable() if (installable is None or not os.path.isdir(installable._directory)): if REQUEST is not None: return self.editCodeSource( manage_tabs_message=\ 'Couldn\'t find the code source on the filesystem.') return False installable.update(self, bool(purge)) if REQUEST is not None: return self.editCodeSource( manage_tabs_message='Source updated from the filesystem.') return True security.declareProtected(SilvaPermissions.ViewManagementScreens, 'manage_exportCodeSource') def manage_exportCodeSource(self, aszip=False, dump=False, REQUEST=None): """Export a code source to the filesystem. """ if dump: installable = self._get_installable() if (installable is None or not os.path.isdir(installable._directory)): message = "Couldn't find the code source on the filesystem." else: installable.export(self) message = "Source dumped to the filesystem." if REQUEST is not None: return self.editCodeSource(manage_tabs_message=message) return None directory = tempfile.mkdtemp('-codesource-export') try: CodeSourceExportable().export(self, directory) result = io.BytesIO() archive = zipfile.ZipFile(result, 'w') for path, directories, filenames in os.walk(directory): root = path[len(directory):] if root: root = os.path.join(self.getId(), root) else: root = self.getId() for filename in filenames: archive.write(os.path.join(path, filename), os.path.join(root, filename)) archive.close() finally: shutil.rmtree(directory) if REQUEST is not None: REQUEST.RESPONSE.setHeader('Content-Type', 'application/zip') REQUEST.RESPONSE.setHeader( 'Content-Disposition', 'attachment;filename=%s.zip' % self.getId()) return result.getvalue() security.declareProtected(SilvaPermissions.ViewManagementScreens, 'manage_editCodeSource') def manage_editCodeSource(self, title, script_id, data_encoding, description=None, location=None, cacheable=None, previewable=None, usable=None, script_layers=None): """ Edit a code source settings. """ msg = u'' if location is not None and location != self._fs_location: if location: installable = self._get_installable(location) if installable is None: msg += "Invalid location for the code source " + \ "definition, not changed! " return self.editCodeSource(manage_tabs_message=msg) self._fs_location = location msg += "Code source location changed. " if data_encoding != self._data_encoding: try: unicode('abcd', data_encoding, 'replace') except LookupError: # unknown encoding, return error message msg += "Unknown encoding %s, not changed! " % data_encoding return self.editCodeSource(manage_tabs_message=msg) self.set_data_encoding(data_encoding) msg += u'Data encoding changed. ' if script_layers is not None: try: self.set_script_layers(script_layers) except ValueError as error: msg += "Error while setting script layers: %s" % error.args[0] return self.editCodeSource(manage_tabs_message=msg) title = unicode(title, self.management_page_charset) if title and title != self.title: self.title = title msg += "Title changed. " if script_id and script_id != self._script_id: self._script_id = script_id msg += "Script id changed. " # Assume description is in the encoding as specified # by "management_page_charset". Store it in unicode. if description is not None: description = unicode(description, self.management_page_charset) if description != self._description: self.set_description(description) msg += "Description changed. " if not bool(cacheable) is self.is_cacheable(): self.set_cacheable(bool(cacheable)) msg += "Cacheability setting changed. " if not bool(usable) is self.is_usable(): self.set_usable(bool(usable)) msg += "Usability setting changed. " if not bool(previewable) is self.is_previewable(): self.set_previewable(bool(previewable)) msg += "Previewable setting changed. " return self.editCodeSource(manage_tabs_message=msg)
class File(Asset): __doc__ = """Any digital file can be uploaded as Silva content. For instance large files such as pdf docs or mpegs can be placed in a site. File objects have metadata as well.""" security = ClassSecurityInfo() meta_type = "Silva File" grok.implements(interfaces.IFile) silvaconf.icon('icons/file.png') silvaconf.factory('manage_addFile') # Default values _filename = None _content_encoding = None # ACCESSORS security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_filename') def get_filename(self): """Object's id is filename if not set. """ if self._filename is not None: return self._filename return self.id security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_file_size') def get_file_size(self): """Get the size of the file as it will be downloaded. """ return self._file.get_size() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'get_mime_type') def get_mime_type(self): """Return the content mimetype. """ # possibly strip out charset encoding return self.get_content_type().split(';')[0].strip() security.declareProtected(SilvaPermissions.AccessContentsInformation, 'fulltext') def fulltext(self): """Return the content of this object without any markup """ converter = get_converter_for_mimetype(self.get_mime_type()) fulltext = [self.get_title()] if converter is None: return fulltext text = None filename = self.get_file_system_path() if filename is not None: text = converter.convert_file(filename) else: file_data = self.get_file() if file_data: text = converter.convert_string(file_data) if text: fulltext.append(text) return fulltext security.declareProtected(SilvaPermissions.View, 'get_download_url') def get_download_url(self, preview=False, request=None): if request is None: request = self.REQUEST url = getMultiAdapter((self, request), IContentURL).url(preview=preview) if preview: # In case of preview we add something that change at the # end of the url to prevent caching from the browser. url += '?' + str(int(time.time())) return url security.declareProtected(SilvaPermissions.View, 'tag') def tag(self, **kw): warnings.warn( 'tag have been replaced with get_html_tag. ' 'It will be removed, please update your code.', DeprecationWarning, stacklevel=2) return self.get_html_tag(**kw) security.declareProtected(SilvaPermissions.View, 'get_html_tag') def get_html_tag(self, preview=False, request=None, **extra_attributes): """ return xhtml tag Since 'class' is a Python reserved word, it cannot be passed in directly in keyword arguments which is a problem if you are trying to use 'tag()' to include a CSS class. The tag() method will accept a 'css_class' argument that will be converted to 'class' in the output tag to work around this. """ src = self.get_download_url(preview, request) title = self.get_title_or_id() if 'css_class' in extra_attributes: extra_attributes['class'] = extra_attributes['css_class'] del extra_attributes['css_class'] extra_html_attributes = [ '{name}="{value}"'.format(name=escape(name, 1), value=escape(value, 1)) for name, value in extra_attributes.items() ] return '<a href="%s" title="Download %s" %s>%s</a>' % ( src, self.get_filename(), extra_html_attributes, title) # checks where the mime type is text/* or javascript security.declareProtected(SilvaPermissions.AccessContentsInformation, 'is_text') def is_text(self): mimetype = self.get_mime_type() if ((mimetype.startswith('text/') and mimetype != 'text/rtf') or mimetype in ('application/x-javascript', 'application/xml', 'application/xhtml+xml')): return self.get_content_encoding() is None return False security.declareProtected(SilvaPermissions.AccessContentsInformation, 'is_text_editable') def is_text_editable(self): #size is editable if it is less than 150 KB return self.is_text() and (not self.get_file_size() > 153600) security.declareProtected(SilvaPermissions.View, 'get_text') def get_text(self): if not self.is_text(): raise TypeError("Content of Silva File is not text") return self.get_file() security.declareProtected(SilvaPermissions.View, 'get_file') def get_file(self): fd = self.get_file_fd() data = fd.read() fd.close() return data security.declareProtected(SilvaPermissions.View, 'get_file_fd') def get_file_fd(self): raise NotImplementedError security.declareProtected(SilvaPermissions.View, 'get_content_type') def get_content_type(self): return self._file.content_type security.declareProtected(SilvaPermissions.View, 'get_content_encoding') def get_content_encoding(self): return self._content_encoding # MODIFIERS security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_file') def set_file(self, stream, content_type=None, content_encoding=None): """Set data in _file object """ raise NotImplementedError security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_filename') def set_filename(self, filename): """Set filename """ self._filename = filename security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'get_file_system_path') def get_file_system_path(self): """Return path on filesystem for containing File. """ return None security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_content_type') def set_content_type(self, content_type): self._file.content_type = content_type security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_content_encoding') def set_content_encoding(self, content_encoding): self._content_encoding = content_encoding security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_text') def set_text(self, text): raise NotImplementedError
class SQLSource(EditableExternalSource, Folder, ZMIObject): grok.implements(IExternalSource) # register icon and factories silvaconf.icon('www/sqlsource.png') silvaconf.factory('manage_addSQLSourceForm') silvaconf.factory('manage_addSQLSource') silvaconf.zmi_addable(True) meta_type = "Silva SQL Source" security = ClassSecurityInfo() _sql_method_id = 'sql_method' _layout_id = 'layout' _default_batch_size = 10 _v_cached_parameters = None # ZMI Tabs manage_options = ( {'label':'Edit', 'action':'editSQLSource'}, {'label':'Parameters', 'action':'parameters/manage_main'}, ) + Folder.manage_options management_page_charset = 'utf-8' security.declareProtected(ViewManagementScreens, 'editSQLSource') editSQLSource = PageTemplateFile( 'www/sqlSourceEdit', globals(), __name__='sqlCodeSource') def __init__(self, id): self.id = id self._sql_method = None self._statement = None self._connection_id = None # ACCESSORS def layout_id(self): return self._layout_id def connection_id(self): return self._connection_id def statement(self): return self._statement def available_connection_ids(self): return SQLConnectionIDs(self) security.declareProtected(AccessContentsInformation, 'to_html') def to_html(self, content, request, **parameters): """ render HTML for SQL source """ values = self._get_data(parameters) names = values.names() batch_size = self._default_batch_size if parameters.get('sqlbatchsize'): batch_size = int(parameters.get('sqlbatchsize')) data = Batch( values.dictionaries(), factory=self._decode_dict_helper, count=batch_size, name=self.getId(), request=request) model = content if IVersion.providedBy(content): model = content.get_content() layout = self._getOb(self._layout_id) batch = getMultiAdapter((model, data, request), IBatching)() return layout( table=data, batch=batch, names=names, parameters=parameters) def _get_data(self, args): if not self._sql_method: self._set_sql_method() elif self._v_cached_parameters != self.get_parameters_form().get_field_ids(): self._set_sql_method() args = self._encode_dict_helper(args) return self._sql_method(REQUEST=args) def _decode_dict_helper(self, dictionary): for key, value in dictionary.items(): if type(value) is type(''): dictionary[key] = unicode( value, self._data_encoding, 'replace') return dictionary def _encode_dict_helper(self, dictionary): for key, value in dictionary.items(): if type(value) is type(u''): dictionary[key] = value.encode( self._data_encoding, 'replace') return dictionary # MODIFIERS def _set_statement(self, statement): self._statement = statement #invalidate sql method self._sql_method = None self._p_changed = 1 def _set_connection_id(self, id): self._connection_id = id #invalidate sql method self._sql_method = None self._p_changed = 1 def _set_sql_method(self): self._v_cached_parameters = parameters = self.get_parameters_form().get_field_ids() arguments = '\n'.join(parameters) self._sql_method = SQL( self._sql_method_id, '', self._connection_id, arguments.encode('ascii'), self._statement.encode('UTF-8')) self._p_changed = 1 # MANAGERS security.declareProtected(ViewManagementScreens, 'manage_editSQLSource') def manage_editSQLSource( self, title, data_encoding, statement, connection_id=None, description=None, cacheable=None, layout_id=None, reset_layout=None, reset_params=None, previewable=None, usable=None, ): """ Edit SQLSource object """ msg = u'' if reset_layout: reset_table_layout(self) return self.editSQLSource( manage_tabs_message="Table rendering pagetemplate reset " \ "to default layout.") if reset_params: reset_parameter_form(self) return self.editSQLSource( manage_tabs_message="Parameters form reset to default.") if data_encoding and data_encoding != self._data_encoding: try: unicode('abcd', data_encoding, 'replace') except LookupError: # unknown encoding, return error message msg += "Unknown encoding %s, not changed!" % data_encoding return self.editSQLSource(manage_tabs_message=msg) self.set_data_encoding(data_encoding) msg += "Data encoding changed. " if connection_id and connection_id != self._connection_id: self._set_connection_id(connection_id) msg += "Connection id changed. " if statement: statement = unicode(statement, 'UTF-8') self._set_statement(statement) msg += "SQL statement changed. " title = unicode(title, self.management_page_charset) if title and title != self.title: self.set_title(title) msg += "Title changed. " description = unicode(description, self.management_page_charset) if description != self._description: self.set_description(description) msg += "Description changed. " if not bool(cacheable) is self.is_cacheable(): self.set_cacheable(bool(cacheable)) msg += "Cacheability setting changed. " if not bool(previewable) is self.is_previewable(): self.set_previewable(bool(previewable)) msg += "Previewable setting changed. " if not bool(usable) is self.is_usable(): self.set_usable(bool(usable)) msg += "Usability setting changed. " if layout_id and layout_id != self._layout_id: self._layout_id = layout_id msg += "Layout object id changed. " return self.editSQLSource(manage_tabs_message=msg)
class MyFolder(Folder): meta_type = 'My Folder' silvaconf.factory('manage_addMyFolder')