Coverage for core\test_leoImport.py: 100%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

596 statements  

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 import sys 

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

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

2726 

2727 txt = ('class A:\n' 

2728 ' a=1\n' 

2729 ' b=1\n' 

2730 ' c=1\n' 

2731 ' d=1\n' 

2732 ' e=1\n' 

2733 ' f=1\n' 

2734 ' g=1\n' 

2735 ' h=1\n' 

2736 ' i=1\n' 

2737 ' j=1\n' 

2738 ' k=1\n' 

2739 ' l=1\n' 

2740 ' m=1\n' 

2741 ' n=1\n' 

2742 ' o=1\n' 

2743 ' p=1\n' 

2744 ' q=1\n' 

2745 ' r=1\n' 

2746 ' s=1\n' 

2747 ' t=1\n' 

2748 ' u=1\n' 

2749 ' v=1\n' 

2750 ' w=1\n' 

2751 ' x=1\n' 

2752 ' y=1\n' 

2753 ' x=1\n' 

2754 '\n' 

2755 ) 

2756 exp_nodes = [ 

2757 (0, 'ignored h', 

2758 '@language python\n' 

2759 '@tabwidth -4\n' 

2760 '@others\n' 

2761 ), 

2762 (1, 'A', 

2763 'class A:\n' 

2764 ' a=1\n' 

2765 ' b=1\n' 

2766 ' c=1\n' 

2767 ' d=1\n' 

2768 ' e=1\n' 

2769 ' f=1\n' 

2770 ' g=1\n' 

2771 ' h=1\n' 

2772 ' i=1\n' 

2773 ' j=1\n' 

2774 ' k=1\n' 

2775 ' l=1\n' 

2776 ' m=1\n' 

2777 ' n=1\n' 

2778 ' o=1\n' 

2779 ' p=1\n' 

2780 ' q=1\n' 

2781 ' r=1\n' 

2782 ' s=1\n' 

2783 ' t=1\n' 

2784 ' u=1\n' 

2785 ' v=1\n' 

2786 ' w=1\n' 

2787 ' x=1\n' 

2788 ' y=1\n' 

2789 ' x=1\n' 

2790 '\n' 

2791 ) 

2792 ] 

2793 p = self.run_test(txt) 

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

2795 assert ok, msg 

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

2797 def test_large_class_under_indented(self): 

2798 txt = ('class A:\n' 

2799 ' a=1\n' 

2800 ' b=1\n' 

2801 ' c=1\n' 

2802 ' d=1\n' 

2803 ' e=1\n' 

2804 ' def f(self):\n' 

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

2806 'dummy2\n' 

2807 'dummy3"""\n' 

2808 ' g=1\n' 

2809 ' h=1\n' 

2810 ' i=1\n' 

2811 ' j=1\n' 

2812 ' k=1\n' 

2813 ' l=1\n' 

2814 ' m=1\n' 

2815 ' n=1\n' 

2816 ' o=1\n' 

2817 ' p=1\n' 

2818 ' q=1\n' 

2819 ' r=1\n' 

2820 ' s=1\n' 

2821 ' t=1\n' 

2822 ' u=1\n' 

2823 ' v=1\n' 

2824 ' w=1\n' 

2825 ' x=1\n' 

2826 ' y=1\n' 

2827 ' x=1\n' 

2828 '\n' 

2829 ) 

2830 exp_nodes = [ 

2831 (0, 'ignored h', 

2832 '@language python\n' 

2833 '@tabwidth -4\n' 

2834 '@others\n' 

2835 ), 

2836 (1, 'A', 

2837 'class A:\n' 

2838 ' a=1\n' 

2839 ' b=1\n' 

2840 ' c=1\n' 

2841 ' d=1\n' 

2842 ' e=1\n' 

2843 ' @others\n' 

2844 ' g=1\n' 

2845 ' h=1\n' 

2846 ' i=1\n' 

2847 ' j=1\n' 

2848 ' k=1\n' 

2849 ' l=1\n' 

2850 ' m=1\n' 

2851 ' n=1\n' 

2852 ' o=1\n' 

2853 ' p=1\n' 

2854 ' q=1\n' 

2855 ' r=1\n' 

2856 ' s=1\n' 

2857 ' t=1\n' 

2858 ' u=1\n' 

2859 ' v=1\n' 

2860 ' w=1\n' 

2861 ' x=1\n' 

2862 ' y=1\n' 

2863 ' x=1\n' 

2864 '\n' 

2865 ), 

2866 (2, 'f', 

2867 'def f(self):\n' 

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

2869 '\\\\-4.dummy2\n' 

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

2871 ) 

2872 ] 

2873 p = self.run_test(txt) 

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

2875 assert ok, msg 

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

2877 def check_outline(self, p, nodes): 

2878 it = iter(nodes) 

2879 zlev = p.level() 

2880 for p1 in p.self_and_subtree(): 

2881 lev, h, b = next(it) 

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

2883 if lev > 0: 

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

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

2886 try: 

2887 next(it) 

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

2889 except StopIteration: 

2890 return True, 'ok' 

2891 #@-others 

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

2893class TestRst(BaseTestImporter): 

2894 

2895 ext = '.rst' 

2896 treeType = '@auto-rst' 

2897 

2898 #@+others 

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

2900 def test_rst_1(self): 

2901 

2902 try: 

2903 import docutils 

2904 assert docutils 

2905 except Exception: # pragma: no cover 

2906 self.skipTest('no docutils') 

2907 

2908 s = """ 

2909 .. toc 

2910 

2911 ==== 

2912 top 

2913 ==== 

2914 

2915 The top section 

2916 

2917 section 1 

2918 --------- 

2919 

2920 section 1, line 1 

2921 -- 

2922 section 1, line 2 

2923 

2924 section 2 

2925 --------- 

2926 

2927 section 2, line 1 

2928 

2929 section 2.1 

2930 ~~~~~~~~~~~ 

2931 

2932 section 2.1, line 1 

2933 

2934 section 2.1.1 

2935 ............. 

2936 

2937 section 2.2.1 line 1 

2938 

2939 section 3 

2940 --------- 

2941 

2942 section 3, line 1 

2943 

2944 section 3.1.1 

2945 ............. 

2946 

2947 section 3.1.1, line 1 

2948 """ 

2949 p = self.run_test(s) 

2950 self.check_headlines(p, ( 

2951 (1, '!Dummy chapter'), 

2952 (1, 'top'), 

2953 (1, 'section 1'), 

2954 (1, 'section 2'), 

2955 (2, 'section 2.1'), 

2956 (3, 'section 2.1.1'), 

2957 (1, 'section 3'), 

2958 (2, 'placeholder'), 

2959 (3, 'section 3.1.1'), 

2960 )) 

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

2962 def test_simple(self): 

2963 

2964 try: 

2965 import docutils 

2966 assert docutils 

2967 except Exception: # pragma: no cover 

2968 self.skipTest('no docutils') 

2969 

2970 s = """ 

2971 .. toc 

2972 

2973 .. The section name contains trailing whitespace. 

2974 

2975 ======= 

2976 Chapter 

2977 ======= 

2978 

2979 The top chapter. 

2980 """ 

2981 p = self.run_test(s) 

2982 self.check_headlines(p, ( 

2983 (1, "!Dummy chapter"), 

2984 (1, "Chapter"), 

2985 )) 

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

2987 def test_no_double_underlines(self): 

2988 

2989 try: 

2990 import docutils 

2991 assert docutils 

2992 except Exception: # pragma: no cover 

2993 self.skipTest('no docutils') 

2994 

2995 s = """ 

2996 .. toc 

2997 

2998 top 

2999 ==== 

3000 

3001 The top section 

3002 

3003 section 1 

3004 --------- 

3005 

3006 section 1, line 1 

3007 -- 

3008 section 1, line 2 

3009 

3010 section 2 

3011 --------- 

3012 

3013 section 2, line 1 

3014 

3015 section 2.1 

3016 ~~~~~~~~~~~ 

3017 

3018 section 2.1, line 1 

3019 

3020 section 2.1.1 

3021 ............. 

3022 

3023 section 2.2.1 line 1 

3024 

3025 section 3 

3026 --------- 

3027 

3028 section 3, line 1 

3029 

3030 section 3.1.1 

3031 ............. 

3032 

3033 section 3.1.1, line 1 

3034 """ 

3035 p = self.run_test(s) 

3036 self.check_headlines(p, ( 

3037 (1, '!Dummy chapter'), 

3038 (1, 'top'), 

3039 (1, 'section 1'), 

3040 (1, 'section 2'), 

3041 (2, 'section 2.1'), 

3042 (3, 'section 2.1.1'), 

3043 (1, 'section 3'), 

3044 (2, 'placeholder'), 

3045 (3, 'section 3.1.1'), 

3046 )) 

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

3048 def test_long_underlines(self): 

3049 

3050 try: 

3051 import docutils 

3052 assert docutils 

3053 except Exception: # pragma: no cover 

3054 self.skipTest('no docutils') 

3055 

3056 s = """ 

3057 .. toc 

3058 

3059 top 

3060 ------------- 

3061 

3062 The top section 

3063 """ 

3064 p = self.run_test(s) 

3065 self.check_headlines(p, ( 

3066 (1, '!Dummy chapter'), 

3067 (1, 'top'), 

3068 )) 

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

3070 def test_test_long_overlines(self): 

3071 

3072 try: 

3073 import docutils 

3074 assert docutils 

3075 except Exception: # pragma: no cover 

3076 self.skipTest('no docutils') 

3077 

3078 s = """ 

3079 .. toc 

3080 

3081 ====== 

3082 top 

3083 ====== 

3084 

3085 The top section 

3086 """ 

3087 p = self.run_test(s) 

3088 self.check_headlines(p, ( 

3089 (1, "!Dummy chapter"), 

3090 (1, "top"), 

3091 )) 

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

3093 def test_trailing_whitespace(self): 

3094 

3095 try: 

3096 import docutils 

3097 assert docutils 

3098 except Exception: # pragma: no cover 

3099 self.skipTest('no docutils') 

3100 

3101 s = """ 

3102 .. toc 

3103 

3104 .. The section name contains trailing whitespace. 

3105 

3106 ====== 

3107 top 

3108 ====== 

3109 

3110 The top section. 

3111 """ 

3112 p = self.run_test(s) 

3113 self.check_headlines(p, ( 

3114 (1, "!Dummy chapter"), 

3115 (1, "top"), 

3116 )) 

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

3118 def test_leo_rst(self): 

3119 

3120 try: 

3121 import docutils 

3122 assert docutils 

3123 except Exception: # pragma: no cover 

3124 self.skipTest('no docutils') 

3125 

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

3127 s = """\ 

3128 ######### 

3129 Chapter 1 

3130 ######### 

3131 

3132 It was a dark and stormy night. 

3133 

3134 section 1 

3135 +++++++++ 

3136 

3137 Sec 1. 

3138 

3139 section 2 

3140 +++++++++ 

3141 

3142 Sec 2. 

3143 """ 

3144 p = self.run_test(s) 

3145 self.check_headlines(p, ( 

3146 (1, 'Chapter 1'), 

3147 (2, 'section 1'), 

3148 (2, 'section 2'), 

3149 )) 

3150 #@-others 

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

3152class TestTypescript(BaseTestImporter): 

3153 

3154 ext = '.ts' 

3155 

3156 #@+others 

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

3158 def test_class(self): 

3159 

3160 s = ''' 

3161 class Greeter { 

3162 greeting: string; 

3163 constructor (message: string) { 

3164 this.greeting = message; 

3165 } 

3166 greet() { 

3167 return "Hello, " + this.greeting; 

3168 } 

3169 } 

3170  

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

3172  

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

3174 button.innerText = "Say Hello" 

3175 button.onclick = function() { 

3176 alert(greeter.greet()) 

3177 } 

3178  

3179 document.body.appendChild(button) 

3180 

3181 ''' 

3182 self.run_test(s) 

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

3184 def test_module(self): 

3185 s = ''' 

3186 module Sayings { 

3187 export class Greeter { 

3188 greeting: string; 

3189 constructor (message: string) { 

3190 this.greeting = message; 

3191 } 

3192 greet() { 

3193 return "Hello, " + this.greeting; 

3194 } 

3195 } 

3196 } 

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

3198 

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

3200 button.innerText = "Say Hello" 

3201 button.onclick = function() { 

3202 alert(greeter.greet()) 

3203 } 

3204 

3205 document.body.appendChild(button) 

3206 ''' 

3207 self.run_test(s) 

3208 #@-others 

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

3210class TestXML(BaseTestImporter): 

3211 

3212 ext = '.xml' 

3213 

3214 def setUp(self): 

3215 super().setUp() 

3216 c = self.c 

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

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

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

3220 c.config.settingsDict = settingsDict 

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

3222 

3223 #@+others 

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

3225 def test_standard_opening_elements(self): 

3226 c = self.c 

3227 s = """ 

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

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

3230 <html> 

3231 <head> 

3232 <title>Bodystring</title> 

3233 </head> 

3234 <body class='bodystring'> 

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

3236 </body> 

3237 </html> 

3238 """ 

3239 table = ( 

3240 (1, "<html>"), 

3241 (2, "<head>"), 

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

3243 ) 

3244 p = c.p 

3245 self.run_test(s) 

3246 after = p.nodeAfterTree() 

3247 root = p.lastChild() 

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

3249 p = root.firstChild() 

3250 for n, h in table: 

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

3252 self.assertEqual(h, p.h) 

3253 self.assertEqual(n, n2) 

3254 p.moveToThreadNext() 

3255 self.assertEqual(p, after) 

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

3257 def test_xml_11(self): 

3258 

3259 s = """ 

3260 <html> 

3261 <head> 

3262 <title>Bodystring</title> 

3263 </head> 

3264 <body class='bodystring'> 

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

3266 </body> 

3267 </html> 

3268 """ 

3269 p = self.run_test(s) 

3270 self.check_headlines(p, ( 

3271 (1, "<html>"), 

3272 (2, "<head>"), 

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

3274 )) 

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

3276 def test_non_ascii_tags(self): 

3277 s = """ 

3278 <:À.Ç> 

3279 <Ì> 

3280 <_.ÌÑ> 

3281 """ 

3282 self.run_test(s) 

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

3284 def test_is_ws_line(self): 

3285 c = self.c 

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

3287 table = ( 

3288 (1, ' \n'), 

3289 (1, '\n'), 

3290 (1, ' '), 

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

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

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

3294 (0, 'Help'), 

3295 ) 

3296 for expected, line in table: 

3297 got = x.is_ws_line(line) 

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

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

3300 def test_scan_line(self): 

3301 c = self.c 

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

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

3304 table = ( 

3305 (0, '<tag>'), 

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

3307 (1, '<html'), 

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

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

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

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

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

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

3314 ) 

3315 for level, line in table: 

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

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

3318 new_state = x.scan_line(line, prev_state) 

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

3320 #@-others 

3321#@-others 

3322 

3323 

3324#@-leo