• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / DocumentTemplate / 16248906082

17 Mar 2025 07:56AM UTC coverage: 85.158% (-0.2%) from 85.31%
16248906082

push

github

web-flow
Update Python version support. (#79)

* Drop support for Python 3.8.

709 of 976 branches covered (72.64%)

Branch coverage included in aggregate %.

2 of 6 new or added lines in 5 files covered. (33.33%)

5 existing lines in 3 files now uncovered.

3273 of 3700 relevant lines covered (88.46%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.53
/src/DocumentTemplate/tests/testDTML.py
1
##############################################################################
2
#
3
# Copyright (c) 2002 Zope Foundation and Contributors.
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
7
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10
# FOR A PARTICULAR PURPOSE
11
#
12
##############################################################################
13
"""Document Template Tests
14
"""
15

16
import unittest
1✔
17
from html import escape
1✔
18

19
from ..html_quote import html_quote
1✔
20

21

22
try:
1✔
23
    from docutils.core import publish_string  # NOQA: F401 unused import
1✔
24
    HAVE_DOCUTILS = True
1✔
NEW
25
except ModuleNotFoundError:
×
UNCOV
26
    HAVE_DOCUTILS = False
×
27

28

29
class DTMLTests(unittest.TestCase):
1✔
30

31
    def _get_doc_class(self):
1✔
32
        from DocumentTemplate.DT_HTML import HTML
1✔
33
        return HTML
1✔
34
    doc_class = property(_get_doc_class,)
1✔
35

36
    def testBatchingEtc(self):
1✔
37

38
        def item(key, **kw):
1✔
39
            return (key, kw)
1✔
40

41
        items = (
1✔
42
            item(1, dealer='Bay Chevy', make='Chevrolet',
43
                 model='Caprice', year=96),
44
            item(2, dealer='Bay Chevy', make='Chevrolet',
45
                 model='Nova', year=96),
46
            item(4, dealer='Bay Chevy', make='Chevrolet',
47
                 model='Nova', year=96),
48
            item(5, dealer='Bay Chevy', make='Chevrolet',
49
                 model='Nova', year=96),
50
            item(3, dealer='Bay Chevy', make='Chevrolet',
51
                 model='Corvett', year=96),
52
            item(6, dealer='Bay Chevy', make='Chevrolet',
53
                 model='Lumina', year=96),
54
            item(7, dealer='Bay Chevy', make='Chevrolet',
55
                 model='Lumina', year=96),
56
            item(8, dealer='Bay Chevy', make='Chevrolet',
57
                 model='Lumina', year=95),
58
            item(9, dealer='Bay Chevy', make='Chevrolet',
59
                 model='Corsica', year=96),
60
            item(10, dealer='Bay Chevy', make='Chevrolet',
61
                 model='Corsica', year=96),
62
            item(11, dealer='Bay Chevy', make='Toyota',
63
                 model='Camry', year=95),
64
            item(12, dealer='Colman Olds', make='Olds',
65
                 model='Ciera', year=96),
66
            item(12, dealer='Colman Olds', make='Olds',
67
                 model='Ciera', year=96),
68
            item(12, dealer='Colman Olds', make='Olds',
69
                 model='Ciera', year=96),
70
            item(12, dealer='Colman Olds', make='Olds',
71
                 model='Cutlass', year=96),
72
            item(12, dealer='Colman Olds', make='Olds',
73
                 model='Cutlas', year=95),
74
            item(12, dealer='Colman Olds', make='Dodge',
75
                 model='Shadow', year=93),
76
            item(12, dealer='Colman Olds', make='Jeep',
77
                 model='Cheroke', year=94),
78
            item(12, dealer='Colman Olds', make='Toyota',
79
                 model='Previa', year=92),
80
            item(12, dealer='Colman Olds', make='Toyota',
81
                 model='Celica', year=93),
82
            item(12, dealer='Colman Olds', make='Toyota',
83
                 model='Camry', year=93),
84
            item(12, dealer='Colman Olds', make='Honda',
85
                 model='Accord', year=94),
86
            item(12, dealer='Colman Olds', make='Honda',
87
                 model='Accord', year=92),
88
            item(12, dealer='Colman Olds', make='Honda',
89
                 model='Civic', year=94),
90
            item(12, dealer='Colman Olds', make='Honda',
91
                 model='Civix', year=93),
92
            item(1, dealer='Spam Chev', make='Chevrolet',
93
                 model='Caprice', year=96),
94
            item(2, dealer='Spam Chev', make='Chevrolet',
95
                 model='Nova', year=96),
96
            item(4, dealer='Spam Chev', make='Chevrolet',
97
                 model='Nova', year=96),
98
            item(5, dealer='Spam Chev', make='Chevrolet',
99
                 model='Nova', year=96),
100
            item(3, dealer='Spam Chev', make='Chevrolet',
101
                 model='Corvett', year=96),
102
            item(6, dealer='Spam Chev', make='Chevrolet',
103
                 model='Lumina', year=96),
104
            item(7, dealer='Spam Chev', make='Chevrolet',
105
                 model='Lumina', year=96),
106
            item(8, dealer='Spam Chev', make='Chevrolet',
107
                 model='Lumina', year=95),
108
            item(9, dealer='Spam Chev', make='Chevrolet',
109
                 model='Corsica', year=96),
110
            item(10, dealer='Spam Chev', make='Chevrolet',
111
                 model='Corsica', year=96),
112
            item(11, dealer='Spam Chevy', make='Toyota',
113
                 model='Camry', year=95),
114
            item(12, dealer='Spam Olds', make='Olds',
115
                 model='Ciera', year=96),
116
            item(12, dealer='Spam Olds', make='Olds',
117
                 model='Ciera', year=96),
118
            item(12, dealer='Spam Olds', make='Olds',
119
                 model='Ciera', year=96),
120
            item(12, dealer='Spam Olds', make='Olds',
121
                 model='Cutlass', year=96),
122
            item(12, dealer='Spam Olds', make='Olds',
123
                 model='Cutlas', year=95),
124
            item(12, dealer='Spam Olds', make='Dodge',
125
                 model='Shadow', year=93),
126
            item(12, dealer='Spam Olds', make='Jeep',
127
                 model='Cheroke', year=94),
128
            item(12, dealer='Spam Olds', make='Toyota',
129
                 model='Previa', year=92),
130
            item(12, dealer='Spam Olds', make='Toyota',
131
                 model='Celica', year=93),
132
            item(12, dealer='Spam Olds', make='Toyota',
133
                 model='Camry', year=93),
134
            item(12, dealer='Spam Olds', make='Honda',
135
                 model='Accord', year=94),
136
            item(12, dealer='Spam Olds', make='Honda',
137
                 model='Accord', year=92),
138
            item(12, dealer='Spam Olds', make='Honda',
139
                 model='Civic', year=94),
140
            item(12, dealer='Spam Olds', make='Honda',
141
                 model='Civix', year=93),
142
        )
143

144
        html = self.doc_class(read_file('dealers.dtml'))
1✔
145
        res = html(inventory=items, first_ad=15)
1✔
146
        expected = read_file('dealers.out')
1✔
147
        self.assertEqual(res, expected)
1✔
148

149
    def testSequenceSummaries(self):
1✔
150
        data = (dict(name='jim', age=38),
1✔
151
                dict(name='will', age=7),
152
                dict(name='drew', age=4),
153
                dict(name='ches', age=1),
154
                )
155
        html = self.doc_class(
1✔
156
            '<dtml-in data mapping>'
157
            '<dtml-if sequence-end>'
158
            'Variable "name": '
159
            'min=<dtml-var min-name> '
160
            'max=<dtml-var max-name> '
161
            'count=<dtml-var count-name> '
162
            'total=<dtml-var total-name> '
163
            'median=<dtml-var median-name> '
164
            'Variable "age": '
165
            'min=<dtml-var min-age> '
166
            'max=<dtml-var max-age> '
167
            'count=<dtml-var count-age> '
168
            'total=<dtml-var total-age> '
169
            'median=<dtml-var median-age> '
170
            'mean=<dtml-var mean-age> '
171
            '<dtml-let sda=standard-deviation-age>'
172
            's.d.=<dtml-var expr="_.int(sda)">'
173
            '</dtml-let>'
174
            '</dtml-if sequence-end>'
175
            '</dtml-in data>')
176
        res = html(data=data)
1✔
177
        expected = ('Variable "name": min=ches max=will count=4 total= '
1✔
178
                    'median=between jim and drew '
179
                    'Variable "age": min=1 max=38 count=4 total=50 '
180
                    'median=5 mean=12.5 s.d.=17')
181
        self.assertEqual(res, expected)
1✔
182

183
    def testDTMLDateFormatting(self):
1✔
184
        import DateTime
1✔
185
        html = self.doc_class(
1✔
186
            "<dtml-var name capitalize spacify> is "
187
            "<dtml-var date fmt=year>/<dtml-var date "
188
            "fmt=month>/<dtml-var date fmt=day>")
189
        res = html(date=DateTime.DateTime("1995-12-25"),
1✔
190
                   name='christmas_day')
191
        expected = 'Christmas day is 1995/12/25'
1✔
192
        self.assertEqual(res, expected)
1✔
193

194
    def testSimpleString(self):
1✔
195
        from DocumentTemplate.DT_HTML import String
1✔
196
        dt = String('%(name)s')
1✔
197
        res = dt(name='Chris')
1✔
198
        expected = 'Chris'
1✔
199
        self.assertEqual(res, expected)
1✔
200

201
    def testSyntaxErrorHandling(self):
1✔
202
        from ..DT_Util import ParseError
1✔
203
        html = self.doc_class('<dtml-var "&%$#">')
1✔
204

205
        self.assertRaises(ParseError, html)
1✔
206

207
    def testStringDateFormatting(self):
1✔
208
        import DateTime
1✔
209

210
        from DocumentTemplate.DT_HTML import String
1✔
211
        html = String("%(name capitalize spacify)s is "
1✔
212
                      "%(date fmt=year)s/%(date fmt=month)s/%(date fmt=day)s")
213
        res = html(date=DateTime.DateTime("2001-04-27"),
1✔
214
                   name='the_date')
215
        expected = 'The date is 2001/4/27'
1✔
216
        self.assertEqual(res, expected)
1✔
217

218
    def testSequence1(self):
1✔
219
        html = self.doc_class(
1✔
220
            '<dtml-in spam><dtml-in sequence-item><dtml-var sequence-item> '
221
            '</dtml-in sequence-item></dtml-in spam>')
222
        expected = '1 2 3 4 5 6 '
1✔
223
        res = html(spam=[[1, 2, 3], [4, 5, 6]])
1✔
224
        self.assertEqual(res, expected)
1✔
225

226
    def testSequence2(self):
1✔
227
        html = self.doc_class(
1✔
228
            '<dtml-in spam><dtml-in sequence-item><dtml-var sequence-item>-'
229
            '</dtml-in sequence-item></dtml-in spam>')
230
        expected = '1-2-3-4-5-6-'
1✔
231
        res = html(spam=[[1, 2, 3], [4, 5, 6]])
1✔
232
        self.assertEqual(res, expected)
1✔
233

234
    def testNull(self):
1✔
235
        html = self.doc_class('<dtml-var spam fmt="$%.2f bobs your uncle" '
1✔
236
                              'null="spam%eggs!|">')
237
        expected = '$42.00 bobs your unclespam%eggs!|'
1✔
238
        res = html(spam=42) + html(spam=None)
1✔
239
        self.assertEqual(res, expected)
1✔
240

241
    def testSkipQuote(self):
1✔
242
        methods = "html_quote",
1✔
243
        a = '\0he>llo'
1✔
244
        for method in methods:
1✔
245
            expected = html_quote(a)
1✔
246

247
            html = self.doc_class('<dtml-var a %s>' % method)
1✔
248
            self.assertEqual(html(a=a), expected)
1✔
249

250
            html = self.doc_class('&dtml.%s-a;' % method)
1✔
251
            self.assertEqual(html(a=a), expected)
1✔
252

253
    def testUrlUnquote(self):
1✔
254
        html1 = self.doc_class(
1✔
255
            '<dtml-var expr="\'http%3A//www.zope.org%3Fa%3Db%20123\'" '
256
            'fmt=url-unquote>')
257
        html2 = self.doc_class(
1✔
258
            '<dtml-var expr="\'http%3A%2F%2Fwww.zope.org%3Fa%3Db+123\'" '
259
            'fmt=url-unquote-plus>')
260
        expected = 'http://www.zope.org?a=b 123'
1✔
261
        self.assertEqual(html1(), expected)
1✔
262
        self.assertEqual(html2(), expected)
1✔
263

264
        html1 = self.doc_class(
1✔
265
            '<dtml-var expr="\'http%3A//www.zope.org%3Fa%3Db%20123\'" '
266
            'url_unquote>')
267
        html2 = self.doc_class(
1✔
268
            '<dtml-var expr="\'http%3A%2F%2Fwww.zope.org%3Fa%3Db+123\'" '
269
            'url_unquote_plus>')
270
        expected = 'http://www.zope.org?a=b 123'
1✔
271
        self.assertEqual(html1(), expected)
1✔
272
        self.assertEqual(html2(), expected)
1✔
273

274
    def test_sql_quote(self):
1✔
275
        html = self.doc_class('<dtml-var x sql_quote>')
1✔
276
        special = '\xae'
1✔
277

278
        self.assertEqual(html(x='x'), 'x')
1✔
279
        self.assertEqual(html(x=b'x'), 'x')
1✔
280
        self.assertEqual(html(x="Moe's Bar"), "Moe''s Bar")
1✔
281
        self.assertEqual(html(x=b"Moe's Bar"), "Moe''s Bar")
1✔
282

283
        self.assertEqual(html(x="Moe's B%sr" % special),
1✔
284
                         "Moe''s B%sr" % special)
285
        self.assertEqual(html(x=b"Moe's B%sr" % special.encode('UTF-8')),
1✔
286
                         "Moe''s B%sr" % special)
287

288
    def test_fmt(self):
1✔
289
        html = self.doc_class(
1✔
290
            """
291
            <dtml-var spam>
292
            html=<dtml-var spam fmt=html-quote>
293
            url=<dtml-var spam fmt=url-quote>
294
            multi=<dtml-var spam fmt=multi-line>
295
            dollars=<dtml-var spam fmt=whole-dollars>
296
            cents=<dtml-var spam fmt=dollars-and-cents>
297
            dollars,=<dtml-var spam fmt=dollars-with-commas>
298
            cents,=<dtml-var spam fmt=dollars-and-cents-with-commas>""")
299

300
        expected = (
1✔
301
            '''
302
            4200000
303
            html=4200000
304
            url=4200000
305
            multi=4200000
306
            dollars=$4200000
307
            cents=$4200000.00
308
            dollars,=$4,200,000
309
            cents,=$4,200,000.00
310
            None
311
            html=None
312
            url=None
313
            multi=None
314
            dollars=
315
            cents=
316
            dollars,=
317
            cents,=
318
            <a href="spam">
319
foo bar
320
            html=&lt;a href=&quot;spam&quot;&gt;
321
foo bar
322
            url=%3Ca%20href%3D%22spam%22%3E%0Afoo%20bar
323
            multi=<a href="spam"><br />
324
foo bar
325
            dollars=
326
            cents=
327
            dollars,=
328
            cents,=''')
329

330
        res = html(spam=4200000) + html(spam=None) + html(
1✔
331
            spam='<a href="spam">\nfoo bar')
332
        self.assertEqual(res, expected)
1✔
333

334
    def testPropogatedError(self):
1✔
335
        from ExtensionClass import Base
1✔
336

337
        class foo:
1✔
338
            def __len__(self):
1✔
339
                return 9
1✔
340

341
            def __getitem__(self, i):
1✔
342
                if i >= 9:
1!
343
                    raise IndexError(i)
×
344
                return self.testob(i)
1✔
345

346
            class testob(Base):
1✔
347

348
                __roles__ = None  # Public
1✔
349

350
                def __init__(self, index):
1✔
351
                    self.index = index
1✔
352
                    self.value = 'item %s' % index
1✔
353

354
                getValue__roles__ = None  # Public
1✔
355

356
                def getValue(self):
1✔
357
                    return self.value
1✔
358

359
                puke__roles__ = None  # Public
1✔
360

361
                def puke(self):
1✔
362
                    raise PukeError('raaalf')
1✔
363

364
        html = self.doc_class(
1✔
365
            """
366
            <dtml-if spam>
367
            <dtml-in spam>
368
            <dtml-var getValue>
369
            <dtml-var puke>
370
            </dtml-in spam>
371
            </dtml-if spam>
372
            """)
373
        try:
1✔
374
            html(spam=foo())
1✔
375
        except PukeError:
1✔
376
            # Passed the test.
377
            pass
1✔
378
        else:
379
            assert 0, 'Puke error not propogated'
×
380

381
    def testRenderCallable(self):
1✔
382
        # Test automatic rendering of callable objects
383
        from ExtensionClass import Base
1✔
384

385
        class C(Base):
1✔
386
            __allow_access_to_unprotected_subobjects__ = 1
1✔
387
            x = 1
1✔
388

389
            def y(self):
1✔
390
                return self.x * 2
1✔
391

392
        C.h = self.doc_class("The h method, <dtml-var x> <dtml-var y>")
1✔
393
        C.h2 = self.doc_class("The h2 method")
1✔
394

395
        expected = "1, 2, The h method, 1 2"
1✔
396
        res = self.doc_class("<dtml-var x>, <dtml-var y>, <dtml-var h>")(C())
1✔
397
        self.assertEqual(res, expected)
1✔
398

399
        expected = (
1✔
400
            '''
401
            1,
402
            2,
403
            The h2 method''')
404
        res = self.doc_class(
1✔
405
            '''
406
            <dtml-var expr="_.render(i.x)">,
407
            <dtml-var expr="_.render(i.y)">,
408
            <dtml-var expr="_.render(i.h2)">''')(i=C())
409
        self.assertEqual(res, expected)
1✔
410

411
    def testWith(self):
1✔
412
        class person:
1✔
413
            __allow_access_to_unprotected_subobjects__ = 1
1✔
414
            name = 'Jim'
1✔
415
            height_inches = 73
1✔
416

417
        expected = 'Hi, my name is %s and my height is %d cm.' % (
1✔
418
            person.name, int(person.height_inches * 2.54))
419

420
        res = self.doc_class(
1✔
421
            '<dtml-with person>Hi, my name is <dtml-var name> '
422
            'and my height is <dtml-var "_.int(height_inches*2.54)"> '
423
            'cm.</dtml-with>')(person=person)
424
        self.assertEqual(res, expected)
1✔
425

426
    def testRaise(self):
1✔
427
        try:
1✔
428
            res = self.doc_class(
1✔
429
                "<dtml-raise IndexError>success!</dtml-raise>")()
430
        except IndexError as v:
1✔
431
            res = v
1✔
432
        assert str(res) == 'success!'
1✔
433

434
    def testNoItemPush(self):
1✔
435
        data = dict(sec='B',
1✔
436
                    name='XXX',
437
                    sub=(dict(name='b1'), dict(name='b2', sec='XXX')))
438
        html = """
1✔
439
<dtml-with data mapping><dtml-in sub no_push_item>
440
    <dtml-var sec>.<dtml-with sequence-item mapping><dtml-var name></dtml-with>
441
</dtml-in></dtml-with>
442
"""
443
        expected = """
1✔
444
    B.b1    B.b2"""
445
        result = self.doc_class(html)(data=data)
1✔
446
        self.assertEqual(result, expected)
1✔
447

448
    def testBasicHTMLIn(self):
1✔
449
        data = (
1✔
450
            dict(name='jim', age=39),
451
            dict(name='kak', age=29),
452
            dict(name='will', age=8),
453
            dict(name='andrew', age=5),
454
            dict(name='chessie', age=2),
455
        )
456

457
        html = """
1✔
458
<!--#in data mapping-->
459
   <!--#var name-->, <!--#var age-->
460
<!--#/in-->
461
"""
462
        expected = """
1✔
463
   jim, 39
464
   kak, 29
465
   will, 8
466
   andrew, 5
467
   chessie, 2
468
"""
469
        result = self.doc_class(html)(data=data)
1✔
470
        self.assertEqual(result, expected)
1✔
471

472
    def testBasicHTMLIn2(self):
1✔
473
        xxx = (Dummy(name=1), Dummy(name=2), Dummy(name=3))
1✔
474
        html = """
1✔
475
<!--#in xxx-->
476
   <!--#var name  -->
477
<!--#/in-->
478
"""
479
        expected = """
1✔
480
   1
481
   2
482
   3
483
"""
484
        result = self.doc_class(html)(xxx=xxx)
1✔
485
        self.assertEqual(result, expected)
1✔
486

487
    def testBasicHTMLIn3(self):
1✔
488
        ns = {'prop_ids': ('title', 'id'), 'title': 'good', 'id': 'times'}
1✔
489
        html = """:<dtml-in prop_ids><dtml-var sequence-item>=<dtml-var
1✔
490
        expr="_[_['sequence-item']]">:</dtml-in>"""
491
        result = self.doc_class(html)(None, ns)
1✔
492
        expected = ":title=good:id=times:"
1✔
493
        self.assertEqual(result, expected)
1✔
494

495
    def testHTMLInElse(self):
1✔
496
        xxx = (Dummy(name=1), Dummy(name=2), Dummy(name=3))
1✔
497
        html = """
1✔
498
<!--#in data mapping-->
499
<!--#var name-->, <!--#var age-->
500
<!--#else-->
501
<!--#in xxx-->
502
<!--#var name -->
503
<!--#/in-->
504
<!--#/in-->
505
"""
506
        expected = """
1✔
507
1
508
2
509
3
510
"""
511
        result = self.doc_class(html)(xxx=xxx, data={})
1✔
512
        self.assertEqual(result, expected)
1✔
513

514
    def testBasicStringIn(self):
1✔
515
        from DocumentTemplate.DT_HTML import String
1✔
516
        data = (
1✔
517
            dict(name='jim', age=39),
518
            dict(name='kak', age=29),
519
            dict(name='will', age=8),
520
            dict(name='andrew', age=5),
521
            dict(name='chessie', age=2),
522
        )
523
        s = """
1✔
524
%(in data mapping)[
525
   %(name)s, %(age)s
526
%(in)]
527
"""
528
        expected = """
1✔
529
   jim, 39
530
   kak, 29
531
   will, 8
532
   andrew, 5
533
   chessie, 2
534
"""
535
        result = String(s)(data=data)
1✔
536
        self.assertEqual(result, expected)
1✔
537

538

539
@unittest.skipUnless(HAVE_DOCUTILS,
1✔
540
                     'No docutils, skipping reStructuredText tests.')
541
class RESTTests(DTMLTests):
1✔
542

543
    def test_fmt_reST_include_directive_raises(self):
1✔
544
        source = '.. include:: /etc/passwd'
1✔
545
        html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">')
1✔
546
        html._vars['foo'] = source
1✔
547
        result = html()
1✔
548

549
        # The include: directive hasn't been rendered, it remains
550
        # verbatimly in the rendered output.  Instead a warning
551
        # message is presented:
552
        self.assertIn(source, result)
1✔
553
        self.assertIn(docutils_include_warning, result)
1✔
554

555
    def test_fmt_reST_raw_directive_disabled(self):
1✔
556
        EXPECTED = '<h1>HELLO WORLD</h1>'
1✔
557
        source = '.. raw:: html\n\n  %s\n' % EXPECTED
1✔
558
        html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">')
1✔
559
        html._vars['foo'] = source
1✔
560
        result = html()
1✔
561

562
        # The raw: directive hasn't been rendered, it remains
563
        # verbatimly in the rendered output.  Instead a warning
564
        # message is presented:
565
        self.assertNotIn(EXPECTED, result)
1✔
566
        self.assertIn(escape(EXPECTED), result)
1✔
567
        self.assertIn(docutils_raw_warning, result)
1✔
568

569
    def test_fmt_reST_raw_directive_file_option_raises(self):
1✔
570
        source = '.. raw:: html\n  :file: inclusion.txt'
1✔
571
        html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">')
1✔
572
        html._vars['foo'] = source
1✔
573
        result = html()
1✔
574

575
        # The raw: directive hasn't been rendered, it remains
576
        # verbatimly in the rendered output.  Instead a warning
577
        # message is presented:
578
        self.assertIn(source, result)
1✔
579
        self.assertIn(docutils_raw_warning, result)
1✔
580

581
    def test_fmt_reST_raw_directive_url_option_raises(self):
1✔
582
        source = '.. raw:: html\n  :url: http://www.zope.org'
1✔
583
        html = self.doc_class('<dtml-var name="foo" fmt="restructured-text">')
1✔
584
        html._vars['foo'] = source
1✔
585
        result = html()
1✔
586

587
        # The raw: directive hasn't been rendered, it remains
588
        # verbatimly in the rendered output.  Instead a warning
589
        # message is presented:
590
        self.assertIn(source, result)
1✔
591
        self.assertIn(docutils_raw_warning, result)
1✔
592

593

594
def read_file(name):
1✔
595
    import os
1✔
596

597
    from DocumentTemplate import tests
1✔
598
    here = tests.__path__[0]
1✔
599
    with open(os.path.join(here, name)) as fd:
1✔
600
        res = fd.read()
1✔
601
    return res
1✔
602

603

604
class Dummy:
1✔
605
    __allow_access_to_unprotected_subobjects__ = 1
1✔
606

607
    def __init__(self, **kw):
1✔
608
        self.__dict__.update(kw)
1✔
609

610
    def __repr__(self):
1✔
611
        return "Dummy(%r)" % self.__dict__
×
612

613

614
docutils_include_warning = (
1✔
615
    '<p class="system-message-title">System Message: WARNING/2 '
616
    '(<tt class="docutils">&lt;string&gt;</tt>, line 1)</p>\n'
617
    '<p>&quot;include&quot; directive disabled.</p>'
618
)
619

620
docutils_raw_warning = (
1✔
621
    '<p class="system-message-title">System Message: WARNING/2 '
622
    '(<tt class="docutils">&lt;string&gt;</tt>, line 1)</p>\n'
623
    '<p>&quot;raw&quot; directive disabled.</p>')
624

625

626
class PukeError(Exception):
1✔
627
    """Exception raised in test code."""
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc