Projet

Général

Profil

0001-templatetags-add-a-qrcode-filter-for-string-values.patch

Benjamin Dauvergne, 02 août 2021 17:03

Télécharger (16,2 ko)

Voir les différences:

Subject: [PATCH] templatetags: add a qrcode filter for string values

 tests/template-with-qrcode.odt    | Bin 0 -> 9670 bytes
 tests/test_templates.py           |  28 ++++++++++++++++++
 tests/test_workflows.py           |  46 ++++++++++++++++++++++++++++++
 tox.ini                           |   1 +
 wcs/qommon/templatetags/qommon.py |  23 ++++++++++++++-
 5 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 tests/template-with-qrcode.odt
tests/test_templates.py
11 11
except ImportError:
12 12
    langdetect = None
13 13

  
14
import PIL
15
from pyzbar.pyzbar import ZBarSymbol
16
from pyzbar.pyzbar import decode as zbar_decode_qrcode
17

  
14 18
from wcs import fields
15 19
from wcs.formdef import FormDef
16 20
from wcs.qommon.http_request import HTTPRequest
......
1217 1221
    )
1218 1222

  
1219 1223
    assert t.render({'value': 'error1', 'value2': 'error2'}) == ''
1224

  
1225

  
1226
def test_qrcode(pub):
1227
    with pub.complex_data():
1228
        img = Template('{{ url|qrcode }}').render({'url': 'http://example.com/', 'allow_complex': True})
1229
        assert pub.has_cached_complex_data(img)
1230
        value = pub.get_cached_complex_data(img)
1231
        assert value.orig_filename == 'qrcode.png'
1232
        assert value.content_type == 'image/png'
1233
        with value.get_file_pointer() as fp:
1234
            img = PIL.Image.open(fp)
1235
            assert img.size == (330, 330)
1236
            assert (
1237
                zbar_decode_qrcode(img, symbols=[ZBarSymbol.QRCODE])[0].data.decode() == 'http://example.com/'
1238
            )
1239

  
1240
        img = Template('{{ url|qrcode:"qrcode2.png" }}').render(
1241
            {'url': 'http://example.com/', 'allow_complex': True}
1242
        )
1243
        value = pub.get_cached_complex_data(img)
1244
        assert value.orig_filename == 'qrcode2.png'
1245

  
1246
        img = Template('{{ url|qrcode }}').render({'url': 1, 'allow_complex': True})
1247
        assert img == ''
tests/test_workflows.py
17 17
    Image = None
18 18

  
19 19
from django.utils.encoding import force_bytes, force_text
20
from pyzbar.pyzbar import ZBarSymbol
21
from pyzbar.pyzbar import decode as zbar_decode_qrcode
20 22
from quixote import cleanup, get_publisher, get_response
21 23
from quixote.http_request import Upload as QuixoteUpload
22 24

  
......
3823 3825
    )
3824 3826

  
3825 3827

  
3828
def test_export_to_model_qrcode(pub):
3829
    FormDef.wipe()
3830

  
3831
    formdef = FormDef()
3832
    formdef.name = 'baz'
3833
    formdef.fields = []
3834
    formdef.store()
3835

  
3836
    formdef.data_class().wipe()
3837
    formdata = formdef.data_class()()
3838
    formdata.data = {}
3839
    formdata.just_created()
3840
    formdata.store()
3841
    pub.substitutions.feed(formdata)
3842

  
3843
    item = ExportToModel()
3844
    item.convert_to_pdf = False
3845
    item.method = 'non-interactive'
3846
    template_filename = os.path.join(os.path.dirname(__file__), 'template-with-qrcode.odt')
3847
    with open(template_filename, 'rb') as fd:
3848
        template = fd.read()
3849
    upload = QuixoteUpload('/foo/template.odt', content_type='application/octet-stream')
3850
    upload.fp = io.BytesIO()
3851
    upload.fp.write(template)
3852
    upload.fp.seek(0)
3853
    item.model_file = UploadedFile(pub.app_dir, None, upload)
3854
    item.attach_to_history = True
3855

  
3856
    item.perform(formdata)
3857

  
3858
    assert formdata.evolution[-1].parts[-1].base_filename == 'template.odt'
3859
    with zipfile.ZipFile(formdata.evolution[-1].parts[0].filename, mode='r') as zfile:
3860
        # base template use a jpg images and export_to_model does not rename it
3861
        # event when content is PNG, but it still works inside LibreOffice
3862
        # which ignores the filename extension.
3863
        image_filename = [name for name in zfile.namelist() if name.endswith('.jpg')][0]
3864
        with zfile.open(image_filename, 'r') as image_fd:
3865
            img = Image.open(image_fd)
3866
            assert (
3867
                zbar_decode_qrcode(img, symbols=[ZBarSymbol.QRCODE])[0].data.decode()
3868
                == 'http://example.net/backoffice/management/baz/1/'
3869
            )
3870

  
3871

  
3826 3872
def test_export_to_model_backoffice_field(pub):
3827 3873
    wf = Workflow(name='email with attachments')
3828 3874
    wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
tox.ini
43 43
    pylint
44 44
    Quixote>=3.0,<3.2
45 45
    pre-commit
46
    pyzbar
46 47
commands =
47 48
    py.test -v {env:COVERAGE:} --junitxml=junit-{envname}.xml {posargs:tests/}
48 49
    pylint: ./pylint.sh wcs/ tests/
wcs/qommon/templatetags/qommon.py
16 16

  
17 17
import datetime
18 18
import hashlib
19
import io
19 20
import math
20 21
import random
21 22
import string
......
26 27
from decimal import InvalidOperation as DecimalInvalidOperation
27 28

  
28 29
import pyproj
30

  
31
try:
32
    import qrcode
33
except ImportError:
34
    qrcode = None
35

  
29 36
from pyproj import Geod
30 37
from quixote import get_publisher
31 38

  
......
42 49
from django.utils.safestring import mark_safe
43 50
from django.utils.timezone import is_naive, make_aware
44 51

  
45
from wcs.qommon import calendar, evalutils, tokens
52
from wcs.qommon import calendar, evalutils, tokens, upload_storage
46 53
from wcs.qommon.admin.texts import TextsDirectory
47 54

  
48 55
register = template.Library()
......
817 824
def list_(value):
818 825
    # turn a generator into a list
819 826
    return list(unlazy(value))
827

  
828

  
829
@register.filter(name='qrcode')
830
def qrcode_filter(value, name=None):
831
    if not qrcode:
832
        return ''
833
    if not isinstance(value, str):
834
        return ''
835
    img = qrcode.make(value)
836
    buf = io.BytesIO()
837
    img.save(buf)
838
    upload = upload_storage.PicklableUpload(name or 'qrcode.png', 'image/png')
839
    upload.receive([buf.getvalue()])
840
    return upload
820
-