def thumb_url(image, request, size): """ Return the url for displaying the image with dimensions bounded by given size. """ assert IImage.providedBy(image), "Cannot take thumbnail of non-image." return resource_url(image, request, 'thumb', '%dx%d.jpg' % size)
def thumb_url(image, request, size): """ Return the url for displaying the image with dimensions bounded by given size. """ assert IImage.providedBy(image), "Cannot take thumbnail of non-image." return model_url(image, request, 'thumb', '%dx%d.jpg' % size)
def thumbnail_view(context, request): assert IImage.providedBy(context), "Context must be an image." filename = request.subpath[0] # <width>x<length>.jpg size = map(int, filename[:-4].split('x')) thumb = context.thumbnail(tuple(size)) # XXX Allow browser caching be setting Last-modified and Expires # and respecting If-Modified-Since requests with 302 responses. data = thumb.blobfile.open().read() return Response(body=data, content_type=thumb.mimetype)
def thumb_url(image, request, size): """ Return the url for displaying the image with dimensions bounded by given size. """ from karl.views.api import TemplateAPI # avoid circref if not IImage.providedBy(image): api = TemplateAPI(image, request, '') return api.static_url + "/images/brokenImage.gif" return resource_url(image, request, 'thumb', '%dx%d.jpg' % size)
def test_jpg(self): from karl.content.interfaces import IImage from pkg_resources import resource_stream stream = resource_stream('karl.content.models.tests', 'test.jpg') o = self._makeOne(stream=stream, mimetype='image/jpeg') self.failUnless(o.is_image) self.failUnless(IImage.providedBy(o)) self.assertEqual(o.image_size, (390, 569)) self.assertEqual(o.image().size, (390, 569)) from zope.interface.verify import verifyObject verifyObject(IImage, o)
def test_instance_has_valid_construction(self): instance = self._makeOne() self.assertEqual(instance.title, u'title') self.assertEqual(instance.creator, u'admin') self.assertEqual(instance.modified_by, u'admin') self.assertEqual(instance.blobfile.open().read(), 'FAKECONTENT') self.assertEqual(instance.size, 11) self.assertEqual(instance.mimetype, 'text/plain') self.assertEqual(instance.filename, 'afile.txt') self.failIf(instance.is_image) from karl.content.interfaces import IImage self.failIf(IImage.providedBy(instance))
def test_jpg(self): from karl.content.interfaces import IImage from pkg_resources import resource_stream stream = resource_stream('karl.content.models.tests', 'test.jpg') o = self._makeOne(stream=stream, mimetype='image/jpeg') self.failUnless(o.is_image) self.failUnless(IImage.providedBy(o)) self.assertEqual(o.image_size, (390, 569)) self.assertEqual(o.image().size, (390, 569)) from zope.interface.verify import verifyObject verifyObject(IImage, o) return o
def vocabulary_view(context, request): try: attributes = json.loads(request.params.get('attributes', '["title", "id"]')) except: attributes = ['title', 'id'] if 'UID' in attributes: # always put in anyways attributes.remove('UID') try: batch = json.loads(request.params.get('batch')) except: batch = DEFAULT_BATCH query = normalize_query(json.loads(request.params['query'])) criteria = parse_query(query) resolver = ResovlerFactory(context) if 'UID' in query: docids = query['UID'] if type(docids) not in (list, tuple): docids = [docids] # convert to ints new_docids = [] for docid in docids: try: new_docids.append(int(docid)) except: pass docids = new_docids numdocs = len(docids) else: criteria.append(Any('allowed', effective_principals(request))) if 'title' not in query: # we default to requiring a title in these results or # else we get a bunch of junky results criteria.append(NotEq('title', '')) catalog = find_catalog(context) numdocs, docids = catalog.query(And(*criteria)) if batch and ('size' not in batch or 'page' not in batch): batch = DEFAULT_BATCH if batch: # must be slicable for batching support page = int(batch['page']) # page is being passed in is 1-based start = (max(page - 1, 0)) * int(batch['size']) end = start + int(batch['size']) # Try __getitem__-based slice, then iterator slice. # The iterator slice has to consume the iterator through # to the desired slice, but that shouldn't be the end # of the world because at some point the user will hopefully # give up scrolling and search instead. try: docids = docids[start:end] except TypeError: docids = itertools.islice(docids, start, end) # build result items items = [] for docid in docids: result = resolver(docid) if result is None: continue data = { 'UID': docid } for attribute in attributes: attr = attribute if attribute in _attribute_mapping: attr = _attribute_mapping[attribute] if attr in ('Type', 'portal_type'): value = 'Page' if IImage.providedBy(result): value = 'Image' elif ICommunityFile.providedBy(result): value = 'File' elif IFolder.providedBy(result): value = 'Folder' elif attr == 'getURL': value = resource_url(result, request) elif attr == 'path': # a bit weird here... value = resource_path(result, request).split('/GET')[0] else: value = getattr(result, attr, None) data[attribute] = value items.append(data) return { 'results': items, 'total': numdocs }
def drawer_upload_view(context, request, check_upload_size=check_upload_size, get_image_info=get_image_info, batch_images=batch_images, ): """Drawer posts a file with the parameter name "file". """ ## XXX The rest is copied from add_file_view. A common denominator ## would be desirable. creator = authenticated_userid(request) fieldstorage = request.params.get('file') if not hasattr(fieldstorage, 'filename'): msg = 'You must select a file before clicking Upload.' return dict(error = msg) # For file objects, OSI's policy is to store the upload file's # filename as the objectid, instead of basing __name__ on the # title field). filename = basename_of_filepath(fieldstorage.filename) stream = fieldstorage.file # use parameter, as the title (or basename, if missing). title = request.params.get('title', filename) image = create_content(ICommunityFile, title=title, stream=stream, mimetype=get_upload_mimetype(fieldstorage), filename=fieldstorage.filename, creator=creator, ) # Check if it's an image. if not IImage.providedBy(image): msg = 'File %s is not an image' % filename return dict(error=msg) check_upload_size(context, image, 'file') if hasattr(context, 'get_attachments'): target_folder = context.get_attachments() if not has_permission('create', target_folder, request): msg = 'You do not have permission to upload files here.' return dict(error=msg) image.filename = filename name = make_name(target_folder, filename, raise_error=False) if not name: msg = 'The filename must not be empty' return dict(error=msg) # Is there a key in context with that filename? if name in target_folder: msg = 'Filename %s already exists in this folder' % filename return dict(error=msg) target_folder[name] = image workflow = get_workflow(ICommunityFile, 'security', context) if workflow is not None: workflow.initialize(image) # In cases where the image is to live in a piece of content which has not # yet been created (like when using an 'Add' form), the context is going # to be the eventual parent of the not yet created content, which will be # the eventual parent of the just now created image. Since we have nowhere # to put the image, we put it in a tempfolder and later move it over after # the content is created. Normal ContentAdded event handlers are not # called at this stage and workflow is not yet initialized. These will # occur when the content is moved over. else: image.modified = datetime.datetime.now() tempfolder = find_tempfolder(context) tempfolder.add_document(image) # Return info about the image uploaded return dict( upload_image_info=get_image_info(image, request, thumb_size=LARGE_THUMB_SIZE), )
def batch_images(context, request, get_image_info=get_image_info, # unittest get_images_batch=get_images_batch): # unittest include_image_url = request.params.get('include_image_url', None) # include_image_url is a special case. include_info = None if include_image_url is not None: # Note, we must use the path only, as IE submits the full domain # and without the next line IE would fail. path = urlparse.urlparse(include_image_url)[2] include_context = traverse(context, path)['context'] if IImage.providedBy(include_context): # We have a good image to include. include_info = get_image_info(include_context, request) # Find query parameters based on the 'source' param, # which signifies the selection index of the source button # in the imagedrawer dialog. source = request.params.get('source') assert source in ('myrecent', 'thiscommunity', 'allkarl') if source == 'myrecent': creator = authenticated_userid(request) community_path = None elif source == 'thiscommunity': creator = None community = find_community(context) # batching api requires the community path community_path = resource_path(community) else: # All Karl creator = None community_path = None # batching # Decide start and size here, don't let the lower levels # apply their default. This allows us to enforce # a MINIMAL_BATCH size. batch_start = int(request.params.get('start', '0')) batch_size = int(request.params.get('limit', '0')) # there is a minimal batch size to enforce, if the client # does not ask for one # Just pass the values to lower levels where sensible # defaults will be applied. sort_index = request.params.get('sort_on', None) reverse = request.params.get('reverse', None) # XXX include_image will now be inserted in the first # position, as extra image. insert_extra = False if include_info is not None: if batch_start == 0: batch_size -= 1 insert_extra = True else: batch_start -= 1 # Enforce the minimal batch size batch_size = max(batch_size, MINIMAL_BATCH) search_params = dict( creator=creator, community=community_path, batch_start=batch_start, batch_size=batch_size, ) if sort_index: search_params['sort_index'] = sort_index if reverse: search_params['reverse'] = bool(int(reverse)) batch_info = get_images_batch( context, request, **search_params ) records = [get_image_info(image, request) for image in batch_info['entries']] start = batch_info['batch_start'] totalRecords = batch_info['total'] # add the fake included image if include_info is not None: totalRecords += 1 if insert_extra: records.insert(0, include_info) else: start += 1 return dict( records = records, start = start, totalRecords = totalRecords, )