Coverage for core\test_leoImport.py: 100%

595 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-24 10:21 -0500

1# -*- coding: utf-8 -*- 

2#@+leo-ver=5-thin 

3#@+node:ekr.20210904064440.2: * @file ../unittests/core/test_leoImport.py 

4#@@first 

5"""Tests of leoImport.py""" 

6 

7import glob 

8import importlib 

9import sys 

10import textwrap 

11from leo.core import leoGlobals as g 

12from leo.core.leoTest2 import LeoUnitTest 

13# Import all tested scanners. 

14import leo.plugins.importers.coffeescript as cs 

15import leo.plugins.importers.dart as dart 

16import leo.plugins.importers.linescanner as linescanner 

17import leo.plugins.importers.markdown as markdown 

18import leo.plugins.importers.org as org 

19import leo.plugins.importers.otl as otl 

20import leo.plugins.importers.pascal as pascal 

21import leo.plugins.importers.xml as xml 

22#@+others 

23#@+node:ekr.20210904064440.3: ** class BaseTestImporter(LeoUnitTest) 

24class BaseTestImporter(LeoUnitTest): 

25 """The base class for tests of leoImport.py""" 

26 

27 ext = None # Subclasses must set this to the language's extension. 

28 treeType = '@file' # Fix #352. 

29 

30 def setUp(self): 

31 super().setUp() 

32 g.app.loadManager.createAllImporterData() 

33 

34 #@+others 

35 #@+node:ekr.20211128045212.1: *3* BaseTestImporter.check_headlines 

36 def check_headlines(self, p, table): 

37 """Check that p and its subtree have the structure given in the table.""" 

38 # Check structure 

39 p1 = p.copy() 

40 try: 

41 self.assertEqual(p1.h, f"{self.treeType} {self.short_id}") 

42 i = 0 

43 for p in p1.subtree(): 

44 self.assertTrue(i < len(table), msg=repr(p.h)) 

45 data = table[i] 

46 i += 1 

47 n, h = data 

48 self.assertEqual(p.h, h) 

49 # Subtract 1 for compatibility with values in previous tables. 

50 self.assertEqual(p.level() - 1, n, msg=f"{p.h}: expected level {n}, got {p.level()}") 

51 # Make sure there are no extra nodes in p's tree. 

52 self.assertEqual(i, len(table), msg=f"i: {i}, len(table): {len(table)}") 

53 except AssertionError: # pragma: no cover 

54 g.trace(self.short_id) 

55 self.dump_tree(p1) 

56 raise 

57 #@+node:ekr.20211126052156.1: *3* BaseTestImporter.compare_outlines 

58 def compare_outlines(self, created_p, expected_p): # pragma: no cover 

59 """ 

60 Ensure that the created and expected trees have equal shape and contents. 

61 

62 Also ensure that all created nodes have the expected node kind. 

63 """ 

64 d = g.vnode_info 

65 p1, p2 = created_p.copy(), expected_p.copy() 

66 try: 

67 after1, after2 = p1.nodeAfterTree(), p2.nodeAfterTree() 

68 while p1 and p2 and p1 != after1 and p2 != after2: 

69 aList1 = d.get(p1.v)['kind'].split(':') 

70 aList2 = d.get(p2.v)['kind'].split(':') 

71 kind1, kind2 = aList1[0], aList2[0] 

72 self.assertEqual(p1.h, p2.h) 

73 self.assertEqual(p1.numberOfChildren(), p2.numberOfChildren(), msg=p1.h) 

74 self.assertEqual(p1.b.strip(), p2.b.strip(), msg=p1.h) 

75 self.assertEqual(kind1, kind2, msg=p1.h) 

76 p1.moveToThreadNext() 

77 p2.moveToThreadNext() 

78 # Make sure both trees end at the same time. 

79 self.assertTrue(not p1 or p1 == after1) 

80 self.assertTrue(not p2 or p2 == after2) 

81 except AssertionError: 

82 g.es_exception() 

83 self.dump_tree(created_p, tag='===== Created') 

84 self.dump_tree(expected_p, tag='===== Expected') 

85 raise 

86 #@+node:ekr.20211108044605.1: *3* BaseTestImporter.compute_unit_test_kind 

87 def compute_unit_test_kind(self, ext): 

88 """Return kind from the given extention.""" 

89 aClass = g.app.classDispatchDict.get(ext) 

90 kind = {'.md': '@auto-md' 

91 , '.org': '@auto-org' 

92 , '.otl': '@auto-otl' 

93 , '.rst': '@auto-rst' 

94 }.get(ext) 

95 if kind: 

96 return kind 

97 if aClass: 

98 d2 = g.app.atAutoDict 

99 for z in d2: 

100 if d2.get(z) == aClass: 

101 return z # pragma: no cover 

102 return '@file' 

103 #@+node:ekr.20211129062220.1: *3* BaseTestImporter.dump_tree 

104 def dump_tree(self, root, tag=None): # pragma: no cover 

105 """Dump root's tree just as as Importer.dump_tree.""" 

106 d = g.vnode_info # Same as Importer.vnode_info! 

107 if tag: 

108 print(tag) 

109 for p in root.self_and_subtree(): 

110 print('') 

111 print('level:', p.level(), p.h) 

112 lines = d[p.v]['lines'] if p.v in d else g.splitLines(p.v.b) 

113 g.printObj(lines) 

114 #@+node:ekr.20211127042843.1: *3* BaseTestImporter.run_test 

115 def run_test(self, s): 

116 """ 

117 Run a unit test of an import scanner, 

118 i.e., create a tree from string s at location p. 

119 """ 

120 c, ext, p = self.c, self.ext, self.c.p 

121 self.assertTrue(ext) 

122 # Run the test. 

123 parent = p.insertAsLastChild() 

124 kind = self.compute_unit_test_kind(ext) 

125 # TestCase.id() has the form leo.unittests.core.file.class.test_name 

126 id_parts = self.id().split('.') 

127 self.short_id = f"{id_parts[-2]}.{id_parts[-1]}" 

128 parent.h = f"{kind} {self.short_id}" 

129 # createOutline calls Importer.gen_lines and Importer.check. 

130 test_s = textwrap.dedent(s).strip() + '\n\n' 

131 ok = c.importCommands.createOutline(parent.copy(), ext, test_s) 

132 if not ok: # pragma: no cover 

133 self.dump_tree(parent) 

134 self.fail('Perfect import failed') # pragma: no cover 

135 return parent 

136 #@-others 

137#@+node:ekr.20211108052633.1: ** class TestAtAuto (BaseTestImporter) 

138class TestAtAuto(BaseTestImporter): 

139 

140 #@+others 

141 #@+node:ekr.20210904065459.122: *3* TestAtAuto.test_importers_can_be_imported 

142 def test_importers_can_be_imported(self): 

143 path = g.os_path_finalize_join(g.app.loadDir, '..', 'plugins', 'importers') 

144 assert g.os_path_exists(path), repr(path) 

145 pattern = g.os_path_finalize_join(path, '*.py') 

146 for fn in glob.glob(pattern): 

147 sfn = g.shortFileName(fn) 

148 m = importlib.import_module('leo.plugins.importers.%s' % sfn[:-3]) 

149 assert m 

150 #@-others 

151#@+node:ekr.20211108062025.1: ** class TestC (BaseTestImporter) 

152class TestC(BaseTestImporter): 

153 

154 ext = '.c' 

155 

156 #@+others 

157 #@+node:ekr.20210904065459.3: *3* TestC.test_c_class_1 

158 def test_c_class_1(self): 

159 

160 s = """ 

161 class cTestClass1 { 

162 

163 int foo (int a) { 

164 a = 2 ; 

165 } 

166 

167 char bar (float c) { 

168 ; 

169 } 

170 } 

171 """ 

172 p = self.run_test(s) 

173 self.check_headlines(p, ( 

174 (1, 'class cTestClass1'), 

175 (2, 'int foo'), 

176 (2, 'char bar'), 

177 )) 

178 #@+node:ekr.20210904065459.4: *3* TestC.test_class_underindented_line 

179 def test_class_underindented_line(self): 

180 

181 s = """ 

182 class cTestClass1 { 

183 

184 int foo (int a) { 

185 // an underindented line. 

186 a = 2 ; 

187 } 

188 

189 // This should go with the next function. 

190 

191 char bar (float c) { 

192 ; 

193 } 

194 } 

195 """ 

196 p = self.run_test(s) 

197 self.check_headlines(p, ( 

198 (1, 'class cTestClass1'), 

199 (2, 'int foo'), 

200 (2, 'char bar'), 

201 )) 

202 

203 #@+node:ekr.20210904065459.5: *3* TestC.test_comment_follows_arg_list 

204 def test_comment_follows_arg_list(self): 

205 

206 s = """ 

207 void 

208 aaa::bbb::doit 

209 ( 

210 awk* b 

211 ) 

212 { 

213 assert(false); 

214 } 

215 

216 bool 

217 aaa::bbb::dothat 

218 ( 

219 xyz *b 

220 ) // <---------------------problem 

221 { 

222 return true; 

223 } 

224 """ 

225 p = self.run_test(s) 

226 self.check_headlines(p, ( 

227 (1, 'void aaa::bbb::doit'), 

228 (1, 'bool aaa::bbb::dothat'), 

229 )) 

230 #@+node:ekr.20210904065459.6: *3* TestC.test_comment_follows_block_delim 

231 def test_comment_follows_block_delim(self): 

232 

233 s = """ 

234 void 

235 aaa::bbb::doit 

236 ( 

237 awk* b 

238 ) 

239 { 

240 assert(false); 

241 } 

242 

243 bool 

244 aaa::bbb::dothat 

245 ( 

246 xyz *b 

247 ) 

248 { 

249 return true; 

250 } // <--------------------- problem 

251 """ 

252 p = self.run_test(s) 

253 self.check_headlines(p, ( 

254 (1, 'void aaa::bbb::doit'), 

255 (1, 'bool aaa::bbb::dothat'), 

256 )) 

257 #@+node:ekr.20210904065459.10: *3* TestC.test_extern 

258 def test_extern(self): 

259 

260 s = """ 

261 extern "C" 

262 { 

263 #include "stuff.h" 

264 void init(void); 

265 #include "that.h" 

266 } 

267 """ 

268 p = self.run_test(s) 

269 self.check_headlines(p, ( 

270 (1, 'extern "C"'), 

271 )) 

272 #@+node:ekr.20210904065459.7: *3* TestC.test_intermixed_blanks_and_tabs 

273 def test_intermixed_blanks_and_tabs(self): 

274 

275 s = """ 

276 void 

277 aaa::bbb::doit 

278 ( 

279 awk* b // leading blank 

280 ) 

281 { 

282 assert(false); // leading tab 

283 } 

284 """ 

285 p = self.run_test(s) 

286 self.check_headlines(p, ( 

287 (1, 'void aaa::bbb::doit'), 

288 )) 

289 #@+node:ekr.20210904065459.8: *3* TestC.test_old_style_decl_1 

290 def test_old_style_decl_1(self): 

291 

292 s = """ 

293 static void 

294 ReleaseCharSet(cset) 

295 CharSet *cset; 

296 { 

297 ckfree((char *)cset->chars); 

298 if (cset->ranges) { 

299 ckfree((char *)cset->ranges); 

300 } 

301 } 

302 """ 

303 p = self.run_test(s) 

304 self.check_headlines(p, ( 

305 (1, 'static void ReleaseCharSet'), 

306 )) 

307 #@+node:ekr.20210904065459.9: *3* TestC.test_old_style_decl_2 

308 def test_old_style_decl_2(self): 

309 

310 s = """ 

311 Tcl_Obj * 

312 Tcl_NewLongObj(longValue) 

313 register long longValue; /* Long integer used to initialize the 

314 * new object. */ 

315 { 

316 return Tcl_DbNewLongObj(longValue, "unknown", 0); 

317 } 

318 """ 

319 p = self.run_test(s) 

320 self.check_headlines(p, ( 

321 (1, 'Tcl_Obj * Tcl_NewLongObj'), 

322 )) 

323 #@-others 

324#@+node:ekr.20211108063520.1: ** class TestCoffeescript (BaseTextImporter) 

325class TestCoffeescript(BaseTestImporter): 

326 

327 ext = '.coffee' 

328 

329 #@+others 

330 #@+node:ekr.20210904065459.15: *3* TestCoffeescript.test_1 

331 def test_1(self): 

332 

333 s = r''' 

334 

335 # Js2coffee relies on Narcissus's parser. 

336 

337 {parser} = @Narcissus or require('./narcissus_packed') 

338 

339 # Main entry point 

340 

341 buildCoffee = (str) -> 

342 str = str.replace /\r/g, '' 

343 str += "\n" 

344 

345 builder = new Builder 

346 scriptNode = parser.parse str 

347 ''' 

348 p = self.run_test(s) 

349 self.check_headlines(p, ( 

350 (1, 'buildCoffee = (str) ->'), 

351 )) 

352 #@+node:ekr.20210904065459.16: *3* TestCoffeescript.test_2 

353 #@@tabwidth -2 # Required 

354 

355 def test_2(self): 

356 

357 s = """ 

358 class Builder 

359 constructor: -> 

360 @transformer = new Transformer 

361 # `build()` 

362 

363 build: (args...) -> 

364 node = args[0] 

365 @transform node 

366 

367 name = 'other' 

368 name = node.typeName() if node != undefined and node.typeName 

369 

370 fn = (@[name] or @other) 

371 out = fn.apply(this, args) 

372 

373 if node.parenthesized then paren(out) else out 

374 # `transform()` 

375 

376 transform: (args...) -> 

377 @transformer.transform.apply(@transformer, args) 

378 

379 # `body()` 

380 

381 body: (node, opts={}) -> 

382 str = @build(node, opts) 

383 str = blockTrim(str) 

384 str = unshift(str) 

385 if str.length > 0 then str else "" 

386 """ 

387 p = self.run_test(s) 

388 self.check_headlines(p, ( 

389 (1, 'class Builder'), 

390 (2, 'constructor: ->'), 

391 (2, 'build: (args...) ->'), 

392 (2, 'transform: (args...) ->'), 

393 (2, 'body: (node, opts={}) ->'), 

394 )) 

395 

396 #@+node:ekr.20211108085023.1: *3* TestCoffeescript.test_get_leading_indent 

397 def test_get_leading_indent(self): 

398 c = self.c 

399 importer = linescanner.Importer(c.importCommands, language='coffeescript') 

400 self.assertEqual(importer.single_comment, '#') 

401 #@+node:ekr.20210904065459.126: *3* TestCoffeescript.test_scan_line 

402 def test_scan_line(self): 

403 c = self.c 

404 x = cs.CS_Importer(c.importCommands, atAuto=True) 

405 self.assertEqual(x.single_comment, '#') 

406 #@-others 

407#@+node:ekr.20211108062958.1: ** class TestCSharp (BaseTestImporter) 

408class TestCSharp(BaseTestImporter): 

409 

410 ext = '.c#' 

411 

412 #@+others 

413 #@+node:ekr.20210904065459.12: *3* TestCSharp.test_namespace_indent 

414 def test_namespace_indent(self): 

415 

416 s = """ 

417 namespace { 

418 class cTestClass1 { 

419 ; 

420 } 

421 } 

422 """ 

423 p = self.run_test(s) 

424 self.check_headlines(p, ( 

425 (1, 'namespace'), 

426 (2, 'class cTestClass1'), 

427 )) 

428 #@+node:ekr.20210904065459.13: *3* TestImport.test_namespace_no_indent 

429 def test_namespace_no_indent(self): 

430 

431 s = """ 

432 namespace { 

433 class cTestClass1 { 

434 ; 

435 } 

436 } 

437 """ 

438 p = self.run_test(s) 

439 self.check_headlines(p, ( 

440 (1, 'namespace'), 

441 (2, 'class cTestClass1') 

442 )) 

443 #@-others 

444#@+node:ekr.20211108063908.1: ** class TestCython (BaseTestImporter) 

445class TestCython(BaseTestImporter): 

446 

447 ext = '.pyx' 

448 #@+others 

449 #@+node:ekr.20210904065459.11: *3* TestCython.test_importer 

450 def test_importer(self): 

451 

452 s = ''' 

453 from libc.math cimport pow 

454 

455 cdef double square_and_add (double x): 

456 """Compute x^2 + x as double. 

457 

458 This is a cdef function that can be called from within 

459 a Cython program, but not from Python. 

460 """ 

461 return pow(x, 2.0) + x 

462 

463 cpdef print_result (double x): 

464 """This is a cpdef function that can be called from Python.""" 

465 print("({} ^ 2) + {} = {}".format(x, x, square_and_add(x))) 

466 

467 ''' 

468 p = self.run_test(s) 

469 self.check_headlines(p, ( 

470 (1, 'Organizer: Declarations'), 

471 (1, 'double'), 

472 (1, 'print_result'), 

473 )) 

474 #@-others 

475#@+node:ekr.20211108064115.1: ** class TestDart (BaseTestImporter) 

476class TestDart(BaseTestImporter): 

477 

478 ext = '.dart' 

479 

480 #@+others 

481 #@+node:ekr.20210904065459.17: *3* TestDart.test_hello_world 

482 def test_hello_world(self): 

483 

484 s = r''' 

485 var name = 'Bob'; 

486 

487 hello() { 

488 print('Hello, World!'); 

489 } 

490 

491 // Define a function. 

492 printNumber(num aNumber) { 

493 print('The number is $aNumber.'); // Print to console. 

494 } 

495 

496 // This is where the app starts executing. 

497 void main() { 

498 var number = 42; // Declare and initialize a variable. 

499 printNumber(number); // Call a function. 

500 } 

501 ''' 

502 p = self.run_test(s) 

503 self.check_headlines(p, ( 

504 (1, 'hello'), 

505 (1, 'printNumber'), 

506 (1, 'void main'), 

507 )) 

508 #@+node:ekr.20210904065459.127: *3* TestDart.test_clean_headline 

509 def test_clean_headline(self): 

510 c = self.c 

511 x = dart.Dart_Importer(c.importCommands, atAuto=False) 

512 table = ( 

513 ('func(abc) {', 'func'), 

514 ('void foo() {', 'void foo'), 

515 ) 

516 for s, expected in table: 

517 got = x.clean_headline(s) 

518 self.assertEqual(got, expected) 

519 #@-others 

520#@+node:ekr.20211108065659.1: ** class TestElisp (BaseTestImporter) 

521class TestElisp(BaseTestImporter): 

522 

523 ext = '.el' 

524 

525 #@+others 

526 #@+node:ekr.20210904065459.18: *3* TestElisp.test_1 

527 def test_1(self): 

528 

529 s = """ 

530 ;;; comment 

531 ;;; continue 

532 ;;; 

533 

534 (defun abc (a b) 

535 (+ 1 2 3)) 

536 

537 ; comm 

538 (defun cde (a b) 

539 (+ 1 2 3)) 

540 """ 

541 p = self.run_test(s) 

542 self.check_headlines(p, ( 

543 (1, 'defun abc'), 

544 (1, 'defun cde'), 

545 )) 

546 

547 #@-others 

548#@+node:ekr.20211108064432.1: ** class TestHtml (BaseTestImporter) 

549class TestHtml(BaseTestImporter): 

550 

551 ext = '.htm' 

552 

553 def setUp(self): 

554 super().setUp() 

555 c = self.c 

556 # Simulate @data import-html-tags, with *only* standard tags. 

557 tags_list = ['html', 'body', 'head', 'div', 'table'] 

558 settingsDict, junk = g.app.loadManager.createDefaultSettingsDicts() 

559 c.config.settingsDict = settingsDict 

560 c.config.set(c.p, 'data', 'import-html-tags', tags_list, warn=True) 

561 

562 #@+others 

563 #@+node:ekr.20210904065459.19: *3* TestHtml.test_lowercase_tags 

564 def test_lowercase_tags(self): 

565 

566 s = """ 

567 <html> 

568 <head> 

569 <title>Bodystring</title> 

570 </head> 

571 <body class="bodystring"> 

572 <div id='bodydisplay'></div> 

573 </body> 

574 </html> 

575 """ 

576 p = self.run_test(s) 

577 self.check_headlines(p, ( 

578 (1, '<html>'), 

579 (2, '<head>'), 

580 (2, '<body class="bodystring">'), 

581 )) 

582 

583 #@+node:ekr.20210904065459.20: *3* TestHtml.test_multiple_tags_on_a_line 

584 def test_multiple_tags_on_a_line(self): 

585 

586 # tags that cause nodes: html, head, body, div, table, nodeA, nodeB 

587 # NOT: tr, td, tbody, etc. 

588 s = """ 

589 <html> 

590 <body> 

591 <table id="0"> 

592 <tr valign="top"> 

593 <td width="619"> 

594 <table id="2"> <tr valign="top"> <td width="377"> 

595 <table id="3"> 

596 <tr> 

597 <td width="368"> 

598 <table id="4"> 

599 <tbody id="5"> 

600 <tr valign="top"> 

601 <td width="550"> 

602 <table id="6"> 

603 <tbody id="6"> 

604 <tr> 

605 <td class="blutopgrabot"><a href="href1">Listing Standards</a> | <a href="href2">Fees</a> | <strong>Non-compliant Issuers</strong> | <a href="href3">Form 25 Filings</a> </td> 

606 </tr> 

607 </tbody> 

608 </table> 

609 </td> 

610 </tr><tr> 

611 <td width="100%" colspan="2"> 

612 <br /> 

613 </td> 

614 </tr> 

615 </tbody> 

616 </table> 

617 </td> 

618 </tr> 

619 </table> 

620 <!-- View First part --> </td> <td width="242"> <!-- View Second part --> 

621 <!-- View Second part --> </td> </tr></table> 

622 <DIV class="webonly"> 

623 <script src="/scripts/footer.js"></script> 

624 </DIV> 

625 </td> 

626 </tr> 

627 <script language="JavaScript1.1">var SA_ID="nyse;nyse";</script> 

628 <script language="JavaScript1.1" src="/scripts/stats/track.js"></script> 

629 <noscript><img src="/scripts/stats/track.js" height="1" width="1" alt="" border="0"></noscript> 

630 </body> 

631 </html> 

632 """ 

633 p = self.run_test(s) 

634 self.check_headlines(p, ( 

635 (1, '<html>'), 

636 (2, '<body>'), 

637 (3, '<table id="0">'), 

638 (4, '<table id="2">'), 

639 (5, '<table id="3">'), 

640 (6, '<table id="4">'), 

641 (7, '<table id="6">'), 

642 (4, '<DIV class="webonly">'), 

643 )) 

644 

645 #@+node:ekr.20210904065459.21: *3* TestHtml.test_multple_node_completed_on_a_line 

646 def test_multple_node_completed_on_a_line(self): 

647 

648 s = """ 

649 <!-- tags that start nodes: html,body,head,div,table,nodeA,nodeB --> 

650 <html><head>headline</head><body>body</body></html> 

651 """ 

652 p = self.run_test(s) 

653 self.check_headlines(p, ( 

654 # The new xml scanner doesn't generate any new nodes, 

655 # because the scan state hasn't changed at the end of the line! 

656 )) 

657 #@+node:ekr.20210904065459.22: *3* TestHtml.test_multple_node_starts_on_a_line 

658 def test_multple_node_starts_on_a_line(self): 

659 

660 s = ''' 

661 <html> 

662 <head>headline</head> 

663 <body>body</body> 

664 </html> 

665 ''' 

666 p = self.run_test(s) 

667 self.check_headlines(p, ( 

668 (1, '<html>'), 

669 # (2, '<head>'), 

670 # (2, '<body>'), 

671 )) 

672 #@+node:ekr.20210904065459.23: *3* TestHtml.test_underindented_comment 

673 def test_underindented_comment(self): 

674 

675 s = r''' 

676 <td width="550"> 

677 <table cellspacing="0" cellpadding="0" width="600" border="0"> 

678 <td class="blutopgrabot" height="28"></td> 

679 

680 <!-- The indentation of this element causes the problem. --> 

681 <table> 

682 

683 <!-- 

684 <div align="center"> 

685 <iframe src="http://www.amex.com/atamex/regulation/listingStatus/index.jsp"</iframe> 

686 </div> 

687 --> 

688 

689 </table> 

690 </table> 

691 

692 <p>Paragraph</p> 

693 </td> 

694 ''' 

695 p = self.run_test(s) 

696 self.check_headlines(p, ( 

697 (1, '<table cellspacing="0" cellpadding="0" width="600" border="0">'), 

698 (2, '<table>'), 

699 )) 

700 #@+node:ekr.20210904065459.24: *3* TestHtml.test_uppercase_tags 

701 def test_uppercase_tags(self): 

702 

703 s = """ 

704 <HTML> 

705 <HEAD> 

706 <title>Bodystring</title> 

707 </HEAD> 

708 <BODY class='bodystring'> 

709 <DIV id='bodydisplay'></DIV> 

710 </BODY> 

711 </HTML> 

712 """ 

713 p = self.run_test(s) 

714 self.check_headlines(p, ( 

715 (1, '<HTML>'), 

716 (2, '<HEAD>'), 

717 (2, "<BODY class='bodystring'>"), 

718 # (3, "<DIV id='bodydisplay'></DIV>"), 

719 )) 

720 #@+node:ekr.20210904065459.25: *3* TestHtml.test_improperly_nested_tags 

721 def test_improperly_nested_tags(self): 

722 

723 s = """ 

724 <body> 

725 

726 <!-- OOPS: the div and p elements not properly nested.--> 

727 <!-- OOPS: this table got generated twice. --> 

728 

729 <p id="P1"> 

730 <div id="D666">Paragraph</p> <!-- P1 --> 

731 <p id="P2"> 

732 

733 <TABLE id="T666"></TABLE></p> <!-- P2 --> 

734 </div> 

735 </p> <!-- orphan --> 

736 

737 </body> 

738 """ 

739 p = self.run_test(s) 

740 self.check_headlines(p, ( 

741 (1, '<body>'), 

742 (2, '<div id="D666">'), 

743 )) 

744 

745 #@+node:ekr.20210904065459.26: *3* TestHtml.test_improperly_terminated_tags 

746 def test_improperly_terminated_tags(self): 

747 

748 s = ''' 

749 <html> 

750 

751 <head> 

752 <!-- oops: link elements terminated two different ways --> 

753 <link id="L1"> 

754 <link id="L2"> 

755 <link id="L3" /> 

756 <link id='L4' /> 

757 

758 <title>TITLE</title> 

759 

760 <!-- oops: missing tags. --> 

761 ''' 

762 p = self.run_test(s) 

763 self.check_headlines(p, ( 

764 (1, '<html>'), 

765 (2, '<head>'), 

766 )) 

767 

768 #@+node:ekr.20210904065459.27: *3* TestHtml.test_improperly_terminated_tags2 

769 def test_improperly_terminated_tags2(self): 

770 

771 s = ''' 

772 <html> 

773 <head> 

774 <!-- oops: link elements terminated two different ways --> 

775 <link id="L1"> 

776 <link id="L2"> 

777 <link id="L3" /> 

778 <link id='L4' /> 

779 

780 <title>TITLE</title> 

781 

782 </head> 

783 </html> 

784 ''' 

785 p = self.run_test(s) 

786 self.check_headlines(p, ( 

787 (1, '<html>'), 

788 (2, '<head>'), 

789 )) 

790 

791 #@+node:ekr.20210904065459.28: *3* TestHtml.test_brython 

792 def test_brython(self): 

793 

794 # https://github.com/leo-editor/leo-editor/issues/479 

795 s = ''' 

796 <!DOCTYPE html> 

797 <html> 

798 <head> 

799 <script type="text/python3"> 

800 """Code for the header menu""" 

801 from browser import document as doc 

802 from browser import html 

803 import header 

804 

805 qs_lang,language = header.show() 

806 

807 doc["content"].html = doc["content_%s" %language].html 

808 

809 if qs_lang: 

810 doc["c_%s" %qs_lang].href += "?lang=%s" %qs_lang 

811 

812 def ch_lang(ev): 

813 sel = ev.target 

814 new_lang = sel.options[sel.selectedIndex].value 

815 doc.location.href = 'index.html?lang=%s' %new_lang 

816 

817 for elt in doc[html.SELECT]: 

818 if elt.id.startswith('change_lang_'): 

819 doc[elt.id].bind('change',ch_lang) 

820 </script> 

821 

822 <script type="text/python3"> 

823 """Code for the clock""" 

824 

825 import time 

826 import math 

827 import datetime 

828 

829 from browser import document as doc 

830 import browser.timer 

831 

832 sin,cos = math.sin,math.cos 

833 width,height = 250,250 # canvas dimensions 

834 ray = 100 # clock ray 

835 

836 def needle(angle,r1,r2,color="#000000"): 

837 # draw a needle at specified angle in specified color 

838 # r1 and r2 are percentages of clock ray 

839 x1 = width/2-ray*cos(angle)*r1 

840 y1 = height/2-ray*sin(angle)*r1 

841 x2 = width/2+ray*cos(angle)*r2 

842 y2 = height/2+ray*sin(angle)*r2 

843 ctx.beginPath() 

844 ctx.strokeStyle = color 

845 ctx.moveTo(x1,y1) 

846 ctx.lineTo(x2,y2) 

847 ctx.stroke() 

848 

849 def set_clock(): 

850 # erase clock 

851 ctx.beginPath() 

852 ctx.fillStyle = "#FFF" 

853 ctx.arc(width/2,height/2,ray*0.89,0,2*math.pi) 

854 ctx.fill() 

855 

856 # redraw hours 

857 show_hours() 

858 

859 # print day 

860 now = datetime.datetime.now() 

861 day = now.day 

862 ctx.font = "bold 14px Arial" 

863 ctx.textAlign = "center" 

864 ctx.textBaseline = "middle" 

865 ctx.fillStyle="#FFF" 

866 ctx.fillText(day,width*0.7,height*0.5) 

867 

868 # draw needles for hour, minute, seconds 

869 ctx.lineWidth = 3 

870 hour = now.hour%12 + now.minute/60 

871 angle = hour*2*math.pi/12 - math.pi/2 

872 needle(angle,0.05,0.5) 

873 minute = now.minute 

874 angle = minute*2*math.pi/60 - math.pi/2 

875 needle(angle,0.05,0.85) 

876 ctx.lineWidth = 1 

877 second = now.second+now.microsecond/1000000 

878 angle = second*2*math.pi/60 - math.pi/2 

879 needle(angle,0.05,0.85,"#FF0000") # in red 

880 

881 def show_hours(): 

882 ctx.beginPath() 

883 ctx.arc(width/2,height/2,ray*0.05,0,2*math.pi) 

884 ctx.fillStyle = "#000" 

885 ctx.fill() 

886 for i in range(1,13): 

887 angle = i*math.pi/6-math.pi/2 

888 x3 = width/2+ray*cos(angle)*0.75 

889 y3 = height/2+ray*sin(angle)*0.75 

890 ctx.font = "20px Arial" 

891 ctx.textAlign = "center" 

892 ctx.textBaseline = "middle" 

893 ctx.fillText(i,x3,y3) 

894 # cell for day 

895 ctx.fillStyle = "#000" 

896 ctx.fillRect(width*0.65,height*0.47,width*0.1,height*0.06) 

897 

898 canvas = doc["clock"] 

899 # draw clock border 

900 if hasattr(canvas,'getContext'): 

901 ctx = canvas.getContext("2d") 

902 ctx.beginPath() 

903 ctx.lineWidth = 10 

904 ctx.arc(width/2,height/2,ray,0,2*math.pi) 

905 ctx.stroke() 

906 

907 for i in range(60): 

908 ctx.lineWidth = 1 

909 if i%5 == 0: 

910 ctx.lineWidth = 3 

911 angle = i*2*math.pi/60 - math.pi/3 

912 x1 = width/2+ray*cos(angle) 

913 y1 = height/2+ray*sin(angle) 

914 x2 = width/2+ray*cos(angle)*0.9 

915 y2 = height/2+ray*sin(angle)*0.9 

916 ctx.beginPath() 

917 ctx.moveTo(x1,y1) 

918 ctx.lineTo(x2,y2) 

919 ctx.stroke() 

920 browser.timer.set_interval(set_clock,100) 

921 show_hours() 

922 else: 

923 doc['navig_zone'].html = "On Internet Explorer 9 or more, use a Standard rendering engine" 

924 </script> 

925 

926 <title>Brython</title> 

927 <link rel="stylesheet" href="Brython_files/doc_brython.css"> 

928 </head> 

929 <body onload="brython({debug:1, cache:'none'})"> 

930 </body></html> 

931 ''' 

932 p = self.run_test(s) 

933 self.check_headlines(p, ( 

934 (1, '<html>'), 

935 (2, '<head>'), 

936 (2, '<body onload="brython({debug:1, cache:\'none\'})">'), 

937 )) 

938 #@-others 

939#@+node:ekr.20211108062617.1: ** class TestIni (BaseTestImporter) 

940class TestIni(BaseTestImporter): 

941 

942 ext = '.ini' 

943 

944 #@+others 

945 #@+node:ekr.20210904065459.29: *3* TestIni.test_1 

946 def test_1(self): 

947 

948 s = ''' 

949 ; last modified 1 April 2001 by John Doe 

950 [owner] 

951 name=John Doe 

952 organization=Acme Widgets Inc. 

953 

954 ; [ not a section ] 

955 

956 [database] 

957 server=192.0.2.62 

958 ; use IP address 

959 port=143 

960 file = "payroll.dat" 

961 ''' 

962 p = self.run_test(s) 

963 self.check_headlines(p, ( 

964 (1, '[owner]'), 

965 (1, '[database]'), 

966 )) 

967 #@-others 

968#@+node:ekr.20211108065916.1: ** class TestJava (BaseTestImporter) 

969class TestJava(BaseTestImporter): 

970 

971 ext = '.java' 

972 

973 #@+others 

974 #@+node:ekr.20210904065459.30: *3* TestJava.test_from_AdminPermission_java 

975 def test_from_AdminPermission_java(self): 

976 

977 s = """ 

978 /** 

979 * Indicates the caller's authority to perform lifecycle operations on 

980 */ 

981 

982 public final class AdminPermission extends BasicPermission 

983 { 

984 /** 

985 * Creates a new <tt>AdminPermission</tt> object. 

986 */ 

987 public AdminPermission() 

988 { 

989 super("AdminPermission"); 

990 } 

991 } 

992 """ 

993 p = self.run_test(s) 

994 self.check_headlines(p, ( 

995 (1, 'public final class AdminPermission extends BasicPermission'), 

996 (2, 'public AdminPermission'), 

997 )) 

998 #@+node:ekr.20210904065459.31: *3* TestJava.test_from_BundleException_java 

999 def test_from_BundleException_java(self): 

1000 

1001 s = """ 

1002 /* 

1003 * $Header: /cvs/leo/test/unitTest.leo,v 1.247 2008/02/14 14:59:04 edream Exp $ 

1004 * 

1005 * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved. 

1006 * 

1007 * This program and the accompanying materials are made available under the 

1008 * terms of the Eclipse Public License v1.0 which accompanies this 

1009 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html. 

1010 */ 

1011 

1012 package org.osgi.framework; 

1013 

1014 /** 

1015 * A Framework exception used to indicate that a bundle lifecycle problem 

1016 * occurred. 

1017 * 

1018 * <p> 

1019 * <code>BundleException</code> object is created by the Framework to denote 

1020 * an exception condition in the lifecycle of a bundle. 

1021 * <code>BundleException</code>s should not be created by bundle developers. 

1022 * 

1023 * <p> 

1024 * This exception is updated to conform to the general purpose exception 

1025 * chaining mechanism. 

1026 * 

1027 * @version $Revision: 1.247 $ 

1028 */ 

1029 

1030 public class BundleException extends Exception { 

1031 static final long serialVersionUID = 3571095144220455665L; 

1032 /** 

1033 * Nested exception. 

1034 */ 

1035 private Throwable cause; 

1036 

1037 /** 

1038 * Creates a <code>BundleException</code> that wraps another exception. 

1039 * 

1040 * @param msg The associated message. 

1041 * @param cause The cause of this exception. 

1042 */ 

1043 public BundleException(String msg, Throwable cause) { 

1044 super(msg); 

1045 this.cause = cause; 

1046 } 

1047 } 

1048 

1049 """ 

1050 p = self.run_test(s) 

1051 self.check_headlines(p, ( 

1052 (1, 'public class BundleException extends Exception'), 

1053 (2, 'public BundleException'), 

1054 )) 

1055 #@+node:ekr.20210904065459.32: *3* TestJava.test_interface_test1 

1056 def test_interface_test1(self): 

1057 

1058 s = """ 

1059 interface Bicycle { 

1060 void changeCadence(int newValue); 

1061 void changeGear(int newValue); 

1062 } 

1063 """ 

1064 p = self.run_test(s) 

1065 self.check_headlines(p, ( 

1066 (1, 'interface Bicycle'), 

1067 )) 

1068 #@+node:ekr.20210904065459.33: *3* TestJava.test_interface_test2 

1069 def test_interface_test2(self): 

1070 

1071 s = """ 

1072 interface Bicycle { 

1073 void changeCadence(int newValue); 

1074 void changeGear(int newValue); 

1075 } 

1076 """ 

1077 p = self.run_test(s) 

1078 self.check_headlines(p, ( 

1079 (1, 'interface Bicycle'), 

1080 )) 

1081 #@-others 

1082#@+node:ekr.20211108070310.1: ** class TestJavascript (BaseTestImporter) 

1083class TestJavascript(BaseTestImporter): 

1084 

1085 ext = '.js' 

1086 

1087 #@+others 

1088 #@+node:ekr.20210904065459.34: *3* TestJavascript.test_regex_1 

1089 def test_regex_1(self): 

1090 

1091 s = """ 

1092 String.prototype.toJSONString = function() 

1093 { 

1094 if(/["\\\\\\x00-\\x1f]/.test(this)) 

1095 return '"' + this.replace(/([\\x00-\\x1f\\"])/g,replaceFn) + '"'; 

1096 

1097 return '"' + this + '"'; 

1098 }; 

1099 """ 

1100 self.run_test(s) 

1101 #@+node:ekr.20210904065459.35: *3* TestJavascript.test_3 

1102 def test_3(self): 

1103 

1104 s = """ 

1105 // Restarting 

1106 function restart() 

1107 { 

1108 invokeParamifier(params,"onstart"); 

1109 if(story.isEmpty()) { 

1110 var tiddlers = store.filterTiddlers(store.getTiddlerText("DefaultTiddlers")); 

1111 for(var t=0; t<tiddlers.length; t++) { 

1112 story.displayTiddler("bottom",tiddlers[t].title); 

1113 } 

1114 } 

1115 window.scrollTo(0,0); 

1116 } 

1117 """ 

1118 self.run_test(s) 

1119 #@+node:ekr.20210904065459.36: *3* TestJavascript.test_4 

1120 def test_4(self): 

1121 

1122 s = """ 

1123 var c3 = (function () { 

1124 "use strict"; 

1125 

1126 // Globals 

1127 var c3 = { version: "0.0.1" }; 

1128 

1129 c3.someFunction = function () { 

1130 console.log("Just a demo..."); 

1131 }; 

1132 

1133 return c3; 

1134 }()); 

1135 """ 

1136 self.run_test(s) 

1137 #@+node:ekr.20210904065459.37: *3* TestJavascript.test_5 

1138 def test_5(self): 

1139 

1140 s = """ 

1141 var express = require('express'); 

1142 

1143 var app = express.createServer(express.logger()); 

1144 

1145 app.get('/', function(request, response) { 

1146 response.send('Hello World!'); 

1147 }); 

1148 

1149 var port = process.env.PORT || 5000; 

1150 app.listen(port, function() { 

1151 console.log("Listening on " + port); 

1152 }); 

1153 """ 

1154 self.run_test(s) 

1155 #@+node:ekr.20210904065459.38: *3* TestJavascript.test_639_many_top_level_nodes 

1156 def test_639_many_top_level_nodes(self): 

1157 

1158 s = """ 

1159 // Easy test for #639: https://github.com/leo-editor/leo-editor/issues/639 

1160 

1161 //============================================================================= 

1162 // rpg_core.js v1.3.0 

1163 //============================================================================= 

1164 

1165 //----------------------------------------------------------------------------- 

1166 /** 

1167 * This is not a class, but contains some methods that will be added to the 

1168 * standard Javascript objects. 

1169 * 

1170 * @class JsExtensions 

1171 */ 

1172 function JsExtensions() { 

1173 throw new Error('This is not a class'); 

1174 } 

1175 

1176 /** 

1177 * Returns a number whose value is limited to the given range. 

1178 * 

1179 * @method Number.prototype.clamp 

1180 * @param {Number} min The lower boundary 

1181 * @param {Number} max The upper boundary 

1182 * @return {Number} A number in the range (min, max) 

1183 */ 

1184 Number.prototype.clamp = function(min, max) { 

1185 return Math.min(Math.max(this, min), max); 

1186 }; 

1187 """ 

1188 self.run_test(s) 

1189 #@+node:ekr.20210904065459.39: *3* TestJavascript.test_639_acid_test_1 

1190 def test_639_acid_test_1(self): 

1191 

1192 s = """ 

1193 // Acid test for #639: https://github.com/leo-editor/leo-editor/issues/639 

1194 require([ 

1195 'jquery', 

1196 ], function( 

1197 $, 

1198 termjs, 

1199 ){ 

1200 var header = $("#header")[0]; 

1201 function calculate_size() { 

1202 var height = $(window).height() - header.offsetHeight; 

1203 } 

1204 page.show_header(); 

1205 window.onresize = function() { 

1206 terminal.socket.send(JSON.stringify([ 

1207 "set_size", geom.rows, geom.cols, 

1208 $(window).height(), $(window).width()]) 

1209 ); 

1210 }; 

1211 window.terminal = terminal; 

1212 }); 

1213 """ 

1214 self.run_test(s) 

1215 #@+node:ekr.20210904065459.40: *3* TestJavascript.test_639_acid_test_2 

1216 def test_639_acid_test_2(self): 

1217 

1218 s = """ 

1219 // Acid test for #639: https://github.com/leo-editor/leo-editor/issues/639 

1220 require([ 

1221 'jquery', 

1222 ], function( 

1223 $, 

1224 termjs, 

1225 ){ 

1226 var head = "head" 

1227 function f1() { 

1228 var head1 = "head1" 

1229 function f11 () { 

1230 var v11 ="v1.1" 

1231 } 

1232 var middle1 = "middle1" 

1233 function f12 () { 

1234 var v12 ="v1.2" 

1235 } 

1236 var tail1 = "tail1" 

1237 } 

1238 var middle = "middle" 

1239 function f2() { 

1240 var head2 = "head2" 

1241 function f21 () { 

1242 var v21 ="2.1" 

1243 } 

1244 var middle2 = "middle2" 

1245 function f22 () { 

1246 var v22 = "2.2.1" 

1247 } 

1248 var tail2 = "tail2" 

1249 } 

1250 var tail = "tail" 

1251 }); 

1252 """ 

1253 self.run_test(s) 

1254 #@-others 

1255#@+node:ekr.20211108043230.1: ** class TestMarkdown (BaseTestImporter) 

1256class TestMarkdown(BaseTestImporter): 

1257 

1258 ext = '.md' 

1259 treeType = '@auto-md' 

1260 

1261 #@+others 

1262 #@+node:ekr.20210904065459.109: *3* TestMarkdown.test_md_import 

1263 def test_md_import(self): 

1264 

1265 s = """\ 

1266 #Top 

1267 The top section 

1268 

1269 ##Section 1 

1270 section 1, line 1 

1271 section 1, line 2 

1272 

1273 ##Section 2 

1274 section 2, line 1 

1275 

1276 ###Section 2.1 

1277 section 2.1, line 1 

1278 

1279 ####Section 2.1.1 

1280 section 2.2.1 line 1 

1281 The next section is empty. It must not be deleted. 

1282 

1283 ###Section 2.2 

1284 

1285 ##Section 3 

1286 Section 3, line 1 

1287 """ 

1288 p = self.run_test(s) 

1289 self.check_headlines(p, ( 

1290 (1, 'Top'), 

1291 (2, 'Section 1'), 

1292 (2, 'Section 2'), 

1293 (3, 'Section 2.1'), 

1294 (4, 'Section 2.1.1'), 

1295 (3, 'Section 2.2'), 

1296 (2, 'Section 3'), 

1297 )) 

1298 #@+node:ekr.20210904065459.110: *3* TestMarkdown.test_md_import_rst_style 

1299 def test_md_import_rst_style(self): 

1300 

1301 s = """\ 

1302 Top 

1303 ==== 

1304 

1305 The top section 

1306 

1307 Section 1 

1308 --------- 

1309 

1310 section 1, line 1 

1311 -- Not an underline 

1312 secttion 1, line 2 

1313 

1314 Section 2 

1315 --------- 

1316 

1317 section 2, line 1 

1318 

1319 ###Section 2.1 

1320 

1321 section 2.1, line 1 

1322 

1323 ####Section 2.1.1 

1324 

1325 section 2.2.1 line 1 

1326 

1327 ###Section 2.2 

1328 section 2.2, line 1. 

1329 

1330 Section 3 

1331 --------- 

1332 

1333 section 3, line 1 

1334 """ 

1335 p = self.run_test(s) 

1336 self.check_headlines(p, ( 

1337 (1, 'Top'), 

1338 (2, 'Section 1'), 

1339 (2, 'Section 2'), 

1340 (3, 'Section 2.1'), 

1341 (4, 'Section 2.1.1'), 

1342 (3, 'Section 2.2'), 

1343 (2, 'Section 3'), 

1344 )) 

1345 #@+node:ekr.20210904065459.111: *3* TestMarkdown.test_markdown_importer_basic 

1346 def test_markdown_importer_basic(self): 

1347 

1348 # insert test for markdown here. 

1349 s = """ 

1350 Decl line. 

1351 #Header 

1352 

1353 After header text 

1354 

1355 ##Subheader 

1356 

1357 Not an underline 

1358 

1359 ---------------- 

1360 

1361 After subheader text 

1362 

1363 #Last header: no text 

1364 """ 

1365 p = self.run_test(s) 

1366 self.check_headlines(p, ( 

1367 (1, '!Declarations'), 

1368 (1, 'Header'), 

1369 (2, 'Subheader'), 

1370 (1, 'Last header: no text'), 

1371 )) 

1372 #@+node:ekr.20210904065459.112: *3* TestMarkdown.test_markdown_importer_implicit_section 

1373 def test_markdown_importer_implicit_section(self): 

1374 

1375 s = """ 

1376 Decl line. 

1377 #Header 

1378 

1379 After header text 

1380 

1381 ##Subheader 

1382 

1383 Not an underline 

1384 

1385 ---------------- 

1386 

1387 This *should* be a section 

1388 ========================== 

1389 

1390 After subheader text 

1391 

1392 #Last header: no text 

1393 """ 

1394 # Implicit underlining *must* cause the perfect-import test to fail! 

1395 g.app.suppressImportChecks = True 

1396 p = self.run_test(s) 

1397 self.check_headlines(p, ( 

1398 (1, '!Declarations'), 

1399 (1, 'Header'), 

1400 (2, 'Subheader'), 

1401 (1, 'This *should* be a section'), 

1402 (1, 'Last header: no text'), 

1403 )) 

1404 #@+node:ekr.20210904065459.114: *3* TestMarkdown.test_markdown_github_syntax 

1405 def test_markdown_github_syntax(self): 

1406 

1407 s = """ 

1408 Decl line. 

1409 #Header 

1410 

1411 ```python 

1412 loads.init = { 

1413 Chloride: 11.5, 

1414 TotalP: 0.002, 

1415 } 

1416 ``` 

1417 #Last header 

1418 """ 

1419 p = self.run_test(s) 

1420 self.check_headlines(p, ( 

1421 (1, '!Declarations'), 

1422 (1, 'Header'), 

1423 (1, 'Last header'), 

1424 )) 

1425 #@+node:ekr.20210904065459.128: *3* TestMarkdown.test_is_hash 

1426 def test_is_hash(self): 

1427 c = self.c 

1428 ic = c.importCommands 

1429 x = markdown.Markdown_Importer(ic, atAuto=False) 

1430 assert x.md_pattern_table 

1431 table = ( 

1432 (1, 'name', '# name\n'), 

1433 (2, 'a test', '## a test\n'), 

1434 (3, 'a test', '### a test\n'), 

1435 ) 

1436 for data in table: 

1437 level, name, line = data 

1438 level2, name2 = x.is_hash(line) 

1439 self.assertEqual(level, level2) 

1440 self.assertEqual(name, name2) 

1441 level3, name = x.is_hash('Not a hash') 

1442 assert level3 is None 

1443 assert name is None 

1444 #@+node:ekr.20210904065459.129: *3* TestMarkdown.test_is_underline 

1445 def test_is_underline(self): 

1446 c = self.c 

1447 ic = c.importCommands 

1448 x = markdown.Markdown_Importer(ic, atAuto=False) 

1449 for line in ('----\n', '-----\n', '====\n', '====\n'): 

1450 got = x.is_underline(line) 

1451 assert got, repr(line) 

1452 for line in ('-\n', '--\n', '---\n', '==\n', '===\n', '===\n', '==-==\n', 'abc\n'): 

1453 got = x.is_underline(line) 

1454 assert not got, repr(line) 

1455 #@-others 

1456#@+node:ekr.20211108080955.1: ** class TestOrg (BaseTestImporter) 

1457class TestOrg(BaseTestImporter): 

1458 

1459 ext = '.org' 

1460 treeType = '@auto-org' 

1461 

1462 #@+others 

1463 #@+node:ekr.20210904065459.42: *3* TestOrg.test_1 

1464 def test_1(self): 

1465 

1466 s = """ 

1467 * Section 1 

1468 Sec 1. 

1469 * Section 2 

1470 Sec 2. 

1471 ** Section 2-1 

1472 Sec 2.1 

1473 *** Section 2-1-1 

1474 Sec 2.1.1 

1475 * Section 3 

1476 ** Section 3.1 

1477 Sec 3.1 

1478 """ 

1479 p = self.run_test(s) 

1480 self.check_headlines(p, ( 

1481 (1, 'Section 1'), 

1482 (1, 'Section 2'), 

1483 (2, 'Section 2-1'), 

1484 (3, 'Section 2-1-1'), 

1485 (1, 'Section 3'), 

1486 (2, 'Section 3.1'), 

1487 )) 

1488 

1489 #@+node:ekr.20210904065459.46: *3* TestOrg.test_1074 

1490 def test_1074(self): 

1491 

1492 s = """ 

1493 * Test 

1494 First line. 

1495 """ 

1496 p = self.run_test(s) 

1497 self.check_headlines(p, ( 

1498 (1, ' Test'), 

1499 )) 

1500 #@+node:ekr.20210904065459.45: *3* TestOrg.test_552 

1501 def test_552(self): 

1502 

1503 s = """ 

1504 * Events 

1505 :PROPERTIES: 

1506 :CATEGORY: events 

1507 :END: 

1508 ** 整理个人生活 

1509 *** 每周惯例 

1510 """ 

1511 p = self.run_test(s) 

1512 self.check_headlines(p, ( 

1513 (1, 'Events'), 

1514 (2, '整理个人生活'), 

1515 (3, '每周惯例'), 

1516 )) 

1517 #@+node:ekr.20210904065459.44: *3* TestOrg.test_intro 

1518 def test_intro(self): 

1519 

1520 s = """ 

1521 Intro line. 

1522 * Section 1 

1523 Sec 1. 

1524 * Section 2 

1525 Sec 2. 

1526 """ 

1527 p = self.run_test(s) 

1528 self.check_headlines(p, ( 

1529 (1, 'Section 1'), 

1530 (1, 'Section 2'), 

1531 )) 

1532 #@+node:ekr.20210904065459.41: *3* TestOrg.test_pattern 

1533 def test_pattern(self): 

1534 

1535 c = self.c 

1536 x = org.Org_Importer(c.importCommands, atAuto=False) 

1537 pattern = x.org_pattern 

1538 table = ( 

1539 # 'body * line', 

1540 '* line 1', 

1541 '** level 2', 

1542 ) 

1543 for line in table: 

1544 m = pattern.match(line) 

1545 # print('%20s ==> (%r)(%r)' % (line, m and m.group(1), m and m.group(2))) 

1546 assert m, repr(line) 

1547 #@+node:ekr.20210904065459.47: *3* TestOrg.test_placeholder 

1548 def test_placeholder(self): 

1549 

1550 # insert test for org here. 

1551 s = """ 

1552 * Section 1 

1553 Sec 1. 

1554 * Section 2 

1555 Sec 2. 

1556 ** Section 2-1 

1557 Sec 2.1 

1558 *** Section 2-1-1 

1559 Sec 2.1.1 

1560 * Section 3 

1561 ****** Section 3-1-1-1-1-1 

1562 : Sec 3-1-1-1-1-1 

1563 ** Section 3.1 

1564 Sec 3.1 

1565 """ 

1566 # Suppress perfect import checks. 

1567 g.app.suppressImportChecks = True 

1568 p = self.run_test(s) 

1569 self.check_headlines(p, ( 

1570 (1, 'Section 1'), 

1571 (1, 'Section 2'), 

1572 (2, 'Section 2-1'), 

1573 (3, 'Section 2-1-1'), 

1574 (1, 'Section 3'), 

1575 (2, 'placeholder'), 

1576 (3, 'placeholder'), 

1577 (4, 'placeholder'), 

1578 (5, 'placeholder'), 

1579 (6, 'Section 3-1-1-1-1-1'), 

1580 (2, 'Section 3.1'), 

1581 )) 

1582 #@+node:ekr.20210904065459.43: *3* TestOrg.test_tags 

1583 def test_tags(self): 

1584 

1585 s = """ 

1586 * Section 1 :tag1: 

1587 * Section 2 :tag2: 

1588 * Section 3 :tag3:tag4: 

1589 """ 

1590 p = self.run_test(s) 

1591 self.check_headlines(p, ( 

1592 (1, 'Section 1 :tag1:'), 

1593 (1, 'Section 2 :tag2:'), 

1594 (1, 'Section 3 :tag3:tag4:'), 

1595 )) 

1596 #@-others 

1597#@+node:ekr.20211108081327.1: ** class TestOtl (BaseTestImporter) 

1598class TestOtl(BaseTestImporter): 

1599 

1600 ext = '.otl' 

1601 treeType = '@auto-otl' 

1602 

1603 #@+others 

1604 #@+node:ekr.20210904065459.49: *3* TestOtl.test_otl_1 

1605 def test_otl_1(self): 

1606 

1607 s = """\ 

1608 preamble. 

1609 Section 1 

1610 : Sec 1. 

1611 Section 2 

1612 : Sec 2. 

1613 \tSection 2-1 

1614 : Sec 2-1 

1615 \t\tSection 2-1-1 

1616 : Sect 2-1-1 

1617 Section 3 

1618 : Sec 3 

1619 \tSection 3.1 

1620 : Sec 3.1 

1621 """ 

1622 p = self.run_test(s) 

1623 self.check_headlines(p, ( 

1624 (1, 'preamble.'), 

1625 (1, 'Section 1'), 

1626 (1, 'Section 2'), 

1627 (1, 'Section 2-1'), 

1628 (1, 'Section 2-1-1'), 

1629 (1, 'Section 3'), 

1630 (1, 'Section 3.1'), 

1631 (1, ''), # Due to the added blank line? 

1632 )) 

1633 #@+node:ekr.20210904065459.48: *3* TestOtl.test_vim_outline_mode 

1634 def test_vim_outline_mode(self): 

1635 

1636 c = self.c 

1637 x = otl.Otl_Importer(c.importCommands, atAuto=False) 

1638 pattern = x.otl_pattern 

1639 table = ( 

1640 'body line', 

1641 '\tline 1', 

1642 ' \tlevel 2', 

1643 ) 

1644 for line in table: 

1645 m = pattern.match(line) 

1646 self.assertTrue(m, msg=repr(line)) 

1647 #@-others 

1648#@+node:ekr.20211108081719.1: ** class TestPascal (BaseTestImporter) 

1649class TestPascal(BaseTestImporter): 

1650 

1651 ext = '.pas' 

1652 

1653 #@+others 

1654 #@+node:ekr.20210904065459.50: *3* TestPascal.test_delphi_interface 

1655 def test_delphi_interface(self): 

1656 

1657 s = """ 

1658 unit Unit1; 

1659 

1660 interface 

1661 

1662 uses 

1663 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 

1664 Forms, 

1665 Dialogs; 

1666 

1667 type 

1668 TForm1 = class(TForm) 

1669 procedure FormCreate(Sender: TObject); 

1670 private 

1671 { Private declarations } 

1672 public 

1673 { Public declarations } 

1674 end; 

1675 

1676 var 

1677 Form1: TForm1; 

1678 

1679 implementation 

1680 

1681 {$R *.dfm} 

1682 

1683 procedure TForm1.FormCreate(Sender: TObject); 

1684 var 

1685 x,y: double; 

1686 begin 

1687 x:= 4; 

1688 Y := x/2; 

1689 end; 

1690 

1691 end. // interface 

1692 """ 

1693 p = self.run_test(s) 

1694 self.check_headlines(p, ( 

1695 (1, 'interface'), 

1696 (2, 'procedure FormCreate'), 

1697 (2, 'procedure TForm1.FormCreate'), 

1698 )) 

1699 #@+node:ekr.20210904065459.130: *3* TestPascal.test_methods 

1700 def test_methods(self): 

1701 

1702 c = self.c 

1703 x = pascal.Pascal_Importer(c.importCommands, atAuto=False) 

1704 table = ( 

1705 ('procedure TForm1.FormCreate(Sender: TObject);\n', 'procedure TForm1.FormCreate'), 

1706 ) 

1707 state = g.Bunch(context='') 

1708 for line, cleaned in table: 

1709 assert x.starts_block(0, [line], state, state) 

1710 self.assertEqual(x.clean_headline(line), cleaned) 

1711 #@-others 

1712#@+node:ekr.20211108081950.1: ** class TestPerl (BaseTestImporter) 

1713class TestPerl(BaseTestImporter): 

1714 

1715 ext = '.pl' 

1716 

1717 #@+others 

1718 #@+node:ekr.20210904065459.51: *3* TestPerl.test_1 

1719 def test_1(self): 

1720 

1721 s = """ 

1722 #!/usr/bin/perl 

1723 

1724 # Function definition 

1725 sub Hello{ 

1726 print "Hello, World!\n"; 

1727 } 

1728 

1729 sub Test{ 

1730 print "Test!\n"; 

1731 } 

1732 "\N{LATIN SMALL LIGATURE FI}" =~ /fi/i; 

1733 

1734 $bar = "foo"; 

1735 if ($bar =~ /foo/){ 

1736 print "Second time is matching\n"; 

1737 }else{ 

1738 print "Second time is not matching\n"; 

1739 } 

1740 

1741 # Function call 

1742 Hello(); 

1743 """ 

1744 self.run_test(s) 

1745 #@+node:ekr.20210904065459.53: *3* TestPerl.test_multi_line_string 

1746 def test_multi_line_string(self): 

1747 

1748 s = """ 

1749 #!/usr/bin/perl 

1750 

1751 # This would print with a line break in the middle 

1752 print "Hello 

1753 

1754 sub World { 

1755 print "This is not a funtion!" 

1756 } 

1757 

1758 world\n"; 

1759 """ 

1760 self.run_test(s) 

1761 #@+node:ekr.20210904065459.52: *3* TestPerl.test_perlpod_comment 

1762 def test_perlpod_comment(self): 

1763 

1764 s = """ 

1765 #!/usr/bin/perl 

1766 

1767 sub Test{ 

1768 print "Test!\n"; 

1769 } 

1770 

1771 =begin comment 

1772 sub World { 

1773 print "This is not a funtion!" 

1774 } 

1775 =cut 

1776 

1777 # Function definition 

1778 sub Hello{ 

1779 print "Hello, World!\n"; 

1780 } 

1781 """ 

1782 self.run_test(s) 

1783 #@+node:ekr.20210904065459.54: *3* TestPerl.test_regex_1 

1784 def test_regex_1(self): 

1785 

1786 # ('len', 'tr///', '/', context, 0, 0, 0), 

1787 # ('len', 's///', '/', context, 0, 0, 0), 

1788 # ('len', 'm//', '/', context, 0, 0, 0), 

1789 # ('len', '/', '/', '', 0, 0, 0), 

1790 s = """ 

1791 #!/usr/bin/perl 

1792 

1793 sub test1 { 

1794 s = /{/g; 

1795 } 

1796 

1797 sub test2 { 

1798 s = m//{/; 

1799 } 

1800 

1801 sub test3 { 

1802 s = s///{/; 

1803 } 

1804 

1805 sub test4 { 

1806 s = tr///{/; 

1807 } 

1808 """ 

1809 self.run_test(s) 

1810 

1811 #@+node:ekr.20210904065459.55: *3* TestPerl.test_regex_2 

1812 def test_regex_2(self): 

1813 

1814 s = """ 

1815 #!/usr/bin/perl 

1816 

1817 sub test1 { 

1818 s = /}/g; 

1819 } 

1820 

1821 sub test2 { 

1822 s = m//}/; 

1823 } 

1824 

1825 sub test3 { 

1826 s = s///}/; 

1827 } 

1828 

1829 sub test4 { 

1830 s = tr///}/; 

1831 } 

1832 """ 

1833 p = self.run_test(s) 

1834 self.check_headlines(p, ( 

1835 (1, 'sub test1'), 

1836 (1, 'sub test2'), 

1837 (1, 'sub test3'), 

1838 (1, 'sub test4'), 

1839 )) 

1840 #@-others 

1841#@+node:ekr.20211108082208.1: ** class TestPhp (BaseTestImporter) 

1842class TestPhp(BaseTestImporter): 

1843 

1844 ext = '.php' 

1845 

1846 #@+others 

1847 #@+node:ekr.20210904065459.56: *3* TestPhp.test_import_class 

1848 def test_import_class(self): 

1849 

1850 s = """ 

1851 <?php 

1852 

1853 $type = 'cc'; 

1854 $obj = new $type; // outputs "hi!" 

1855 

1856 class cc { 

1857 function __construct() { 

1858 echo 'hi!'; 

1859 } 

1860 } 

1861 

1862 ?> 

1863 """ 

1864 self.run_test(s) 

1865 #@+node:ekr.20210904065459.57: *3* TestPhp.test_import_conditional_class 

1866 def test_import_conditional_class(self): 

1867 

1868 s = """ 

1869 <?php 

1870 

1871 if (expr) { 

1872 class cc { 

1873 // version 1 

1874 } 

1875 } else { 

1876 class cc { 

1877 // version 2 

1878 } 

1879 } 

1880 

1881 ?> 

1882 """ 

1883 self.run_test(s) 

1884 #@+node:ekr.20210904065459.58: *3* TestPhp.test_import_classes__functions 

1885 def test_import_classes__functions(self): 

1886 

1887 s = """ 

1888 <?php 

1889 class Enum { 

1890 protected $self = array(); 

1891 public function __construct( /*...*/ ) { 

1892 $args = func_get_args(); 

1893 for( $i=0, $n=count($args); $i<$n; $i++ ) 

1894 $this->add($args[$i]); 

1895 } 

1896 

1897 public function __get( /*string*/ $name = null ) { 

1898 return $this->self[$name]; 

1899 } 

1900 

1901 public function add( /*string*/ $name = null, /*int*/ $enum = null ) { 

1902 if( isset($enum) ) 

1903 $this->self[$name] = $enum; 

1904 else 

1905 $this->self[$name] = end($this->self) + 1; 

1906 } 

1907 } 

1908 

1909 class DefinedEnum extends Enum { 

1910 public function __construct( /*array*/ $itms ) { 

1911 foreach( $itms as $name => $enum ) 

1912 $this->add($name, $enum); 

1913 } 

1914 } 

1915 

1916 class FlagsEnum extends Enum { 

1917 public function __construct( /*...*/ ) { 

1918 $args = func_get_args(); 

1919 for( $i=0, $n=count($args), $f=0x1; $i<$n; $i++, $f *= 0x2 ) 

1920 $this->add($args[$i], $f); 

1921 } 

1922 } 

1923 ?> 

1924 """ 

1925 self.run_test(s) 

1926 #@+node:ekr.20210904065459.59: *3* TestPhp.test_here_doc 

1927 def test_here_doc(self): 

1928 

1929 s = """ 

1930 <?php 

1931 class foo { 

1932 public $bar = <<<EOT 

1933 a test. 

1934 bar 

1935 EOT; 

1936 } 

1937 ?> 

1938 """ 

1939 self.run_test(s) 

1940 #@-others 

1941#@+node:ekr.20211108082509.1: ** class TestPython (BaseTestImporter) 

1942class TestPython(BaseTestImporter): 

1943 

1944 check_tree = False 

1945 ext = '.py' 

1946 treeType = '@file' 

1947 

1948 def setUp(self): 

1949 super().setUp() 

1950 if sys.version_info < (3, 7, 0): 

1951 self.skipTest('The python importer requires python 3.7 or above') # pragma: no cover 

1952 

1953 #@+others 

1954 #@+node:ekr.20211126055349.1: *3* TestPython.test_short_file 

1955 def test_short_file(self): 

1956 

1957 input_s = ( 

1958 '"""A docstring"""\n' 

1959 'switch = 1\n' 

1960 'print(3)\n' 

1961 'print(6)\n' 

1962 'def a():\n' 

1963 ' pass\n' 

1964 'print(7)\n' 

1965 ) 

1966 exp_nodes = [(0, 'ignored h', 

1967 '@language python\n' 

1968 '@tabwidth -4\n' 

1969 '"""A docstring"""\n' 

1970 'switch = 1\n' 

1971 'print(3)\n' 

1972 'print(6)\n' 

1973 'def a():\n' 

1974 ' pass\n' 

1975 'print(7)\n\n' 

1976 )] 

1977 p = self.run_test(input_s) 

1978 ok, msg = self.check_outline(p, exp_nodes) 

1979 assert ok, msg 

1980 #@+node:ekr.20210904065459.63: *3* TestPython.test_short_classes 

1981 def test_short_classes(self): 

1982 s = ( 

1983 'import sys\n' 

1984 'def f1():\n' 

1985 ' pass\n' 

1986 '\n' 

1987 'class Class1:\n' 

1988 ' def method11():\n' 

1989 ' pass\n' 

1990 ' def method12():\n' 

1991 ' pass\n' 

1992 ' \n' 

1993 'a = 2\n' 

1994 '\n' 

1995 'def f2():\n' 

1996 ' pass\n' 

1997 '\n' 

1998 '# An outer comment\n' 

1999 '@myClassDecorator\n' 

2000 'class Class2:\n' 

2001 ' @myDecorator\n' 

2002 ' def method21():\n' 

2003 ' pass\n' 

2004 ' def method22():\n' 

2005 ' pass\n' 

2006 ' \n' 

2007 '# About main.\n' 

2008 'def main():\n' 

2009 ' pass\n' 

2010 '\n' 

2011 "if __name__ == '__main__':\n" 

2012 ' main()\n' 

2013 ) 

2014 exp_nodes = [ 

2015 (0, 'ignored h', '@language python\n' 

2016 '@tabwidth -4\n' 

2017 'import sys\n' 

2018 '@others\n' 

2019 "if __name__ == '__main__':\n" 

2020 ' main()\n\n' 

2021 ), 

2022 (1, 'f1', 'def f1():\n' 

2023 ' pass\n' 

2024 '\n' 

2025 ), 

2026 (1, 'Class1', 'class Class1:\n' 

2027 ' def method11():\n' 

2028 ' pass\n' 

2029 ' def method12():\n' 

2030 ' pass\n' 

2031 '\n' 

2032 ), 

2033 (1, 'a = 2', 'a = 2\n\n'), 

2034 (1, 'f2', 'def f2():\n' 

2035 ' pass\n' 

2036 '\n' 

2037 ), 

2038 (1, 'Class2', '# An outer comment\n' 

2039 '@myClassDecorator\n' 

2040 'class Class2:\n' 

2041 ' @myDecorator\n' 

2042 ' def method21():\n' 

2043 ' pass\n' 

2044 ' def method22():\n' 

2045 ' pass\n' 

2046 '\n' 

2047 ), 

2048 (1, 'main', '# About main.\n' 

2049 'def main():\n' 

2050 ' pass\n' 

2051 '\n' 

2052 ) 

2053 ] 

2054 p = self.run_test(s) 

2055 ok, msg = self.check_outline(p, exp_nodes) 

2056 assert ok, msg 

2057 #@+node:vitalije.20211206201240.1: *3* TestPython.test_longer_classes 

2058 def test_longer_classes(self): 

2059 s = ('import sys\n' 

2060 'def f1():\n' 

2061 ' pass\n' 

2062 '\n' 

2063 'class Class1:\n' 

2064 ' def method11():\n' 

2065 ' pass\n' 

2066 ' def method12():\n' 

2067 ' pass\n' 

2068 ' \n' 

2069 '#\n' 

2070 '# Define a = 2\n' 

2071 'a = 2\n' 

2072 '\n' 

2073 'def f2():\n' 

2074 ' pass\n' 

2075 '\n' 

2076 '# An outer comment\n' 

2077 '@myClassDecorator\n' 

2078 'class Class2:\n' 

2079 ' def meth00():\n' 

2080 ' print(1)\n' 

2081 ' print(2)\n' 

2082 ' print(3)\n' 

2083 ' print(4)\n' 

2084 ' print(5)\n' 

2085 ' print(6)\n' 

2086 ' print(7)\n' 

2087 ' print(8)\n' 

2088 ' print(9)\n' 

2089 ' print(10)\n' 

2090 ' print(11)\n' 

2091 ' print(12)\n' 

2092 ' print(13)\n' 

2093 ' print(14)\n' 

2094 ' print(15)\n' 

2095 ' @myDecorator\n' 

2096 ' def method21():\n' 

2097 ' pass\n' 

2098 ' def method22():\n' 

2099 ' pass\n' 

2100 ' \n' 

2101 '# About main.\n' 

2102 'def main():\n' 

2103 ' pass\n' 

2104 '\n' 

2105 "if __name__ == '__main__':\n" 

2106 ' main()\n' 

2107 ) 

2108 exp_nodes = [ 

2109 (0, 'ignored h', 

2110 '@language python\n' 

2111 '@tabwidth -4\n' 

2112 'import sys\n' 

2113 '@others\n' 

2114 "if __name__ == '__main__':\n" 

2115 ' main()\n\n' 

2116 ), 

2117 (1, 'f1', 

2118 'def f1():\n' 

2119 ' pass\n' 

2120 '\n' 

2121 ), 

2122 (1, 'Class1', 

2123 'class Class1:\n' 

2124 ' def method11():\n' 

2125 ' pass\n' 

2126 ' def method12():\n' 

2127 ' pass\n' 

2128 '\n' 

2129 ), 

2130 (1, 'Define a = 2', # #2500 

2131 '#\n' 

2132 '# Define a = 2\n' 

2133 'a = 2\n' 

2134 '\n' 

2135 ), 

2136 (1, 'f2', 

2137 'def f2():\n' 

2138 ' pass\n' 

2139 '\n' 

2140 ), 

2141 (1, 'Class2', 

2142 '# An outer comment\n' 

2143 '@myClassDecorator\n' 

2144 'class Class2:\n' 

2145 ' @others\n' 

2146 ), 

2147 (2, 'meth00', 

2148 'def meth00():\n' 

2149 ' print(1)\n' 

2150 ' print(2)\n' 

2151 ' print(3)\n' 

2152 ' print(4)\n' 

2153 ' print(5)\n' 

2154 ' print(6)\n' 

2155 ' print(7)\n' 

2156 ' print(8)\n' 

2157 ' print(9)\n' 

2158 ' print(10)\n' 

2159 ' print(11)\n' 

2160 ' print(12)\n' 

2161 ' print(13)\n' 

2162 ' print(14)\n' 

2163 ' print(15)\n' 

2164 ), 

2165 (2, 'method21', 

2166 '@myDecorator\n' 

2167 'def method21():\n' 

2168 ' pass\n' 

2169 ), 

2170 (2, 'method22', 

2171 'def method22():\n' 

2172 ' pass\n' 

2173 '\n' 

2174 ), 

2175 (1, 'main', 

2176 '# About main.\n' 

2177 'def main():\n' 

2178 ' pass\n' 

2179 '\n' 

2180 ) 

2181 ] 

2182 p = self.run_test(s) 

2183 ok, msg = self.check_outline(p, exp_nodes) 

2184 assert ok, msg 

2185 #@+node:vitalije.20211206212507.1: *3* TestPython.test_oneliners 

2186 def test_oneliners(self): 

2187 s = ('import sys\n' 

2188 'def f1():\n' 

2189 ' pass\n' 

2190 '\n' 

2191 'class Class1:pass\n' 

2192 'a = 2\n' 

2193 '@dec_for_f2\n' 

2194 'def f2(): pass\n' 

2195 '\n' 

2196 '\n' 

2197 'class A: pass\n' 

2198 '# About main.\n' 

2199 'def main():\n' 

2200 ' pass\n' 

2201 '\n' 

2202 "if __name__ == '__main__':\n" 

2203 ' main()\n' 

2204 ) 

2205 exp_nodes = [(0, 'ignored h', 

2206 '@language python\n' 

2207 '@tabwidth -4\n' 

2208 'import sys\n' 

2209 '@others\n' 

2210 "if __name__ == '__main__':\n" 

2211 ' main()\n\n' 

2212 ), 

2213 (1, 'f1', 

2214 'def f1():\n' 

2215 ' pass\n' 

2216 '\n' 

2217 ), 

2218 (1, 'Class1', 

2219 'class Class1:pass\n' 

2220 ), 

2221 (1, 'a = 2', 

2222 'a = 2\n' 

2223 ), 

2224 (1, 'f2', 

2225 '@dec_for_f2\n' 

2226 'def f2(): pass\n' 

2227 '\n' 

2228 '\n' 

2229 ), 

2230 (1, 'A', 

2231 'class A: pass\n' 

2232 ), 

2233 (1, 'main', 

2234 '# About main.\n' 

2235 'def main():\n' 

2236 ' pass\n' 

2237 '\n' 

2238 ) 

2239 ] 

2240 p = self.run_test(s) 

2241 ok, msg = self.check_outline(p, exp_nodes) 

2242 assert ok, msg 

2243 

2244 #@+node:ekr.20211202064822.1: *3* TestPython: test_nested_classes 

2245 def test_nested_classes(self): 

2246 txt = ('class TestCopyFile(unittest.TestCase):\n' 

2247 '\n' 

2248 ' _delete = False\n' 

2249 ' a00 = 1\n' 

2250 ' a01 = 1\n' 

2251 ' a02 = 1\n' 

2252 ' a03 = 1\n' 

2253 ' a04 = 1\n' 

2254 ' a05 = 1\n' 

2255 ' a06 = 1\n' 

2256 ' a07 = 1\n' 

2257 ' a08 = 1\n' 

2258 ' a09 = 1\n' 

2259 ' a10 = 1\n' 

2260 ' a11 = 1\n' 

2261 ' a12 = 1\n' 

2262 ' a13 = 1\n' 

2263 ' a14 = 1\n' 

2264 ' a15 = 1\n' 

2265 ' a16 = 1\n' 

2266 ' a17 = 1\n' 

2267 ' a18 = 1\n' 

2268 ' a19 = 1\n' 

2269 ' a20 = 1\n' 

2270 ' a21 = 1\n' 

2271 ' class Faux(object):\n' 

2272 ' _entered = False\n' 

2273 ' _exited_with = None # type: tuple\n' 

2274 ' _raised = False\n' 

2275 ) 

2276 exp_nodes = [ 

2277 (0, 'ignored h', 

2278 '@language python\n' 

2279 '@tabwidth -4\n' 

2280 '@others\n' 

2281 ), 

2282 (1, 'TestCopyFile', 

2283 'class TestCopyFile(unittest.TestCase):\n' 

2284 '\n' 

2285 ' _delete = False\n' 

2286 ' a00 = 1\n' 

2287 ' a01 = 1\n' 

2288 ' a02 = 1\n' 

2289 ' a03 = 1\n' 

2290 ' a04 = 1\n' 

2291 ' a05 = 1\n' 

2292 ' a06 = 1\n' 

2293 ' a07 = 1\n' 

2294 ' a08 = 1\n' 

2295 ' a09 = 1\n' 

2296 ' a10 = 1\n' 

2297 ' a11 = 1\n' 

2298 ' a12 = 1\n' 

2299 ' a13 = 1\n' 

2300 ' a14 = 1\n' 

2301 ' a15 = 1\n' 

2302 ' a16 = 1\n' 

2303 ' a17 = 1\n' 

2304 ' a18 = 1\n' 

2305 ' a19 = 1\n' 

2306 ' a20 = 1\n' 

2307 ' a21 = 1\n' 

2308 ' @others\n' 

2309 ), 

2310 (2, 'Faux', 

2311 'class Faux(object):\n' 

2312 ' _entered = False\n' 

2313 ' _exited_with = None # type: tuple\n' 

2314 ' _raised = False\n\n' 

2315 ) 

2316 ] 

2317 # mypy/test-data/stdlib-samples/3.2/test/shutil.py 

2318 p = self.run_test(txt) 

2319 ok, msg = self.check_outline(p, exp_nodes) 

2320 assert ok, msg 

2321 #@+node:vitalije.20211213125810.1: *3* TestPython: test_nested_classes 

2322 def test_nested_classes_with_async(self): 

2323 txt = ('class TestCopyFile(unittest.TestCase):\n' 

2324 '\n' 

2325 ' _delete = False\n' 

2326 ' a00 = 1\n' 

2327 ' a01 = 1\n' 

2328 ' a02 = 1\n' 

2329 ' a03 = 1\n' 

2330 ' a04 = 1\n' 

2331 ' a05 = 1\n' 

2332 ' a06 = 1\n' 

2333 ' a07 = 1\n' 

2334 ' a08 = 1\n' 

2335 ' a09 = 1\n' 

2336 ' a10 = 1\n' 

2337 ' a11 = 1\n' 

2338 ' a12 = 1\n' 

2339 ' a13 = 1\n' 

2340 ' a14 = 1\n' 

2341 ' a15 = 1\n' 

2342 ' a16 = 1\n' 

2343 ' a17 = 1\n' 

2344 ' a18 = 1\n' 

2345 ' a19 = 1\n' 

2346 ' a20 = 1\n' 

2347 ' a21 = 1\n' 

2348 ' async def a(self):\n' 

2349 ' return await f(self)\n' 

2350 ' class Faux(object):\n' 

2351 ' _entered = False\n' 

2352 ' _exited_with = None # type: tuple\n' 

2353 ' _raised = False\n' 

2354 ) 

2355 exp_nodes = [ 

2356 (0, 'ignored h', 

2357 '@language python\n' 

2358 '@tabwidth -4\n' 

2359 '@others\n' 

2360 ), 

2361 (1, 'TestCopyFile', 

2362 'class TestCopyFile(unittest.TestCase):\n' 

2363 '\n' 

2364 ' _delete = False\n' 

2365 ' a00 = 1\n' 

2366 ' a01 = 1\n' 

2367 ' a02 = 1\n' 

2368 ' a03 = 1\n' 

2369 ' a04 = 1\n' 

2370 ' a05 = 1\n' 

2371 ' a06 = 1\n' 

2372 ' a07 = 1\n' 

2373 ' a08 = 1\n' 

2374 ' a09 = 1\n' 

2375 ' a10 = 1\n' 

2376 ' a11 = 1\n' 

2377 ' a12 = 1\n' 

2378 ' a13 = 1\n' 

2379 ' a14 = 1\n' 

2380 ' a15 = 1\n' 

2381 ' a16 = 1\n' 

2382 ' a17 = 1\n' 

2383 ' a18 = 1\n' 

2384 ' a19 = 1\n' 

2385 ' a20 = 1\n' 

2386 ' a21 = 1\n' 

2387 ' @others\n' 

2388 ), 

2389 (2, 'a', 

2390 'async def a(self):\n' 

2391 ' return await f(self)\n' 

2392 ), 

2393 (2, 'Faux', 

2394 'class Faux(object):\n' 

2395 ' _entered = False\n' 

2396 ' _exited_with = None # type: tuple\n' 

2397 ' _raised = False\n\n' 

2398 ) 

2399 ] 

2400 # mypy/test-data/stdlib-samples/3.2/test/shutil.py 

2401 p = self.run_test(txt) 

2402 ok, msg = self.check_outline(p, exp_nodes) 

2403 assert ok, msg 

2404 #@+node:ekr.20211202094115.1: *3* TestPython: test_strange_indentation 

2405 def test_strange_indentation(self): 

2406 txt = ('if 1:\n' 

2407 " print('1')\n" 

2408 'if 2:\n' 

2409 " print('2')\n" 

2410 'if 3:\n' 

2411 " print('3')\n" 

2412 '\n' 

2413 'class StrangeClass:\n' 

2414 ' a = 1\n' 

2415 ' if 1:\n' 

2416 " print('1')\n" 

2417 ' if 2:\n' 

2418 " print('2')\n" 

2419 ' if 3:\n' 

2420 " print('3')\n" 

2421 ' if 4:\n' 

2422 " print('4')\n" 

2423 ' if 5:\n' 

2424 " print('5')\n" 

2425 ' if 6:\n' 

2426 " print('6')\n" 

2427 ' if 7:\n' 

2428 " print('7')\n" 

2429 ' if 8:\n' 

2430 " print('8')\n" 

2431 ' if 9:\n' 

2432 " print('9')\n" 

2433 ' if 10:\n' 

2434 " print('10')\n" 

2435 ' if 11:\n' 

2436 " print('11')\n" 

2437 ' if 12:\n' 

2438 " print('12')\n" 

2439 ' def a(self):\n' 

2440 ' pass\n' 

2441 ) 

2442 exp_nodes = [ 

2443 (0, 'ignored h', 

2444 '@language python\n' 

2445 '@tabwidth -4\n' 

2446 'if 1:\n' 

2447 " print('1')\n" 

2448 'if 2:\n' 

2449 " print('2')\n" 

2450 'if 3:\n' 

2451 " print('3')\n" 

2452 '\n' 

2453 '@others\n' 

2454 ), 

2455 (1, 'StrangeClass', 

2456 'class StrangeClass:\n' 

2457 ' a = 1\n' 

2458 ' if 1:\n' 

2459 " print('1')\n" 

2460 ' if 2:\n' 

2461 " print('2')\n" 

2462 ' if 3:\n' 

2463 " print('3')\n" 

2464 ' if 4:\n' 

2465 " print('4')\n" 

2466 ' if 5:\n' 

2467 " print('5')\n" 

2468 ' if 6:\n' 

2469 " print('6')\n" 

2470 ' if 7:\n' 

2471 " print('7')\n" 

2472 ' if 8:\n' 

2473 " print('8')\n" 

2474 ' if 9:\n' 

2475 " print('9')\n" 

2476 ' if 10:\n' 

2477 " print('10')\n" 

2478 ' if 11:\n' 

2479 " print('11')\n" 

2480 ' if 12:\n' 

2481 " print('12')\n" 

2482 ' @others\n' 

2483 ), 

2484 (2, 'a', 

2485 'def a(self):\n' 

2486 ' pass\n\n' 

2487 ) 

2488 ] 

2489 p = self.run_test(txt) 

2490 ok, msg = self.check_outline(p, exp_nodes) 

2491 assert ok, msg 

2492 #@+node:vitalije.20211208210459.1: *3* TestPython: test_strange_indentation 

2493 def test_strange_indentation_with_added_class_in_the_headline(self): 

2494 self.c.config.set(None, 'bool', 'put-class-in-imported-headlines', True) 

2495 txt = ('if 1:\n' 

2496 " print('1')\n" 

2497 'if 2:\n' 

2498 " print('2')\n" 

2499 'if 3:\n' 

2500 " print('3')\n" 

2501 '\n' 

2502 'class StrangeClass:\n' 

2503 ' a = 1\n' 

2504 ' if 1:\n' 

2505 " print('1')\n" 

2506 ' if 2:\n' 

2507 " print('2')\n" 

2508 ' if 3:\n' 

2509 " print('3')\n" 

2510 ' if 4:\n' 

2511 " print('4')\n" 

2512 ' if 5:\n' 

2513 " print('5')\n" 

2514 ' if 6:\n' 

2515 " print('6')\n" 

2516 ' if 7:\n' 

2517 " print('7')\n" 

2518 ' if 8:\n' 

2519 " print('8')\n" 

2520 ' if 9:\n' 

2521 " print('9')\n" 

2522 ' if 10:\n' 

2523 " print('10')\n" 

2524 ' if 11:\n' 

2525 " print('11')\n" 

2526 ' if 12:\n' 

2527 " print('12')\n" 

2528 ' def a(self):\n' 

2529 ' pass\n' 

2530 ) 

2531 exp_nodes = [ 

2532 (0, 'ignored h', 

2533 '@language python\n' 

2534 '@tabwidth -4\n' 

2535 'if 1:\n' 

2536 " print('1')\n" 

2537 'if 2:\n' 

2538 " print('2')\n" 

2539 'if 3:\n' 

2540 " print('3')\n" 

2541 '\n' 

2542 '@others\n' 

2543 ), 

2544 (1, 'class StrangeClass', 

2545 'class StrangeClass:\n' 

2546 ' a = 1\n' 

2547 ' if 1:\n' 

2548 " print('1')\n" 

2549 ' if 2:\n' 

2550 " print('2')\n" 

2551 ' if 3:\n' 

2552 " print('3')\n" 

2553 ' if 4:\n' 

2554 " print('4')\n" 

2555 ' if 5:\n' 

2556 " print('5')\n" 

2557 ' if 6:\n' 

2558 " print('6')\n" 

2559 ' if 7:\n' 

2560 " print('7')\n" 

2561 ' if 8:\n' 

2562 " print('8')\n" 

2563 ' if 9:\n' 

2564 " print('9')\n" 

2565 ' if 10:\n' 

2566 " print('10')\n" 

2567 ' if 11:\n' 

2568 " print('11')\n" 

2569 ' if 12:\n' 

2570 " print('12')\n" 

2571 ' @others\n' 

2572 ), 

2573 (2, 'a', 

2574 'def a(self):\n' 

2575 ' pass\n\n' 

2576 ) 

2577 ] 

2578 p = self.run_test(txt) 

2579 ok, msg = self.check_outline(p, exp_nodes) 

2580 assert ok, msg 

2581 #@+node:vitalije.20211207183645.1: *3* TestPython: test_no_defs 

2582 def test_no_defs(self): 

2583 txt = ('a = 1\n' 

2584 'if 1:\n' 

2585 " print('1')\n" 

2586 'if 2:\n' 

2587 " print('2')\n" 

2588 'if 3:\n' 

2589 " print('3')\n" 

2590 'if 4:\n' 

2591 " print('4')\n" 

2592 'if 5:\n' 

2593 " print('5')\n" 

2594 'if 6:\n' 

2595 " print('6')\n" 

2596 'if 7:\n' 

2597 " print('7')\n" 

2598 'if 8:\n' 

2599 " print('8')\n" 

2600 'if 9:\n' 

2601 " print('9')\n" 

2602 'if 10:\n' 

2603 " print('10')\n" 

2604 'if 11:\n' 

2605 " print('11')\n" 

2606 'if 12:\n' 

2607 " print('12')\n" 

2608 ) 

2609 exp_nodes = [ 

2610 (0, 'ignored h', '@language python\n' 

2611 '@tabwidth -4\n' 

2612 'a = 1\n' 

2613 'if 1:\n' 

2614 " print('1')\n" 

2615 'if 2:\n' 

2616 " print('2')\n" 

2617 'if 3:\n' 

2618 " print('3')\n" 

2619 'if 4:\n' 

2620 " print('4')\n" 

2621 'if 5:\n' 

2622 " print('5')\n" 

2623 'if 6:\n' 

2624 " print('6')\n" 

2625 'if 7:\n' 

2626 " print('7')\n" 

2627 'if 8:\n' 

2628 " print('8')\n" 

2629 'if 9:\n' 

2630 " print('9')\n" 

2631 'if 10:\n' 

2632 " print('10')\n" 

2633 'if 11:\n' 

2634 " print('11')\n" 

2635 'if 12:\n' 

2636 " print('12')\n\n" 

2637 ) 

2638 ] 

2639 p = self.run_test(txt) 

2640 ok, msg = self.check_outline(p, exp_nodes) 

2641 assert ok, msg 

2642 #@+node:vitalije.20211207185708.1: *3* TestPython: test_only_docs 

2643 def test_only_docs(self): 

2644 txt = ('class A:\n' 

2645 ' """\n' 

2646 ' dummy doc\n' 

2647 " another line\n" 

2648 " another line\n" 

2649 " another line\n" 

2650 " another line\n" 

2651 " another line\n" 

2652 " another line\n" 

2653 " another line\n" 

2654 " another line\n" 

2655 " another line\n" 

2656 " another line\n" 

2657 " another line\n" 

2658 " another line\n" 

2659 " another line\n" 

2660 " another line\n" 

2661 " another line\n" 

2662 " another line\n" 

2663 " another line\n" 

2664 " another line\n" 

2665 " another line\n" 

2666 " another line\n" 

2667 " another line\n" 

2668 " another line\n" 

2669 " another line\n" 

2670 ' """\n' 

2671 ' def __init__(self):\n' 

2672 ' pass\n' 

2673 '\n' 

2674 ) 

2675 exp_nodes = [ 

2676 (0, 'ignored h', 

2677 '@language python\n' 

2678 '@tabwidth -4\n' 

2679 '@others\n' 

2680 ), 

2681 (1, 'A', 

2682 'class A:\n' 

2683 ' """\n' 

2684 ' dummy doc\n' 

2685 ' another line\n' 

2686 ' another line\n' 

2687 ' another line\n' 

2688 ' another line\n' 

2689 ' another line\n' 

2690 ' another line\n' 

2691 ' another line\n' 

2692 ' another line\n' 

2693 ' another line\n' 

2694 ' another line\n' 

2695 ' another line\n' 

2696 ' another line\n' 

2697 ' another line\n' 

2698 ' another line\n' 

2699 ' another line\n' 

2700 ' another line\n' 

2701 ' another line\n' 

2702 ' another line\n' 

2703 ' another line\n' 

2704 ' another line\n' 

2705 ' another line\n' 

2706 ' another line\n' 

2707 ' another line\n' 

2708 ' """\n' 

2709 ' @others\n' 

2710 ), 

2711 (2, '__init__', 

2712 'def __init__(self):\n' 

2713 ' pass\n' 

2714 '\n' 

2715 ) 

2716 ] 

2717 p = self.run_test(txt) 

2718 ok, msg = self.check_outline(p, exp_nodes) 

2719 assert ok, msg 

2720 #@+node:vitalije.20211207200701.1: *3* TestPython: test_large_class_no_methods 

2721 def test_large_class_no_methods(self): 

2722 

2723 if sys.version_info < (3, 9, 0): 

2724 self.skipTest('Requires Python 3.9') # pragma: no cover 

2725 

2726 txt = ('class A:\n' 

2727 ' a=1\n' 

2728 ' b=1\n' 

2729 ' c=1\n' 

2730 ' d=1\n' 

2731 ' e=1\n' 

2732 ' f=1\n' 

2733 ' g=1\n' 

2734 ' h=1\n' 

2735 ' i=1\n' 

2736 ' j=1\n' 

2737 ' k=1\n' 

2738 ' l=1\n' 

2739 ' m=1\n' 

2740 ' n=1\n' 

2741 ' o=1\n' 

2742 ' p=1\n' 

2743 ' q=1\n' 

2744 ' r=1\n' 

2745 ' s=1\n' 

2746 ' t=1\n' 

2747 ' u=1\n' 

2748 ' v=1\n' 

2749 ' w=1\n' 

2750 ' x=1\n' 

2751 ' y=1\n' 

2752 ' x=1\n' 

2753 '\n' 

2754 ) 

2755 exp_nodes = [ 

2756 (0, 'ignored h', 

2757 '@language python\n' 

2758 '@tabwidth -4\n' 

2759 '@others\n' 

2760 ), 

2761 (1, 'A', 

2762 'class A:\n' 

2763 ' a=1\n' 

2764 ' b=1\n' 

2765 ' c=1\n' 

2766 ' d=1\n' 

2767 ' e=1\n' 

2768 ' f=1\n' 

2769 ' g=1\n' 

2770 ' h=1\n' 

2771 ' i=1\n' 

2772 ' j=1\n' 

2773 ' k=1\n' 

2774 ' l=1\n' 

2775 ' m=1\n' 

2776 ' n=1\n' 

2777 ' o=1\n' 

2778 ' p=1\n' 

2779 ' q=1\n' 

2780 ' r=1\n' 

2781 ' s=1\n' 

2782 ' t=1\n' 

2783 ' u=1\n' 

2784 ' v=1\n' 

2785 ' w=1\n' 

2786 ' x=1\n' 

2787 ' y=1\n' 

2788 ' x=1\n' 

2789 '\n' 

2790 ) 

2791 ] 

2792 p = self.run_test(txt) 

2793 ok, msg = self.check_outline(p, exp_nodes) 

2794 assert ok, msg 

2795 #@+node:vitalije.20211213125307.1: *3* TestPython: test_large_class_no_methods 

2796 def test_large_class_under_indented(self): 

2797 txt = ('class A:\n' 

2798 ' a=1\n' 

2799 ' b=1\n' 

2800 ' c=1\n' 

2801 ' d=1\n' 

2802 ' e=1\n' 

2803 ' def f(self):\n' 

2804 ' self._f = """dummy\n' 

2805 'dummy2\n' 

2806 'dummy3"""\n' 

2807 ' g=1\n' 

2808 ' h=1\n' 

2809 ' i=1\n' 

2810 ' j=1\n' 

2811 ' k=1\n' 

2812 ' l=1\n' 

2813 ' m=1\n' 

2814 ' n=1\n' 

2815 ' o=1\n' 

2816 ' p=1\n' 

2817 ' q=1\n' 

2818 ' r=1\n' 

2819 ' s=1\n' 

2820 ' t=1\n' 

2821 ' u=1\n' 

2822 ' v=1\n' 

2823 ' w=1\n' 

2824 ' x=1\n' 

2825 ' y=1\n' 

2826 ' x=1\n' 

2827 '\n' 

2828 ) 

2829 exp_nodes = [ 

2830 (0, 'ignored h', 

2831 '@language python\n' 

2832 '@tabwidth -4\n' 

2833 '@others\n' 

2834 ), 

2835 (1, 'A', 

2836 'class A:\n' 

2837 ' a=1\n' 

2838 ' b=1\n' 

2839 ' c=1\n' 

2840 ' d=1\n' 

2841 ' e=1\n' 

2842 ' @others\n' 

2843 ' g=1\n' 

2844 ' h=1\n' 

2845 ' i=1\n' 

2846 ' j=1\n' 

2847 ' k=1\n' 

2848 ' l=1\n' 

2849 ' m=1\n' 

2850 ' n=1\n' 

2851 ' o=1\n' 

2852 ' p=1\n' 

2853 ' q=1\n' 

2854 ' r=1\n' 

2855 ' s=1\n' 

2856 ' t=1\n' 

2857 ' u=1\n' 

2858 ' v=1\n' 

2859 ' w=1\n' 

2860 ' x=1\n' 

2861 ' y=1\n' 

2862 ' x=1\n' 

2863 '\n' 

2864 ), 

2865 (2, 'f', 

2866 'def f(self):\n' 

2867 ' self._f = """dummy\n' 

2868 '\\\\-4.dummy2\n' 

2869 '\\\\-4.dummy3"""\n' 

2870 ) 

2871 ] 

2872 p = self.run_test(txt) 

2873 ok, msg = self.check_outline(p, exp_nodes) 

2874 assert ok, msg 

2875 #@+node:vitalije.20211206180043.1: *3* check_outline 

2876 def check_outline(self, p, nodes): 

2877 it = iter(nodes) 

2878 zlev = p.level() 

2879 for p1 in p.self_and_subtree(): 

2880 lev, h, b = next(it) 

2881 assert p1.level() - zlev == lev, f'lev:{p1.level()-zlev} != {lev}' 

2882 if lev > 0: 

2883 assert p1.h == h, f'"{p1.h}" != "{h}"' 

2884 assert p1.b == b, f'\n{repr(p1.b)} !=\n{repr(b)}' 

2885 try: 

2886 next(it) 

2887 return False, 'extra nodes' # pragma: no cover 

2888 except StopIteration: 

2889 return True, 'ok' 

2890 #@-others 

2891#@+node:ekr.20211108050827.1: ** class TestRst (BaseTestImporter) 

2892class TestRst(BaseTestImporter): 

2893 

2894 ext = '.rst' 

2895 treeType = '@auto-rst' 

2896 

2897 #@+others 

2898 #@+node:ekr.20210904065459.115: *3* TestRst.test_rst_1 

2899 def test_rst_1(self): 

2900 

2901 try: 

2902 import docutils 

2903 assert docutils 

2904 except Exception: # pragma: no cover 

2905 self.skipTest('no docutils') 

2906 

2907 s = """ 

2908 .. toc 

2909 

2910 ==== 

2911 top 

2912 ==== 

2913 

2914 The top section 

2915 

2916 section 1 

2917 --------- 

2918 

2919 section 1, line 1 

2920 -- 

2921 section 1, line 2 

2922 

2923 section 2 

2924 --------- 

2925 

2926 section 2, line 1 

2927 

2928 section 2.1 

2929 ~~~~~~~~~~~ 

2930 

2931 section 2.1, line 1 

2932 

2933 section 2.1.1 

2934 ............. 

2935 

2936 section 2.2.1 line 1 

2937 

2938 section 3 

2939 --------- 

2940 

2941 section 3, line 1 

2942 

2943 section 3.1.1 

2944 ............. 

2945 

2946 section 3.1.1, line 1 

2947 """ 

2948 p = self.run_test(s) 

2949 self.check_headlines(p, ( 

2950 (1, '!Dummy chapter'), 

2951 (1, 'top'), 

2952 (1, 'section 1'), 

2953 (1, 'section 2'), 

2954 (2, 'section 2.1'), 

2955 (3, 'section 2.1.1'), 

2956 (1, 'section 3'), 

2957 (2, 'placeholder'), 

2958 (3, 'section 3.1.1'), 

2959 )) 

2960 #@+node:ekr.20210904065459.116: *3* TestRst.test_simple 

2961 def test_simple(self): 

2962 

2963 try: 

2964 import docutils 

2965 assert docutils 

2966 except Exception: # pragma: no cover 

2967 self.skipTest('no docutils') 

2968 

2969 s = """ 

2970 .. toc 

2971 

2972 .. The section name contains trailing whitespace. 

2973 

2974 ======= 

2975 Chapter 

2976 ======= 

2977 

2978 The top chapter. 

2979 """ 

2980 p = self.run_test(s) 

2981 self.check_headlines(p, ( 

2982 (1, "!Dummy chapter"), 

2983 (1, "Chapter"), 

2984 )) 

2985 #@+node:ekr.20210904065459.117: *3* TestRst.test_no_double_underlines 

2986 def test_no_double_underlines(self): 

2987 

2988 try: 

2989 import docutils 

2990 assert docutils 

2991 except Exception: # pragma: no cover 

2992 self.skipTest('no docutils') 

2993 

2994 s = """ 

2995 .. toc 

2996 

2997 top 

2998 ==== 

2999 

3000 The top section 

3001 

3002 section 1 

3003 --------- 

3004 

3005 section 1, line 1 

3006 -- 

3007 section 1, line 2 

3008 

3009 section 2 

3010 --------- 

3011 

3012 section 2, line 1 

3013 

3014 section 2.1 

3015 ~~~~~~~~~~~ 

3016 

3017 section 2.1, line 1 

3018 

3019 section 2.1.1 

3020 ............. 

3021 

3022 section 2.2.1 line 1 

3023 

3024 section 3 

3025 --------- 

3026 

3027 section 3, line 1 

3028 

3029 section 3.1.1 

3030 ............. 

3031 

3032 section 3.1.1, line 1 

3033 """ 

3034 p = self.run_test(s) 

3035 self.check_headlines(p, ( 

3036 (1, '!Dummy chapter'), 

3037 (1, 'top'), 

3038 (1, 'section 1'), 

3039 (1, 'section 2'), 

3040 (2, 'section 2.1'), 

3041 (3, 'section 2.1.1'), 

3042 (1, 'section 3'), 

3043 (2, 'placeholder'), 

3044 (3, 'section 3.1.1'), 

3045 )) 

3046 #@+node:ekr.20210904065459.118: *3* TestRst.test_long_underlines 

3047 def test_long_underlines(self): 

3048 

3049 try: 

3050 import docutils 

3051 assert docutils 

3052 except Exception: # pragma: no cover 

3053 self.skipTest('no docutils') 

3054 

3055 s = """ 

3056 .. toc 

3057 

3058 top 

3059 ------------- 

3060 

3061 The top section 

3062 """ 

3063 p = self.run_test(s) 

3064 self.check_headlines(p, ( 

3065 (1, '!Dummy chapter'), 

3066 (1, 'top'), 

3067 )) 

3068 #@+node:ekr.20210904065459.119: *3* TestRst.test_test_long_overlines 

3069 def test_test_long_overlines(self): 

3070 

3071 try: 

3072 import docutils 

3073 assert docutils 

3074 except Exception: # pragma: no cover 

3075 self.skipTest('no docutils') 

3076 

3077 s = """ 

3078 .. toc 

3079 

3080 ====== 

3081 top 

3082 ====== 

3083 

3084 The top section 

3085 """ 

3086 p = self.run_test(s) 

3087 self.check_headlines(p, ( 

3088 (1, "!Dummy chapter"), 

3089 (1, "top"), 

3090 )) 

3091 #@+node:ekr.20210904065459.120: *3* TestRst.test_trailing_whitespace 

3092 def test_trailing_whitespace(self): 

3093 

3094 try: 

3095 import docutils 

3096 assert docutils 

3097 except Exception: # pragma: no cover 

3098 self.skipTest('no docutils') 

3099 

3100 s = """ 

3101 .. toc 

3102 

3103 .. The section name contains trailing whitespace. 

3104 

3105 ====== 

3106 top 

3107 ====== 

3108 

3109 The top section. 

3110 """ 

3111 p = self.run_test(s) 

3112 self.check_headlines(p, ( 

3113 (1, "!Dummy chapter"), 

3114 (1, "top"), 

3115 )) 

3116 #@+node:ekr.20210904065459.121: *3* TestRst.test_leo_rst 

3117 def test_leo_rst(self): 

3118 

3119 try: 

3120 import docutils 

3121 assert docutils 

3122 except Exception: # pragma: no cover 

3123 self.skipTest('no docutils') 

3124 

3125 # All heading must be followed by an empty line. 

3126 s = """\ 

3127 ######### 

3128 Chapter 1 

3129 ######### 

3130 

3131 It was a dark and stormy night. 

3132 

3133 section 1 

3134 +++++++++ 

3135 

3136 Sec 1. 

3137 

3138 section 2 

3139 +++++++++ 

3140 

3141 Sec 2. 

3142 """ 

3143 p = self.run_test(s) 

3144 self.check_headlines(p, ( 

3145 (1, 'Chapter 1'), 

3146 (2, 'section 1'), 

3147 (2, 'section 2'), 

3148 )) 

3149 #@-others 

3150#@+node:ekr.20211108083038.1: ** class TestTypescript (BaseTestImporter) 

3151class TestTypescript(BaseTestImporter): 

3152 

3153 ext = '.ts' 

3154 

3155 #@+others 

3156 #@+node:ekr.20210904065459.103: *3* TestTypescript.test_class 

3157 def test_class(self): 

3158 

3159 s = ''' 

3160 class Greeter { 

3161 greeting: string; 

3162 constructor (message: string) { 

3163 this.greeting = message; 

3164 } 

3165 greet() { 

3166 return "Hello, " + this.greeting; 

3167 } 

3168 } 

3169 

3170 var greeter = new Greeter("world"); 

3171 

3172 var button = document.createElement('button') 

3173 button.innerText = "Say Hello" 

3174 button.onclick = function() { 

3175 alert(greeter.greet()) 

3176 } 

3177 

3178 document.body.appendChild(button) 

3179 

3180 ''' 

3181 self.run_test(s) 

3182 #@+node:ekr.20210904065459.104: *3* TestTypescript.test_module 

3183 def test_module(self): 

3184 s = ''' 

3185 module Sayings { 

3186 export class Greeter { 

3187 greeting: string; 

3188 constructor (message: string) { 

3189 this.greeting = message; 

3190 } 

3191 greet() { 

3192 return "Hello, " + this.greeting; 

3193 } 

3194 } 

3195 } 

3196 var greeter = new Sayings.Greeter("world"); 

3197 

3198 var button = document.createElement('button') 

3199 button.innerText = "Say Hello" 

3200 button.onclick = function() { 

3201 alert(greeter.greet()) 

3202 } 

3203 

3204 document.body.appendChild(button) 

3205 ''' 

3206 self.run_test(s) 

3207 #@-others 

3208#@+node:ekr.20211108065014.1: ** class TestXML (BaseTestImporter) 

3209class TestXML(BaseTestImporter): 

3210 

3211 ext = '.xml' 

3212 

3213 def setUp(self): 

3214 super().setUp() 

3215 c = self.c 

3216 # Simulate @data import-xml-tags, with *only* standard tags. 

3217 tags_list = ['html', 'body', 'head', 'div', 'table'] 

3218 settingsDict, junk = g.app.loadManager.createDefaultSettingsDicts() 

3219 c.config.settingsDict = settingsDict 

3220 c.config.set(c.p, 'data', 'import-xml-tags', tags_list, warn=True) 

3221 

3222 #@+others 

3223 #@+node:ekr.20210904065459.105: *3* TestXml.test_standard_opening_elements 

3224 def test_standard_opening_elements(self): 

3225 c = self.c 

3226 s = """ 

3227 <?xml version="1.0" encoding="UTF-8"?> 

3228 <!DOCTYPE note SYSTEM "Note.dtd"> 

3229 <html> 

3230 <head> 

3231 <title>Bodystring</title> 

3232 </head> 

3233 <body class='bodystring'> 

3234 <div id='bodydisplay'></div> 

3235 </body> 

3236 </html> 

3237 """ 

3238 table = ( 

3239 (1, "<html>"), 

3240 (2, "<head>"), 

3241 (2, "<body class='bodystring'>"), 

3242 ) 

3243 p = c.p 

3244 self.run_test(s) 

3245 after = p.nodeAfterTree() 

3246 root = p.lastChild() 

3247 self.assertEqual(root.h, f"@file {self.short_id}") 

3248 p = root.firstChild() 

3249 for n, h in table: 

3250 n2 = p.level() - root.level() 

3251 self.assertEqual(h, p.h) 

3252 self.assertEqual(n, n2) 

3253 p.moveToThreadNext() 

3254 self.assertEqual(p, after) 

3255 #@+node:ekr.20210904065459.106: *3* TestXml.test_xml_1 

3256 def test_xml_11(self): 

3257 

3258 s = """ 

3259 <html> 

3260 <head> 

3261 <title>Bodystring</title> 

3262 </head> 

3263 <body class='bodystring'> 

3264 <div id='bodydisplay'></div> 

3265 </body> 

3266 </html> 

3267 """ 

3268 p = self.run_test(s) 

3269 self.check_headlines(p, ( 

3270 (1, "<html>"), 

3271 (2, "<head>"), 

3272 (2, "<body class='bodystring'>"), 

3273 )) 

3274 #@+node:ekr.20210904065459.108: *3* TestXml.test_non_ascii_tags 

3275 def test_non_ascii_tags(self): 

3276 s = """ 

3277 <:À.Ç> 

3278 <Ì> 

3279 <_.ÌÑ> 

3280 """ 

3281 self.run_test(s) 

3282 #@+node:ekr.20210904065459.132: *3* TestXml.test_is_ws_line 

3283 def test_is_ws_line(self): 

3284 c = self.c 

3285 x = xml.Xml_Importer(importCommands=c.importCommands, atAuto=False) 

3286 table = ( 

3287 (1, ' \n'), 

3288 (1, '\n'), 

3289 (1, ' '), 

3290 (1, '<!-- comment -->'), 

3291 (0, ' <!-- comment --> Help'), 

3292 (0, 'x <!-- comment -->'), 

3293 (0, 'Help'), 

3294 ) 

3295 for expected, line in table: 

3296 got = x.is_ws_line(line) 

3297 self.assertEqual(expected, got, msg=repr(line)) 

3298 #@+node:ekr.20210904065459.133: *3* TestXml.test_scan_line 

3299 def test_scan_line(self): 

3300 c = self.c 

3301 x = xml.Xml_Importer(importCommands=c.importCommands, atAuto=False) 

3302 x.start_tags.append('html') # Don't rely on settings. 

3303 table = ( 

3304 (0, '<tag>'), 

3305 (0, '<tag></tag'), 

3306 (1, '<html'), 

3307 (1, '<html attrib="<">'), 

3308 (0, '<html attrib="<" />'), 

3309 (0, '<html>x</html>'), 

3310 (0, '</br>'), # Tag underflow 

3311 (0, '<br />'), 

3312 (0, '<br/>'), 

3313 ) 

3314 for level, line in table: 

3315 prev_state = x.state_class() # Start in level 0 

3316 self.assertEqual(prev_state.tag_level, 0, msg=line) 

3317 new_state = x.scan_line(line, prev_state) 

3318 self.assertEqual(new_state.tag_level, level, msg=line) 

3319 #@-others 

3320#@-others 

3321 

3322 

3323#@-leo