Projet

Général

Profil

0001-misc-split-emails-tests-36977.patch

Lauréline Guérin, 21 septembre 2021 18:44

Télécharger (21,1 ko)

Voir les différences:

Subject: [PATCH 1/4] misc: split emails tests (#36977)

 tests/test_emails.py | 221 +++++++++++++++++++++++++++++++++++++++++++
 tests/test_misc.py   | 206 ----------------------------------------
 2 files changed, 221 insertions(+), 206 deletions(-)
 create mode 100644 tests/test_emails.py
tests/test_emails.py
1
import base64
2
import os
3
import pwd
4
import socket
5

  
6
import pytest
7
from quixote import cleanup
8

  
9
from wcs.qommon.emails import docutils  # noqa pylint: disable=unused-import
10
from wcs.qommon.emails import email as send_email
11
from wcs.qommon.upload_storage import PicklableUpload
12

  
13
from .utilities import clean_temporary_pub, create_temporary_pub
14

  
15

  
16
def setup_module(module):
17
    cleanup()
18

  
19

  
20
def teardown_module(module):
21
    clean_temporary_pub()
22

  
23

  
24
def test_email_signature_plain(emails):
25
    pub = create_temporary_pub()
26
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
27
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
28
    assert emails.count() == 1
29
    assert not emails.emails['test']['msg'].is_multipart()
30
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload(decode=True)
31

  
32

  
33
def test_email_from(emails):
34
    pub = create_temporary_pub()
35
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
36
    assert emails.count() == 1
37
    assert emails.emails['test']['from'] == '%s@%s' % (pwd.getpwuid(os.getuid())[0], socket.getfqdn())
38

  
39
    pub.cfg['emails'] = {'from': 'foo@localhost'}
40
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
41
    assert emails.count() == 1
42
    assert emails.emails['test']['from'] == 'foo@localhost'
43
    assert emails.emails['test']['msg']['From'] == 'foo@localhost'
44

  
45
    if not pub.site_options.has_section('variables'):
46
        pub.site_options.add_section('variables')
47
    pub.site_options.set('variables', 'global_title', 'HELLO')
48
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
49
    assert emails.count() == 1
50
    assert emails.emails['test']['from'] == 'foo@localhost'
51
    assert emails.emails['test']['msg']['From'] in (
52
        '=?utf-8?q?HELLO?= <foo@localhost>',
53
        'HELLO <foo@localhost>',
54
    )
55

  
56

  
57
@pytest.mark.skipif('docutils is None')
58
def test_email_signature_rst(emails):
59
    pub = create_temporary_pub()
60
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
61
    send_email('test', mail_body='Hello', email_rcpt='test@localhost')
62
    assert emails.count() == 1
63
    assert emails.emails['test']['msg'].is_multipart()
64
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
65
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
66
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
67
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
68
    assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
69

  
70

  
71
@pytest.mark.skipif('docutils is None')
72
def test_email_signature_rst_pipes(emails):
73
    pub = create_temporary_pub()
74
    pub.cfg['emails'] = {'footer': '| Footer\n| Text'}
75
    send_email('test', mail_body='Hello', email_rcpt='test@localhost')
76
    assert emails.count() == 1
77
    assert emails.emails['test']['msg'].is_multipart()
78
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
79
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
80
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
81
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
82
    assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
83

  
84

  
85
def test_email_plain_with_attachments(emails):
86
    create_temporary_pub()
87

  
88
    jpg = PicklableUpload('test.jpeg', 'image/jpeg')
89
    with open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb') as fd:
90
        jpg_content = fd.read()
91
    jpg.receive([jpg_content])
92
    txt = PicklableUpload('test.txt', 'text/plain')
93
    txt.receive([b'foo-text-bar'])
94
    odt = PicklableUpload('test.odt', 'application/vnd.oasis.opendocument.text')
95
    with open(os.path.join(os.path.dirname(__file__), 'template.odt'), 'rb') as fd:
96
        odt_content = fd.read()
97
    odt.receive([odt_content])
98

  
99
    send_email('jpg', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg])
100
    assert emails.count() == 1
101
    assert emails.emails['jpg']['msg'].is_multipart()
102
    assert emails.emails['jpg']['msg'].get_content_subtype() == 'mixed'
103
    assert emails.emails['jpg']['msg'].get_payload()[0].get_content_type() == 'text/plain'
104
    assert emails.emails['jpg']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
105
    assert base64.b64decode(emails.emails['jpg']['msg'].get_payload()[1].get_payload()) == jpg_content
106

  
107
    send_email('txt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[txt])
108
    assert emails.emails['txt']['msg'].is_multipart()
109
    assert emails.emails['txt']['msg'].get_content_subtype() == 'mixed'
110
    assert emails.emails['txt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
111
    assert emails.emails['txt']['msg'].get_payload()[1].get_content_type() == 'text/plain'
112
    assert emails.emails['txt']['msg'].get_payload()[1].get_payload(decode=True) == b'foo-text-bar'
113

  
114
    send_email(
115
        'jpgodt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg, odt]
116
    )
117
    assert emails.emails['jpgodt']['msg'].is_multipart()
118
    assert emails.emails['jpgodt']['msg'].get_content_subtype() == 'mixed'
119
    assert emails.emails['jpgodt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
120
    assert emails.emails['jpgodt']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
121
    assert (
122
        emails.emails['jpgodt']['msg'].get_payload()[2].get_content_type()
123
        == 'application/vnd.oasis.opendocument.text'
124
    )
125
    assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[1].get_payload()) == jpg_content
126
    assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[2].get_payload()) == odt_content
127

  
128
    unknown = PicklableUpload('test.eo', 'x-foo/x-bar')
129
    unknown.receive([b'barfoo'])
130
    send_email(
131
        'unknown', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[unknown]
132
    )
133
    assert emails.emails['unknown']['msg'].is_multipart()
134
    assert emails.emails['unknown']['msg'].get_content_subtype() == 'mixed'
135
    assert emails.emails['unknown']['msg'].get_payload()[0].get_content_type() == 'text/plain'
136
    assert emails.emails['unknown']['msg'].get_payload()[1].get_content_type() == 'x-foo/x-bar'
137
    assert emails.emails['unknown']['msg'].get_payload()[1].get_payload(decode=False).strip() == 'YmFyZm9v'
138

  
139
    send_email(
140
        'test-bad-attachment',
141
        mail_body='Hello',
142
        email_rcpt='test@localhost',
143
        want_html=False,
144
        attachments=['foobad'],
145
    )
146
    assert not emails.emails['test-bad-attachment']['msg'].is_multipart()
147

  
148
    assert emails.count() == 5
149

  
150

  
151
@pytest.mark.skipif('docutils is None')
152
def test_email_plain_and_html_with_attachments(emails):
153
    pub = create_temporary_pub()
154
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
155
    jpg = PicklableUpload('test.jpeg', 'image/jpeg')
156
    with open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb') as fd:
157
        jpg.receive([fd.read()])
158

  
159
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', attachments=[jpg])
160
    assert emails.count() == 1
161
    assert emails.emails['test']['msg'].is_multipart()
162
    assert emails.emails['test']['msg'].get_content_subtype() == 'mixed'
163
    assert emails.emails['test']['msg'].get_payload()[0].is_multipart()
164
    assert emails.emails['test']['msg'].get_payload()[0].get_content_subtype() == 'alternative'
165
    assert emails.emails['test']['msg'].get_payload()[0].get_payload()[0].get_content_type() == 'text/plain'
166
    assert emails.emails['test']['msg'].get_payload()[0].get_payload()[1].get_content_type() == 'text/html'
167
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
168

  
169

  
170
@pytest.mark.skipif('docutils is None')
171
def test_email_with_enumeration(emails):
172
    pub = create_temporary_pub()
173
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
174
    mail_body = '''
175
A. FooAlpha1
176
B. FooAlpha2
177

  
178
1. Num1
179
2. Num2
180

  
181
M. Francis Kuntz
182

  
183
'''
184
    send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
185
    assert emails.count() == 1
186
    assert emails.emails['test']['msg'].is_multipart()
187
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
188
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
189
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
190
    html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
191
    assert html.count(b'<ol') == 1
192
    assert b'<ul' not in html
193
    assert b'arabic simple' in html
194
    assert b'M. Francis Kuntz' in html
195

  
196

  
197
@pytest.mark.skipif('docutils is None')
198
def test_email_with_unexpected_transition(emails):
199
    create_temporary_pub()
200
    mail_body = '''
201
Value:
202
 A
203

  
204
Other value:
205
 ?????????
206

  
207
Plop:
208
 C
209

  
210
bye,
211
'''
212
    send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
213
    assert emails.count() == 1
214
    assert emails.emails['test']['msg'].is_multipart()
215
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
216
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
217
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
218
    text = emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
219
    html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
220
    assert text.count(b'\n ?????????\n') == 1
221
    assert html.count(b'<dd>?????????</dd>') == 1
tests/test_misc.py
1
import base64
2 1
import datetime
3 2
import json
4 3
import os
5
import pwd
6 4
import re
7
import socket
8 5
import time
9 6
from unittest import mock
10 7

  
......
19 16
from wcs.fields import StringField
20 17
from wcs.qommon import evalutils, force_str
21 18
from wcs.qommon.backoffice.listing import pagination_links
22
from wcs.qommon.emails import docutils  # noqa pylint: disable=unused-import
23
from wcs.qommon.emails import email as send_email
24 19
from wcs.qommon.form import FileSizeWidget
25 20
from wcs.qommon.http_request import HTTPRequest
26 21
from wcs.qommon.humantime import humanduration2seconds, seconds2humanduration
......
34 29
    parse_isotime,
35 30
    simplify,
36 31
)
37
from wcs.qommon.upload_storage import PicklableUpload
38 32
from wcs.scripts import Script
39 33
from wcs.wf.jump import JumpWorkflowStatusItem
40 34
from wcs.workflows import Workflow
......
407 401
    assert '(1-500/1000)' in get_texts(pagination_links(0, 501, 1000))  # 500 is the max
408 402

  
409 403

  
410
def test_email_signature_plain(emails):
411
    pub = create_temporary_pub()
412
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
413
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
414
    assert emails.count() == 1
415
    assert not emails.emails['test']['msg'].is_multipart()
416
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload(decode=True)
417

  
418

  
419
def test_email_from(emails):
420
    pub = create_temporary_pub()
421
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
422
    assert emails.count() == 1
423
    assert emails.emails['test']['from'] == '%s@%s' % (pwd.getpwuid(os.getuid())[0], socket.getfqdn())
424

  
425
    pub.cfg['emails'] = {'from': 'foo@localhost'}
426
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
427
    assert emails.count() == 1
428
    assert emails.emails['test']['from'] == 'foo@localhost'
429
    assert emails.emails['test']['msg']['From'] == 'foo@localhost'
430

  
431
    if not pub.site_options.has_section('variables'):
432
        pub.site_options.add_section('variables')
433
    pub.site_options.set('variables', 'global_title', 'HELLO')
434
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', want_html=False)
435
    assert emails.count() == 1
436
    assert emails.emails['test']['from'] == 'foo@localhost'
437
    assert emails.emails['test']['msg']['From'] in (
438
        '=?utf-8?q?HELLO?= <foo@localhost>',
439
        'HELLO <foo@localhost>',
440
    )
441

  
442

  
443
@pytest.mark.skipif('docutils is None')
444
def test_email_signature_rst(emails):
445
    pub = create_temporary_pub()
446
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
447
    send_email('test', mail_body='Hello', email_rcpt='test@localhost')
448
    assert emails.count() == 1
449
    assert emails.emails['test']['msg'].is_multipart()
450
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
451
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
452
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
453
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
454
    assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
455

  
456

  
457
@pytest.mark.skipif('docutils is None')
458
def test_email_signature_rst_pipes(emails):
459
    pub = create_temporary_pub()
460
    pub.cfg['emails'] = {'footer': '| Footer\n| Text'}
461
    send_email('test', mail_body='Hello', email_rcpt='test@localhost')
462
    assert emails.count() == 1
463
    assert emails.emails['test']['msg'].is_multipart()
464
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
465
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
466
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
467
    assert b'Footer\nText' in emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
468
    assert b'>Footer<' in emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
469

  
470

  
471
def test_email_plain_with_attachments(emails):
472
    create_temporary_pub()
473

  
474
    jpg = PicklableUpload('test.jpeg', 'image/jpeg')
475
    with open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb') as fd:
476
        jpg_content = fd.read()
477
    jpg.receive([jpg_content])
478
    txt = PicklableUpload('test.txt', 'text/plain')
479
    txt.receive([b'foo-text-bar'])
480
    odt = PicklableUpload('test.odt', 'application/vnd.oasis.opendocument.text')
481
    with open(os.path.join(os.path.dirname(__file__), 'template.odt'), 'rb') as fd:
482
        odt_content = fd.read()
483
    odt.receive([odt_content])
484

  
485
    send_email('jpg', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg])
486
    assert emails.count() == 1
487
    assert emails.emails['jpg']['msg'].is_multipart()
488
    assert emails.emails['jpg']['msg'].get_content_subtype() == 'mixed'
489
    assert emails.emails['jpg']['msg'].get_payload()[0].get_content_type() == 'text/plain'
490
    assert emails.emails['jpg']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
491
    assert base64.b64decode(emails.emails['jpg']['msg'].get_payload()[1].get_payload()) == jpg_content
492

  
493
    send_email('txt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[txt])
494
    assert emails.emails['txt']['msg'].is_multipart()
495
    assert emails.emails['txt']['msg'].get_content_subtype() == 'mixed'
496
    assert emails.emails['txt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
497
    assert emails.emails['txt']['msg'].get_payload()[1].get_content_type() == 'text/plain'
498
    assert emails.emails['txt']['msg'].get_payload()[1].get_payload(decode=True) == b'foo-text-bar'
499

  
500
    send_email(
501
        'jpgodt', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[jpg, odt]
502
    )
503
    assert emails.emails['jpgodt']['msg'].is_multipart()
504
    assert emails.emails['jpgodt']['msg'].get_content_subtype() == 'mixed'
505
    assert emails.emails['jpgodt']['msg'].get_payload()[0].get_content_type() == 'text/plain'
506
    assert emails.emails['jpgodt']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
507
    assert (
508
        emails.emails['jpgodt']['msg'].get_payload()[2].get_content_type()
509
        == 'application/vnd.oasis.opendocument.text'
510
    )
511
    assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[1].get_payload()) == jpg_content
512
    assert base64.b64decode(emails.emails['jpgodt']['msg'].get_payload()[2].get_payload()) == odt_content
513

  
514
    unknown = PicklableUpload('test.eo', 'x-foo/x-bar')
515
    unknown.receive([b'barfoo'])
516
    send_email(
517
        'unknown', mail_body='Hello', email_rcpt='test@localhost', want_html=False, attachments=[unknown]
518
    )
519
    assert emails.emails['unknown']['msg'].is_multipart()
520
    assert emails.emails['unknown']['msg'].get_content_subtype() == 'mixed'
521
    assert emails.emails['unknown']['msg'].get_payload()[0].get_content_type() == 'text/plain'
522
    assert emails.emails['unknown']['msg'].get_payload()[1].get_content_type() == 'x-foo/x-bar'
523
    assert emails.emails['unknown']['msg'].get_payload()[1].get_payload(decode=False).strip() == 'YmFyZm9v'
524

  
525
    send_email(
526
        'test-bad-attachment',
527
        mail_body='Hello',
528
        email_rcpt='test@localhost',
529
        want_html=False,
530
        attachments=['foobad'],
531
    )
532
    assert not emails.emails['test-bad-attachment']['msg'].is_multipart()
533

  
534
    assert emails.count() == 5
535

  
536

  
537
@pytest.mark.skipif('docutils is None')
538
def test_email_plain_and_html_with_attachments(emails):
539
    pub = create_temporary_pub()
540
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
541
    jpg = PicklableUpload('test.jpeg', 'image/jpeg')
542
    with open(os.path.join(os.path.dirname(__file__), 'image-with-gps-data.jpeg'), 'rb') as fd:
543
        jpg.receive([fd.read()])
544

  
545
    send_email('test', mail_body='Hello', email_rcpt='test@localhost', attachments=[jpg])
546
    assert emails.count() == 1
547
    assert emails.emails['test']['msg'].is_multipart()
548
    assert emails.emails['test']['msg'].get_content_subtype() == 'mixed'
549
    assert emails.emails['test']['msg'].get_payload()[0].is_multipart()
550
    assert emails.emails['test']['msg'].get_payload()[0].get_content_subtype() == 'alternative'
551
    assert emails.emails['test']['msg'].get_payload()[0].get_payload()[0].get_content_type() == 'text/plain'
552
    assert emails.emails['test']['msg'].get_payload()[0].get_payload()[1].get_content_type() == 'text/html'
553
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'image/jpeg'
554

  
555

  
556 404
def test_cache():
557 405
    cache.set('hello', 'world')
558 406
    assert cache.get('hello') == 'world'
......
578 426
    assert normalize_geolocation({'lat': 0.0, 'lon': -400.0}) == {'lat': 0.0, 'lon': -40.0}
579 427

  
580 428

  
581
@pytest.mark.skipif('docutils is None')
582
def test_email_with_enumeration(emails):
583
    pub = create_temporary_pub()
584
    pub.cfg['emails'] = {'footer': 'Footer\nText'}
585
    mail_body = '''
586
A. FooAlpha1
587
B. FooAlpha2
588

  
589
1. Num1
590
2. Num2
591

  
592
M. Francis Kuntz
593

  
594
'''
595
    send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
596
    assert emails.count() == 1
597
    assert emails.emails['test']['msg'].is_multipart()
598
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
599
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
600
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
601
    html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
602
    assert html.count(b'<ol') == 1
603
    assert b'<ul' not in html
604
    assert b'arabic simple' in html
605
    assert b'M. Francis Kuntz' in html
606

  
607

  
608
@pytest.mark.skipif('docutils is None')
609
def test_email_with_unexpected_transition(emails):
610
    create_temporary_pub()
611
    mail_body = '''
612
Value:
613
 A
614

  
615
Other value:
616
 ?????????
617

  
618
Plop:
619
 C
620

  
621
bye,
622
'''
623
    send_email('test', mail_body=mail_body, email_rcpt='test@localhost')
624
    assert emails.count() == 1
625
    assert emails.emails['test']['msg'].is_multipart()
626
    assert emails.emails['test']['msg'].get_content_subtype() == 'alternative'
627
    assert emails.emails['test']['msg'].get_payload()[0].get_content_type() == 'text/plain'
628
    assert emails.emails['test']['msg'].get_payload()[1].get_content_type() == 'text/html'
629
    text = emails.emails['test']['msg'].get_payload()[0].get_payload(decode=True)
630
    html = emails.emails['test']['msg'].get_payload()[1].get_payload(decode=True)
631
    assert text.count(b'\n ?????????\n') == 1
632
    assert html.count(b'<dd>?????????</dd>') == 1
633

  
634

  
635 429
def test_dict_from_prefix():
636 430
    d = evalutils.dict_from_prefix('var1', {})
637 431
    assert d == {}
638
-