GithubHelp home page GithubHelp logo

plone / plone.scale Goto Github PK

View Code? Open in Web Editor NEW
2.0 159.0 14.0 2.44 MB

Contains image scaling logic for use in Zope environments. It supports Zope 2, Pyramid and other systems build on using the Zope ToolKit (ZTK).

Home Page: https://pypi.org/project/plone.scale

Python 100.00%

plone.scale's Introduction

Introduction

This package contains image scaling logic for use in Zope environments. It supports Zope 2, grok and other systems build on using the Zope ToolKit (ZTK).

Several design goals were used when writing this package:

  • image scaling to any width, height, width&height should be supported using both up-scaling and down-scaling. Scaling parameters should never be fixed in code. This allows designers to use any image scale they want without having to modify python code.
  • the result of scaling will be an image along with its new size, not a HTML or XHTML tag. We already have excellent tools to generate tags in the form of Zope Pagetemplates, Genshi and other template languages that are much better suited for this purpose.

In addition several implementation goals were defined:

  • image scaling must happen on demand instead of up-front. This reduces initial save time and prevents unnecessary scalings from being generated.
  • image scaling parameters should not be part of the generated URL. Since the number of parameters can change and new parameters may be added in the future this would create overly complex URLs and URL parsing.
  • no HTML rewriting (such as done by repoze.bitblt) should be required.
  • it should be possibly to develop an external storage system which stores scaled images externally and returns a URL which bypasses the application server. This should be configurable via just a filesystem path & base URL.
  • minimum number of external dependencies, allowing this package to be used in many environments.
  • testable without requiring zope.testing. Running setup.py test should be sufficient.
  • URLs for scaled images should have an extension which reflects their MIME type. This is facilitates cache (and other front-end services) configuration.

Usage

The most common way to use plone.scale is from a HTML template. In TAL syntax a typical usage looks like this, assuming you have hooked up an image-scaling view:

<img tal:define="scales context/@@image-scaling;
                 thumbnail python:scales.pre_scale('logo', width=64, height=64)"
     tal:attributes="src thumbnail/url;
                     width thumbnail/width;
                     height thumbnail/height" />

With the pre_scale method, no scaling with Pillow actually happens yet. If you call the scale method instead, the scaling does happen. This generates a thumbnail of an image field called logo with a maximum size of 64x64 pixels. The dimensions of the resulting image (which might not be exactly 64x64) are set as attributes on the img tag to speed up browser rendering. Visiting the url will generate the scale if this has not happened yet.

If you prefer Genshi syntax and have the IImageScaleStorage interface in scope the syntax looks like this:

<img py:with="thumbnail=IImageScaleStorage(context).pre_scale('logo', width=64, height=64)"
     py:attributes="dict(src=thumbnail.url, width=thumbnail.width, height=thumbnail.height" />

plone.scale's People

Contributors

agitator avatar bloodbare avatar davisagli avatar dhavlik avatar ericof avatar esteele avatar fschulze avatar fulv avatar gforcada avatar gotcha avatar hannosch avatar jensens avatar khink avatar kroman0 avatar lrowe avatar mamico avatar mattss avatar mauritsvanrees avatar mrtango avatar optilude avatar pbauer avatar pre-commit-ci[bot] avatar reebalazs avatar sureshvv avatar thet avatar tisto avatar tomster avatar vangheem avatar wichert avatar witsch avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plone.scale's Issues

Remove deprecated factory handler

In storage.py we support passing a factory to the scale method. When you use this, we print a warning:

Deprecated usage of factory in plone.scale. Provide an adapter for the factory instead. The kwarg will be dropped with plone.scale 3.0.

Instead it is still there in latest official release 3.1.2. So let's remove it in version 4 then. I will make a PR.
I have already released a 4.0.0a1 today, for Python 3 only. Still works on 5.2 as well, for those who want it.

Current plone.app.tiles still uses the deprecated way, which is probably one reason why it was not removed yet. I can update this package. That should be possible when using plone.namedfile 6.0.0a2.

Are image scales thrown away needlessly?

I have heard community members complain about image scales being purged from the storage when there is no reason. I am doing some tests, also adding unit tests, and so far it seems to go how I expect:

  • Add a portal_type with an image field to Plone and view two scales, let's say on @@images/image/mini and @@images/image/preview.
  • Edit the image and only change the title.
  • View the scales: you get the cached scales.
  • Edit the image and upload a different image.
  • View the mini scale: the old mini scale is explicitly removed and a new one is generated. The preview scale is kept.
  • View the preview scale 24 hours later via the unique url: you get the cached scale, even though it is outdated.
  • View the large scale: you have not viewed this yet, so a new scale is generated. This triggers cleaning up outdated scales.
  • The cached preview scale is removed because it is older than 24 hours and is outdated.
  • The cached mini scale is kept even though it is older than 24 hours: it is not outdated.

So that seems fine.

The only other thing I fear could be true, is:

  • You have a portal_type with two image fields.
  • Upload to image field 1, save, generate a scale.
  • Upload to image field 2, maybe after 24 hours, save, generate a scale.
  • This might throw away scales from image field 1, although they are not outdated.

Is that maybe the case?

@datakurre I think at least you reported this.

Modernize plone.scale, make AnnotationStorage an adapter

Low hanging fruit:

  • Make it Python 3.7+, Plone 6 only. (Well, might work on 5.2 Py 3 as well. The package itself does not do anything with the rest of Plone, expect importing plone.testing in the tests.)
  • black, isort5, pyupgrade
  • Remove the docs directory and the [sphinx] extra. The last real update is from 2010. The text from the index has been included in the readme, and the rest is not interesting, and outdated. Hosted here: https://pythonhosted.org/plone.scale/
  • GitHub Actions may be nice here, since the package does not use Plone, and advertises itself as supporting "Zope 2, grok and other systems build on using the Zope ToolKit".

And then the interesting one: register AnnotationStorage as an adapter.

AnnotationStorage is defined like this:

@implementer(IImageScaleStorage)
class AnnotationStorage(MutableMapping):

But there is no zcml, so this is never registered as an adapter.
So plone.namedfile has to call AnnotationStorage directly instead of doing an adapter lookup.
With an adapter lookup in place, I can register a different adapter for tiles. Currently plone.app.tiles defines its own annotation storage which it uses in publishTraverse and in scale. This is one of the reasons that plone.app.tiles copies over so many code from plone.namedfile.

If we register AnnotationStorage as an adapter, we solve this problem. And it seems logical.

What do you think?

Cleanup does wrong time comparison

We are trying to clean up scales that are more than a day out of date. This time was chosen because possibly old cached html might still be referencing a by now outdated scale: if you are seeing old html it is better to see an old image too instead of no image.

But the code thinks the modified time is measured in milli seconds. And actually it is in seconds. I was the one who actually added this code...

Either I was wrong then or I am wrong now.

So before I change anything: can someone check this? Is the modified time expected to be in seconds or in milliseconds?

Implementing an IImageScaleStorage that stores scales only in memory

I have an application where image scales are heavily used, and once they are generated they are stored forever, even when they are not useful anymore.

So I'm thinking about implementing a new IImageScaleStorage implementation, where scales are stored only in RAM memory. If memory was infinite it would be easy. However I would like to store the scales in a cache, where least used scales would get purged eventually (probably Zope's RAM cache, but that's just an implementation detail). The problem is when a client of the storage requests an image by it's UID and it is not in the cache anymore. Example: when a user requests the scale by its UID based URL.

To solve this the storage itself could re-generate the scale, but it doesn't know what are the scaling parameters (width, height etc). Unless the parameters are contained in the UID!

In the README I found this statement:

image scaling parameters should not be part of the generated URL. Since the number of parameters can change and new parameters may be added in the future this would create overly complex URLs and URL parsing.

However I thought of an easy way to solve the problems mentioned in the statement. I could encode the parameters as JSON and apply base64 encoding. For example:

>>> parameters = '{width:100,height:100,direction:'down',quality:88}'
>>> uid = base64(parameters)  
e3dpZHRoOjEwMCxoZWlnaHQ6MTAwLGRpcmVjdGlvbjonZG93bicscXVhbGl0eTo4OH0K
>>> len(uid)
68

URL would be not that big (67 chars in the example), parsing and encoding are straightforward and it is futureproof regarding inclusion of new parameters.

So what do you think? Do you see any caveats I am missing? Do you think such a scale storage would be generally useful and worth inclusion in this package? I could open a PR for that.

PS.: This is actually not an issue nor a question, it is a request for thoughts about this idea. I thought about posting it on the Plone Community forum but I think here I have more chances of reaching people how knows more about scaling specifics. I hope this is OK.

Scaled image with mode LA is just a black square.

I have a problem when scaling the attached image. This image has mode LA. When I upload this image in Plone, the scaled versions are all black squares. When I convert the image to mode P and upload that image, the scaled versions are correct. Also, when I do the scaling on the command line, following the same steps, the scaled versions are also correct. Is this a problem with plone.scale or PIL or the image itself?

boek-la

New image scale sizes break cropping

In Plone 6, cropping an image to the thumb scale works fine: you get a 128x128 image.

But how about the new preview scale? It is defined as 400 by 65536. That makes no sense for cropping. I saw this when adding tests.
So how should we handle this? I propose:

  • When asking for a crop (mode="contain")
  • and the asked height is 65536 (or -1, or None)
  • then we crop to a square: use the asked for width also for the height.

I have a branch ready.

Damaged images fail on scale.

Damaged images fail on scale, this info should somehow be shown to the user...

IOError: image file is truncated (56 bytes not processed)
  File "plone/buildout/eggs/plone.namedfile-4.1-py2.7.egg/plone/namedfile/scaling.py", line 220, in __call__
    **parameters
  File "plone/buildout/src-addons/plone.app.imagecropping/src/plone/app/imagecropping/dx.py", line 48, in create_scale
    **parameters
  File "plone/buildout/eggs/plone.namedfile-4.1-py2.7.egg/plone/namedfile/scaling.py", line 170, in create_scale
    **parameters
  File "plone/buildout/src/plone.scale/plone/scale/scale.py", line 51, in scaleImage
    image = scalePILImage(image, width, height, direction)
  File "plone/buildout/src/plone.scale/plone/scale/scale.py", line 164, in scalePILImage
    return _scale_thumbnail(image, width, height)
  File "plone/buildout/src/plone.scale/plone/scale/scale.py", line 98, in _scale_thumbnail
    image.thumbnail((width, height), PIL.Image.ANTIALIAS)
  File "PIL/Image.py", line 1800, in thumbnail
    im = self.resize(size, resample)
  File "PIL/Image.py", line 1533, in resize
    self.load()
  File "PIL/ImageFile.py", line 222, in load
    "(%d bytes not processed)" % len(b))

Scales and read-only frontend

We have a Plone setup with two frontends. One for editors which uses read-write plone instances and one for publicity with read-only plone instances, this looks like this:

      ┌─────────────────┐                 ┌──────────────────┐
      │ www.oursite.com │                 │ cms.oursite.com  │
      │ for publicity   │                 │ for editors      │
      └───────┬─────────┘                 └────────┬─────────┘
              │                                    │
              │                                    │
              ▼                                    ▼
 ┌────────────────────────────┐        ┌───────────────────────────┐
 │ read-only plone instances  │        │read-write plone instances │
 └─────────────┬──────────────┘        └───────────┬───────────────┘
               │                                   │
               │                                   │
               │                                   │
               │            ┌───────────┐          │
               └─────────►  │           │ ◄────────┘
                            │    ZEO    │
                            │           │
                            │           │
                            └───────────┘

cms.oursite.com is only accessible from our intranet - so we have some extra security here.

If an image scale is not accessed via cms.oursite.com before it is accessed via www.oursite.com we will get an "ReadOnlyError" because scaling happens on demand.

We have tried to work around this issue by creating scales on save but it is not very reliable.

Now we consider read-write access from www.oursite.com but maybe there is an other better solution for this?

"ValueError: height and width must be > 0" for tiff files

2019-12-02 10:53:31 ERROR plone.namedfile.scaling Could not scale "<plone.namedfile.file.NamedBlobImage object at 0x11a532cf8>" of 'http://localhost:12481/plone/intern/shop/rechtsquellen-1'
Traceback (most recent call last):
  File "/Users/peter/workspace/test/eggs/plone.namedfile-5.2.0-py2.7.egg/plone/namedfile/scaling.py", line 245, in __call__
    **parameters
  File "/Users/peter/workspace/test/eggs/plone.namedfile-5.2.0-py2.7.egg/plone/namedfile/scaling.py", line 195, in create_scale
    **parameters
  File "/Users/peter/workspace/test/eggs/plone.scale-3.0.3-py2.7.egg/plone/scale/scale.py", line 67, in scaleImage
    image = scalePILImage(image, width, height, direction)
  File "/Users/peter/workspace/test/eggs/plone.scale-3.0.3-py2.7.egg/plone/scale/scale.py", line 194, in scalePILImage
    return _scale_thumbnail(image, width, height)
  File "/Users/peter/workspace/test/eggs/plone.scale-3.0.3-py2.7.egg/plone/scale/scale.py", line 128, in _scale_thumbnail
    image.thumbnail((width, height), PIL.Image.ANTIALIAS)
  File "/Users/peter/workspace/test/eggs/Pillow-6.2.1-py2.7-macosx-10.13-x86_64.egg/PIL/Image.py", line 2219, in thumbnail
    im = self.resize(size, resample)
  File "/Users/peter/workspace/test/eggs/Pillow-6.2.1-py2.7-macosx-10.13-x86_64.egg/PIL/Image.py", line 1883, in resize
    im = im.resize(size, resample, box)
  File "/Users/peter/workspace/test/eggs/Pillow-6.2.1-py2.7-macosx-10.13-x86_64.egg/PIL/Image.py", line 1888, in resize
    return self._new(self.im.resize(size, resample, box))
ValueError: height and width must be > 0

I'm getting this error but scales are created und can be displayed

With Plone 5.1.5 and with the packages used in 5.2.
What's the state of support for tiff files?

Solve Problem on waking up the object to get the scales

Problem:

In order to get a scale or generate its tag one must wake up the context object which has the image. In listings this leads to a vast amount of getObject calls.

How it works now

plone.scale created the scale and stores it as an annotation of the object.

Proposed Solution

Rough sketch:

  • Additional store a mapping (content UID, image hash) as an OOBTree as an annotation at portal level on scale creation.
  • Remove the mapping on cleanup
  • Provide an utility to lookup scales UIDs
  • Also (not in here), provide convinicence API for same features - i.e. tag creation - ass @@images does now directly on the object. Idea: As images adapter between catalog brain and request providing the same interface as @@images.

Refactor CI: just use pip, no mxdev

We use mxdev in this package. This is needed because we want to use the core Plone 5.2/6.0 constraints, and need to ignore plone.scale from the constraints. Nice example, at least for me.
But our only dependencies are setuptools and Pillow. mxdev is overkill then. We should simply test a few combinations of Python and Pillow versions.

DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10

You get this warning when you use Pillow 9.1.0:

DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10 (2023-07-01).
Use Resampling.LANCZOS instead.
  (dimensions.final_width, dimensions.final_height), PIL.Image.ANTIALIAS

Since we try to keep current master of plone.scale also working on Plone 5.2 Py 3, we may need some conditional handling.

Delete scale sometimes fails because values and items are out of sync

Plone 4.3.11, plone.scale 1.4.1, RelStorage.
This is an old copy of the site on a development server, where I just updated from Plone 4.3.6 to 4.3.11. And added five.pt, though I don't think that matters here. The homepage showed fine before, but now fails:

Traceback (innermost last):
  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 48, in call_object
  Module Products.minaraad.browser.homepage, line 20, in __call__
  Module Products.Five.browser.pagetemplatefile, line 125, in __call__
  Module Products.Five.browser.pagetemplatefile, line 59, in __call__
  Module zope.pagetemplate.pagetemplate, line 132, in pt_render
  Module five.pt.engine, line 98, in __call__
  Module z3c.pt.pagetemplate, line 163, in render
  Module chameleon.zpt.template, line 261, in render
  Module chameleon.template, line 191, in render
  Module chameleon.template, line 171, in render
  Module e0d298331ef610c65315d9e5fee21810.py, line 1188, in render
  Module 783a713b2da0eedfb1f625102403febe.py, line 1392, in render_master
  Module 783a713b2da0eedfb1f625102403febe.py, line 559, in render_content
  Module e0d298331ef610c65315d9e5fee21810.py, line 414, in __fill_content_core
  Module plone.app.imaging.scaling, line 185, in scale
  Module plone.app.imaging.scaling, line 272, in getInfo
  Module plone.scale.storage, line 158, in scale
  Module persistent.mapping, line 59, in __delitem__
  Module UserDict, line 25, in __delitem__
KeyError: 'c639a89a-bbc4-41c3-80a0-b68b1f0b5e69'

 - Expression: "python:images.scale('image', width=100, height=100, direction='down')"

It goes wrong on the del line here in storage.py:

    def scale(self, factory=None, **parameters):
        key = self.hash(**parameters)
        storage = self.storage
        info = self.get_info_by_hash(key)
        if info is not None and self._modified_since(info['modified']):
            del storage[info['uid']]

Checking with a pdb, we have this hash key:

(('direction', 'down'), ('fieldname', 'image'), ('height', 100), ('width', 100))

It is in the storage values:

((Pdb)) pp [x['key'] for x in self.storage.values()]
[(('direction', 'down'),
  ('fieldname', 'image'),
  ('height', 105),
  ('width', 105)),
 (('direction', 'down'),
  ('fieldname', 'image'),
  ('height', 105),
  ('width', 105)),
 (('direction', 'down'),
  ('fieldname', 'footerImage'),
  ('height', 500),
  ('width', 1500)),
 (('direction', 'down'),
  ('fieldname', 'footerImage'),
  ('height', 500),
  ('width', 1500)),
 (('direction', 'down'),
  ('fieldname', 'image'),
  ('height', 100),
  ('width', 100))]

But it is not in the keys:

((Pdb)) pp self.storage.keys()
[(('direction', 'down'),
  ('fieldname', 'image'),
  ('height', 105),
  ('width', 105)),
 'd891e734-b164-4e30-90c1-991bd51cadf0',
 '3ceb8c33-17a3-40ba-aae5-db7445eee2a0',
 (('direction', 'down'),
  ('fieldname', 'footerImage'),
  ('height', 500),
  ('width', 1500)),
 (('direction', 'down'),
  ('fieldname', 'image'),
  ('height', 100),
  ('width', 100))]

So the delete fails.

It's easy to add an extra check to avoid the traceback. I'l probably make a pull request for that.

But it is strange that the keys and values can get out of sync. It could have something to do with RelStorage. Or that this is for two zope instances, with the blobstorage on a shared network drive.

Error scaling BMP images in Plone 5.1.5

When calling a scale on a .bmp image I get this error.

Could not scale "<plone.namedfile.file.NamedBlobImage object at 0x7f3dbe51c758>" of <bound method Image.absolute_url of <Image at /Plone/cobweb.bmp>>
Traceback (most recent call last):
  File "/sprj/st_zope_plone5/buildouts/eggs/plone.namedfile-4.2.6-py2.7.egg/plone/namedfile/scaling.py", line 253, in __call__
    **parameters
  File "/sprj/st_zope_plone5/buildouts/eggs/plone.namedfile-4.2.6-py2.7.egg/plone/namedfile/scaling.py", line 200, in create_scale
    **parameters
  File "/sprj/st_zope_plone5/buildouts/eggs/plone.scale-3.0.3-py2.7.egg/plone/scale/scale.py", line 74, in scaleImage
    if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors):
  File "/sprj/st_zope_plone5/buildouts/eggs/plone.scale-3.0.3-py2.7.egg/plone/scale/scale.py", line 74, in <genexpr>
    if all(rgb[0] == rgb[1] == rgb[2] for c, rgb in colors):
IndexError: tuple index out of range

I dug into this a bit in a debugger.

>>> img=app.unrestrictedTraverse('/Plone/cobweb.bmp')
>>> portrait=img.portrait
>>> from plone.scale.scale import scaleImage
>>> scaleImage(portrait.data, 16, 16)

This gives the same error as above. the value of image.format is "BMP" which will cause the scale to assume converting into JPEG. This triggers a later condition where it tries to check the RGB values for equality to determine if it's gray.

>>> import PIL.Image
>>> from StringIO import StringIO
>>> image = PIL.Image.open(StringIO(portrait.data))
>>> colors = image.getcolors(maxcolors=256)
>>> colors
[(59, (255, 255)), (8, (253, 255)), (4, (251, 255)), (4, (249, 255)), (3, (247, 255)), (2, (245, 255)), (1, (241, 255)), (3, (237, 255)), (1, (235, 255)), (2, (227, 255)), (2, (225, 255)), (2, (223, 255)), (3, (217, 255)), (2, (211, 255)), (2, (209, 255)), (1, (205, 255)), (1, (201, 255)), (1, (199, 255)), (1, (183, 255)), (1, (181, 255)), (1, (177, 255)), (1, (167, 255)), (1, (163, 255)), (2, (159, 255)), (1, (157, 255)), (1, (151, 255)), (1, (149, 255)), (2, (147, 255)), (1, (143, 255)), (1, (139, 255)), (1, (135, 255)), (2, (125, 255)), (1, (121, 255)), (2, (113, 255)), (1, (109, 255)), (1, (101, 255)), (1, (99, 255)), (1, (97, 255)), (1, (95, 255)), (2, (93, 255)), (3, (87, 255)), (1, (79, 255)), (1, (77, 255)), (3, (73, 255)), (1, (69, 255)), (1, (65, 255)), (2, (61, 255)), (2, (59, 255)), (1, (53, 255)), (1, (51, 255)), (1, (47, 255)), (2, (37, 255)), (1, (31, 255)), (1, (29, 255)), (10, (25, 255)), (2, (21, 255)), (1, (19, 255)), (2, (17, 255)), (3, (15, 255)), (1, (13, 255)), (2, (9, 255)), (1, (7, 255)), (1, (5, 255)), (1, (1, 255)), (2, (254, 255)), (5, (252, 255)), (2, (250, 255)), (2, (248, 255)), (1, (246, 255)), (5, (244, 255)), (2, (242, 255)), (1, (228, 255)), (1, (226, 255)), (2, (224, 255)), (1, (218, 255)), (1, (214, 255)), (2, (212, 255)), (2, (210, 255)), (1, (206, 255)), (1, (200, 255)), (2, (196, 255)), (1, (194, 255)), (1, (188, 255)), (1, (186, 255)), (1, (168, 255)), (1, (164, 255)), (1, (138, 255)), (1, (136, 255)), (1, (134, 255)), (1, (132, 255)), (1, (130, 255)), (1, (128, 255)), (1, (124, 255)), (1, (122, 255)), (2, (118, 255)), (1, (110, 255)), (1, (108, 255)), (1, (106, 255)), (1, (94, 255)), (1, (88, 255)), (1, (86, 255)), (2, (84, 255)), (1, (78, 255)), (1, (72, 255)), (1, (70, 255)), (1, (56, 255)), (1, (54, 255)), (2, (50, 255)), (1, (38, 255)), (1, (30, 255)), (3, (28, 255)), (1, (26, 255)), (1, (24, 255)), (2, (22, 255)), (1, (18, 255)), (1, (16, 255)), (2, (6, 255)), (1, (2, 255)), (6, (0, 255))]

As you can see the rgb values only have two values so rgb[2] throws an IndexError

storage.py _cleanup TypeError: unsupported operand type(s) for -: 'str' and 'int'

Hi, i get an error while rendering an template with Images. I use Plone 4.3.9. Please no irritations because of the path in the traceback.

  File "/opt/Plone-4.3.3/buildout-cache/eggs/plone.scale-1.4.1-py2.7.egg/plone/scale/storage.py", line 166, in scale
    self._cleanup()
  File "/opt/Plone-4.3.3/buildout-cache/eggs/plone.scale-1.4.1-py2.7.egg/plone/scale/storage.py", line 190, in _cleanup
    value['modified'] < modified_time - KEEP_SCALE_MILLIS):
TypeError: unsupported operand type(s) for -: 'str' and 'int'

# Here my Debug Output of the Values:
2016-08-27 18:58:05 INFO plone.scale key: d7620496-5e61-4f6b-8490-b30399d809ba
2016-08-27 18:58:05 INFO plone.scale modified time     1467291549.8024411467291549.8028791467291549.8032841467291549.8036901467291549.804092
2016-08-27 18:58:05 INFO plone.scale value['modified'] 1467291549.8024411467291549.8028791467291549.8032841467291549.8036901467291549.804092

I think it's not an Integer, all values are 'str'. The comparison but needs integer values . What should i do? Should I overwrite the _cleanup Method and purge the Storage every time?

Confusing modes `contain` and `cover` (to me at least)

I just wondered why the plone.scale modes contain and cover are the direct opposite of the css object-fit meanings?

contain

plone.scale fills width/height completely and image gets clipped out of the center
object-fit scales image to fit width or height and gets letterboxed

cover

plone.scale scales image to fit width or height
object-fit fills width/height and gets clipped according to the container

Note to myself: documentation needs update on this too ... see https://6.docs.plone.org/classic-ui/images.html#scaling-direction ... direction is obsolete and should not be used anymore.

Conflict error on image_scales indexing when uploading an image via `plone.restapi`

BUG/PROBLEM REPORT (OR OTHER COMMON ISSUE)

Conflict error on image_scales indexing when uploading an image via plone.restapi, then the image fails to show in a block.

I downgraded to 6.0.6 and it does not happens.

/cc @davisagli @ericof @mauritsvanrees @fredvd

What I did:

Using Plone 6.0.7 docker images, latest plone.restapi (9.0.0)

When uploading an image, there are randomly:

2023-09-29 10:16:20 ERROR [ZODB.ConflictResolution:307][waitress-0] Unexpected error while trying to resolve conflict on <class 'plone.scale.storage.ScalesDict'>
Traceback (most recent call last):
  File "/app/lib/python3.11/site-packages/ZODB/ConflictResolution.py", line 290, in tryToResolveConflict
    resolved = resolve(old, committed, newstate)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/lib/python3.11/site-packages/plone/scale/storage.py", line 119, in _p_resolveConflict
    self.raise_conflict(saved[key], new[key])
                        ~~~~~^^^^^
KeyError: 'image-1000-ab703699e343ff030a3cc014950e6ada'

Which causes that the scales are not there, then the newly uploaded image fails to show:

image

What I expect to happen:

The scales are in indexed the catalog correctly on upload.

Duplicate scales are generated when the image hasn't been modified

Steps to reproduce:

  1. Create a new Plone 6 classic site
  2. Add an Image content item and save
  3. Run find var/blobstorage -name '*.blob'
  4. Edit the Image content item and change something other than the image itself (e.g. description), then save.
  5. Run find var/blobstorage -name '*.blob' again

Expected: After initial creation of the image, there should be 2 blobs (the full size image and the large scale that was generated when viewing the image). After editing and saving again, there should be 3 blobs (the first 2, plus the preview scale that was generated while viewing the edit form).

Actual: After editing and saving, there are 5 blobs. One of them is identical to the large scale that existed before (there are now 2 copies of it). The other one is a mini scale, but I'm less concerned about that; I just haven't found what caused it to be generated.

I think the duplicate scale is generated because the hash used when generating the scale is based on the modification time of the image content item rather than the modification time of the NamedBlobImage value stored in the image field. That can probably be fixed here: https://github.com/plone/plone.namedfile/blob/master/plone/namedfile/scaling.py#L497 No, that doesn't make sense because we should have the field name. I need to pull out the debugger to see why the hash is changing.

Stop testing master branch with Plone 5.2

The master branch of plone.scale is only used for Plone 6. We should stop testing with the version pins from Plone 5.2 and declare that we've removed support for it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.