Custom validator in easyform

In PloneFormGen I used the following "Custom vaidator" in a file-upload field.

python:test(value.filename.lower().split('.')[-1] in ['png','jpg'],False,'A PNG or JPG file is required, but you have given "'+value.filename+'".')
In collective.easyform, however, I get an error but without actual error message. I only see:

File already uploaded: d.jpg

When I then press "Submit again" with "keep existing file" checked, I see the following error:

NOT_CHANGED' object has no attribute 'filename'
File already uploaded: devil2.jpg

Can somebody tell me the error in my validator? Or better, give me a correct version. I only want to allow filenames that end in ".png" or ".jpg".

Unfortunately, the documentation of easyform
https://collectiveeasyform.readthedocs.io/en/latest/
is unfortunately, not very helpful.

Your expression looks fine to me. I have this validator as part of a cheap captcha:

python: False if str(value).lower().strip() == 'berlin' else "Falsche Eingabe"

Thanks. I've now created a new form with just email address field, file upload and mailer action.

The file upload has now this validator:

python: False if str(value).lower().strip() == 'jpg' else "Falsche Eingabe"

Result when I enter "click.jpg" into the file field:

Falsche Eingabe
File already uploaded: click.jpg

I somehow wonder why it should work the way you proposed it. When I just put

python:value

then I get:the error:

<plone.namedfile.file.NamedBlobFile object at 0x7f7a...>

and when I put

value/__dir__

the error message is:

{'contenType': 'image/png', '_blob': <ZODB.blob.Blob object...>, 'filename': 'panda.jpg'

How can I find out what is wrong?

Addon...

If I enter the custom validator

value/filename

I correctly see the respective filename like a.jpg as the error message.
If, however, i put

python: path(value/filename)

then I see "name 'filename' is not defined.
Isn't that strange?

See here under "Usage" https://pypi.org/project/plone.namedfile/

Do you mean that?


I clearly see that I would be able to access it with value.filename. Am I wrong?

It also does not explain, why the tal expression value/filename works but python: path(value/filename) doesn't. Am I understanding something incorrectly?

Maybe I'm stating the obvious, but is there a confusion here between attribute access and dictionary lookup? value['filename'] is different from value.filename . Some classes overwrite/merge them to be the same by overwriting the 'dunder' __ methods like __getitem__ on the class

The murky part is that TALES expressions (value/filename) try both (attribute access & dictionary lookup), so there you don't notice the difference. (a bit like url traversal in Zope)

python: path(value/filename)

then I see "name 'filename' is not defined.
Isn't that strange?

Upon first reading yes, but the error you see is correct: you should pass a string to the path function.

python: path("value/filename")

should work. with value/filename you are dividing value by filename and filename is correctly unknown.

Confusion maybe, I am not a full-fledged plone developer.
When I put

python: value['filename']

The error message is "NamedBlobFile object is not subscriptable".
With

python: path("value/filename")

I correctly get the filename. Thanks a lot for this hint.
I stily wonder how the python expression would be without using "path" .

I have now modified my initial expression to

python:test(path("value/filename").lower().split('.')[-1] in ['png','jpg'],False,'A PNG or JPG file is required, but you have given "'+path("value/filename")+'".')

and that seems to work as I want.

I cannot recall the exact reason, but at some point I had to remove all usages of test from my templates - maybe that is related to Zope or Chameleon or ... reasons.

cf https://github.com/zopefoundation/Zope/issues/813