From bde31306de4ff2b6e4945683e5deb821c85984e8 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 14 Dec 2019 06:14:16 -0500 Subject: Sample html report for 5.0 --- doc/sample_html/cogapp___init___py.html | 65 +- doc/sample_html/cogapp___main___py.html | 53 +- doc/sample_html/cogapp_backward_py.html | 138 +- doc/sample_html/cogapp_cogapp_py.html | 2414 +++----- doc/sample_html/cogapp_makefiles_py.html | 216 +- doc/sample_html/cogapp_test_cogapp_py.html | 6966 +++++++++--------------- doc/sample_html/cogapp_test_makefiles_py.html | 350 +- doc/sample_html/cogapp_test_whiteutils_py.html | 347 +- doc/sample_html/cogapp_whiteutils_py.html | 257 +- doc/sample_html/coverage_html.js | 122 +- doc/sample_html/index.html | 122 +- doc/sample_html/status.json | 2 +- doc/sample_html/style.css | 489 +- 13 files changed, 3975 insertions(+), 7566 deletions(-) (limited to 'doc/sample_html') diff --git a/doc/sample_html/cogapp___init___py.html b/doc/sample_html/cogapp___init___py.html index da8d9c55..eae3c3a9 100644 --- a/doc/sample_html/cogapp___init___py.html +++ b/doc/sample_html/cogapp___init___py.html @@ -1,16 +1,10 @@ - - - - - Coverage for cogapp/__init__.py: 100.00% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,46 +51,24 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

- -
-

""" Cog code generation tool. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

 

-

from .cogapp import * 

- -
+

1""" Cog content generation tool. 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2015, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9from .cogapp import * 

- - diff --git a/doc/sample_html/cogapp___main___py.html b/doc/sample_html/cogapp___main___py.html index 0306c9d6..9a3d885a 100644 --- a/doc/sample_html/cogapp___main___py.html +++ b/doc/sample_html/cogapp___main___py.html @@ -1,16 +1,10 @@ - - - - - Coverage for cogapp/__main__.py: 0.00% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,38 +51,20 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

- -
-

"""Make Cog runnable directly from the module.""" 

-

import sys 

-

from cogapp import Cog 

-

 

-

sys.exit(Cog().main(sys.argv)) 

- -
+

1"""Make Cog runnable directly from the module.""" 

+

2import sys 

+

3from cogapp import Cog 

+

4 

+

5sys.exit(Cog().main(sys.argv)) 

- - diff --git a/doc/sample_html/cogapp_backward_py.html b/doc/sample_html/cogapp_backward_py.html index 0b672d55..7a1468e7 100644 --- a/doc/sample_html/cogapp_backward_py.html +++ b/doc/sample_html/cogapp_backward_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/backward.py: 57.14% + Coverage for cogapp/backward.py: 69.23% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,80 +51,57 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

- -
-

"""Compatibility between Py2 and Py3.""" 

-

 

-

import sys 

-

 

-

PY3 = sys.version_info[0] == 3 

-

 

-

7 ↛ 8line 7 didn't jump to line 8, because the condition on line 7 was never trueif PY3: 

-

string_types = (str,bytes) 

-

bytes_types = (bytes,) 

-

def b(s): 

-

return s.encode("latin-1") 

-

def to_bytes(s): 

-

return s.encode('utf8') 

-

else: 

-

string_types = (basestring,) 

-

bytes_types = (str,) 

-

def b(s): 

-

return s 

-

def to_bytes(s): 

-

return s 

-

 

-

# Pythons 2 and 3 differ on where to get StringIO 

-

try: 

-

from cStringIO import StringIO 

-

except ImportError: 

-

from io import StringIO 

- -
+

1"""Compatibility between Py2 and Py3.""" 

+

2 

+

3import sys 

+

4import unittest 

+

5 

+

6PY3 = sys.version_info[0] == 3 

+

7 

+

8if PY3: 8 ↛ 14line 8 didn't jump to line 14, because the condition on line 8 was never false

+

9 string_types = (str,bytes) 

+

10 bytes_types = (bytes,) 

+

11 def to_bytes(s): 

+

12 return s.encode('utf8') 

+

13else: 

+

14 string_types = (basestring,) 

+

15 bytes_types = (str,) 

+

16 def to_bytes(s): 

+

17 return s 

+

18 

+

19# Pythons 2 and 3 differ on where to get StringIO 

+

20try: 

+

21 from cStringIO import StringIO 

+

22except ImportError: 

+

23 from io import StringIO 

+

24 

+

25 

+

26def unittest_has(method): 

+

27 """Does `unittest.TestCase` have `method` defined?""" 

+

28 return hasattr(unittest.TestCase, method) 

+

29 

+

30 

+

31class TestCase(unittest.TestCase): 

+

32 """Just like unittest.TestCase, but with assert methods added. 

+

33 

+

34 Designed to be compatible with 3.1 unittest. Methods are only defined if 

+

35 `unittest` doesn't have them. 

+

36 

+

37 """ 

+

38 # pylint: disable=missing-docstring 

+

39 

+

40 if not unittest_has('assertRaisesRegex'): 40 ↛ 41line 40 didn't jump to line 41, because the condition on line 40 was never true

+

41 def assertRaisesRegex(self, *args, **kwargs): 

+

42 return self.assertRaisesRegexp(*args, **kwargs) 

- - diff --git a/doc/sample_html/cogapp_cogapp_py.html b/doc/sample_html/cogapp_cogapp_py.html index 75f1d086..57732e57 100644 --- a/doc/sample_html/cogapp_cogapp_py.html +++ b/doc/sample_html/cogapp_cogapp_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/cogapp.py: 98.84% + Coverage for cogapp/cogapp.py: 49.34% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,1590 +51,823 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

-

533

-

534

-

535

-

536

-

537

-

538

-

539

-

540

-

541

-

542

-

543

-

544

-

545

-

546

-

547

-

548

-

549

-

550

-

551

-

552

-

553

-

554

-

555

-

556

-

557

-

558

-

559

-

560

-

561

-

562

-

563

-

564

-

565

-

566

-

567

-

568

-

569

-

570

-

571

-

572

-

573

-

574

-

575

-

576

-

577

-

578

-

579

-

580

-

581

-

582

-

583

-

584

-

585

-

586

-

587

-

588

-

589

-

590

-

591

-

592

-

593

-

594

-

595

-

596

-

597

-

598

-

599

-

600

-

601

-

602

-

603

-

604

-

605

-

606

-

607

-

608

-

609

-

610

-

611

-

612

-

613

-

614

-

615

-

616

-

617

-

618

-

619

-

620

-

621

-

622

-

623

-

624

-

625

-

626

-

627

-

628

-

629

-

630

-

631

-

632

-

633

-

634

-

635

-

636

-

637

-

638

-

639

-

640

-

641

-

642

-

643

-

644

-

645

-

646

-

647

-

648

-

649

-

650

-

651

-

652

-

653

-

654

-

655

-

656

-

657

-

658

-

659

-

660

-

661

-

662

-

663

-

664

-

665

-

666

-

667

-

668

-

669

-

670

-

671

-

672

-

673

-

674

-

675

-

676

-

677

-

678

-

679

-

680

-

681

-

682

-

683

-

684

-

685

-

686

-

687

-

688

-

689

-

690

-

691

-

692

-

693

-

694

-

695

-

696

-

697

-

698

-

699

-

700

-

701

-

702

-

703

-

704

-

705

-

706

-

707

-

708

-

709

-

710

-

711

-

712

-

713

-

714

-

715

-

716

-

717

-

718

-

719

-

720

-

721

-

722

-

723

-

724

-

725

-

726

-

727

-

728

-

729

-

730

-

731

-

732

-

733

-

734

-

735

-

736

-

737

-

738

-

739

-

740

-

741

-

742

-

743

-

744

-

745

-

746

-

747

-

748

-

749

-

750

-

751

-

752

-

753

-

754

-

755

-

756

-

757

-

758

-

759

-

760

-

761

-

762

-

763

-

764

-

765

-

766

-

767

-

768

-

769

-

770

-

771

-

772

-

773

-

774

-

775

-

776

-

777

-

778

-

779

-

780

-

781

- -
-

# coding: utf8 

-

""" Cog code generation tool. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2016, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import, print_function 

-

 

-

import copy, getopt, hashlib, imp, os, re, shlex, sys, traceback 

-

from .backward import PY3, StringIO, string_types, to_bytes 

-

 

-

__all__ = ['Cog', 'CogUsageError'] 

-

 

-

__version__ = '2.5.1' # History at the end of the file. 

-

 

-

usage = """\ 

-

cog - generate code with inlined Python code. 

-

 

-

cog [OPTIONS] [INFILE | @FILELIST] ... 

-

 

-

INFILE is the name of an input file, '-' will read from stdin. 

-

FILELIST is the name of a text file containing file names or 

-

other @FILELISTs. 

-

 

-

OPTIONS: 

-

-c Checksum the output to protect it against accidental change. 

-

-d Delete the generator code from the output file. 

-

-D name=val Define a global string available to your generator code. 

-

-e Warn if a file has no cog code in it. 

-

-I PATH Add PATH to the list of directories for data files and modules. 

-

-n ENCODING Use ENCODING when reading and writing files. 

-

-o OUTNAME Write the output to OUTNAME. 

-

-r Replace the input file with the output. 

-

-s STRING Suffix all generated output lines with STRING. 

-

-U Write the output with Unix newlines (only LF line-endings). 

-

-w CMD Use CMD if the output file needs to be made writable. 

-

A %s in the CMD will be filled with the filename. 

-

-x Excise all the generated output without running the generators. 

-

-z The end-output marker can be omitted, and is assumed at eof. 

-

-v Print the version of cog and exit. 

-

--verbosity=VERBOSITY 

-

Control the amount of output. 2 (the default) lists all files, 

-

1 lists only changed files, 0 lists no files. 

-

--markers='START END END-OUTPUT' 

-

The patterns surrounding cog inline instructions. Should 

-

include three values separated by spaces, the start, end, 

-

and end-output markers. Defaults to '[[[cog ]]] [[[end]]]'. 

-

-h Print this help. 

-

""" 

-

 

-

# Other package modules 

-

from .whiteutils import * 

-

 

-

class CogError(Exception): 

-

""" Any exception raised by Cog. 

-

""" 

-

def __init__(self, msg, file='', line=0): 

-

if file: 

-

Exception.__init__(self, "%s(%d): %s" % (file, line, msg)) 

-

else: 

-

Exception.__init__(self, msg) 

-

 

-

class CogUsageError(CogError): 

-

""" An error in usage of command-line arguments in cog. 

-

""" 

-

pass #pragma: no cover 

-

 

-

class CogInternalError(CogError): 

-

""" An error in the coding of Cog. Should never happen. 

-

""" 

-

pass #pragma: no cover 

-

 

-

class CogGeneratedError(CogError): 

-

""" An error raised by a user's cog generator. 

-

""" 

-

pass #pragma: no cover 

-

 

-

class Redirectable: 

-

""" An object with its own stdout and stderr files. 

-

""" 

-

def __init__(self): 

-

self.stdout = sys.stdout 

-

self.stderr = sys.stderr 

-

 

-

def setOutput(self, stdout=None, stderr=None): 

-

""" Assign new files for standard out and/or standard error. 

-

""" 

-

if stdout: 

-

self.stdout = stdout 

-

if stderr: 

-

self.stderr = stderr 

-

 

-

def prout(self, s, end="\n"): 

-

print(s, file=self.stdout, end=end) 

-

 

-

def prerr(self, s, end="\n"): 

-

print(s, file=self.stderr, end=end) 

-

 

-

 

-

class CogGenerator(Redirectable): 

-

""" A generator pulled from a source file. 

-

""" 

-

def __init__(self): 

-

Redirectable.__init__(self) 

-

self.markers = [] 

-

self.lines = [] 

-

 

-

def parseMarker(self, l): 

-

self.markers.append(l) 

-

 

-

def parseLine(self, l): 

-

self.lines.append(l.strip('\n')) 

-

 

-

def getCode(self): 

-

""" Extract the executable Python code from the generator. 

-

""" 

-

# If the markers and lines all have the same prefix 

-

# (end-of-line comment chars, for example), 

-

# then remove it from all the lines. 

-

prefIn = commonPrefix(self.markers + self.lines) 

-

if prefIn: 

-

self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ] 

-

self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ] 

-

 

-

return reindentBlock(self.lines, '') 

-

 

-

def evaluate(self, cog, globals, fname='cog generator'): 

-

# figure out the right whitespace prefix for the output 

-

prefOut = whitePrefix(self.markers) 

-

 

-

intext = self.getCode() 

-

if not intext: 

-

return '' 

-

 

-

# In Python 2.2, the last line has to end in a newline. 

-

intext = "import cog\n" + intext + "\n" 

-

code = compile(intext, str(fname), 'exec') 

-

 

-

# Make sure the "cog" module has our state. 

-

cog.cogmodule.msg = self.msg 

-

cog.cogmodule.out = self.out 

-

cog.cogmodule.outl = self.outl 

-

cog.cogmodule.error = self.error 

-

 

-

self.outstring = '' 

-

eval(code, globals) 

-

 

-

# We need to make sure that the last line in the output 

-

# ends with a newline, or it will be joined to the 

-

# end-output line, ruining cog's idempotency. 

-

if self.outstring and self.outstring[-1] != '\n': 

-

self.outstring += '\n' 

-

 

-

return reindentBlock(self.outstring, prefOut) 

-

 

-

def msg(self, s): 

-

self.prout("Message: "+s) 

-

 

-

def out(self, sOut='', dedent=False, trimblanklines=False): 

-

""" The cog.out function. 

-

""" 

-

if trimblanklines and ('\n' in sOut): 

-

lines = sOut.split('\n') 

-

if lines[0].strip() == '': 

-

del lines[0] 

-

167 ↛ 169line 167 didn't jump to line 169, because the condition on line 167 was never false if lines and lines[-1].strip() == '': 

-

del lines[-1] 

-

sOut = '\n'.join(lines)+'\n' 

-

if dedent: 

-

sOut = reindentBlock(sOut) 

-

self.outstring += sOut 

-

 

-

def outl(self, sOut='', **kw): 

-

""" The cog.outl function. 

-

""" 

-

self.out(sOut, **kw) 

-

self.out('\n') 

-

 

-

def error(self, msg='Error raised by cog generator.'): 

-

""" The cog.error function. 

-

Instead of raising standard python errors, cog generators can use 

-

this function. It will display the error without a scary Python 

-

traceback. 

-

""" 

-

raise CogGeneratedError(msg) 

-

 

-

 

-

class NumberedFileReader: 

-

""" A decorator for files that counts the readline()'s called. 

-

""" 

-

def __init__(self, f): 

-

self.f = f 

-

self.n = 0 

-

 

-

def readline(self): 

-

l = self.f.readline() 

-

if l: 

-

self.n += 1 

-

return l 

-

 

-

def linenumber(self): 

-

return self.n 

-

 

-

 

-

class CogOptions: 

-

""" Options for a run of cog. 

-

""" 

-

def __init__(self): 

-

# Defaults for argument values. 

-

self.args = [] 

-

self.includePath = [] 

-

self.defines = {} 

-

self.bShowVersion = False 

-

self.sMakeWritableCmd = None 

-

self.bReplace = False 

-

self.bNoGenerate = False 

-

self.sOutputName = None 

-

self.bWarnEmpty = False 

-

self.bHashOutput = False 

-

self.bDeleteCode = False 

-

self.bEofCanBeEnd = False 

-

self.sSuffix = None 

-

self.bNewlines = False 

-

self.sBeginSpec = '[[[cog' 

-

self.sEndSpec = ']]]' 

-

self.sEndOutput = '[[[end]]]' 

-

self.sEncoding = "utf-8" 

-

self.verbosity = 2 

-

 

-

def __eq__(self, other): 

-

""" Comparison operator for tests to use. 

-

""" 

-

return self.__dict__ == other.__dict__ 

-

 

-

def clone(self): 

-

""" Make a clone of these options, for further refinement. 

-

""" 

-

return copy.deepcopy(self) 

-

 

-

def addToIncludePath(self, dirs): 

-

""" Add directories to the include path. 

-

""" 

-

dirs = dirs.split(os.pathsep) 

-

self.includePath.extend(dirs) 

-

 

-

def parseArgs(self, argv): 

-

# Parse the command line arguments. 

-

try: 

-

opts, self.args = getopt.getopt( 

-

argv, 

-

'cdD:eI:n:o:rs:Uvw:xz', 

-

[ 

-

'markers=', 

-

'verbosity=', 

-

] 

-

) 

-

except getopt.error as msg: 

-

raise CogUsageError(msg) 

-

 

-

# Handle the command line arguments. 

-

for o, a in opts: 

-

if o == '-c': 

-

self.bHashOutput = True 

-

elif o == '-d': 

-

self.bDeleteCode = True 

-

elif o == '-D': 

-

if a.count('=') < 1: 

-

raise CogUsageError("-D takes a name=value argument") 

-

name, value = a.split('=', 1) 

-

self.defines[name] = value 

-

elif o == '-e': 

-

self.bWarnEmpty = True 

-

elif o == '-I': 

-

self.addToIncludePath(a) 

-

elif o == '-n': 

-

self.sEncoding = a 

-

elif o == '-o': 

-

self.sOutputName = a 

-

elif o == '-r': 

-

self.bReplace = True 

-

elif o == '-s': 

-

self.sSuffix = a 

-

elif o == '-U': 

-

self.bNewlines = True 

-

elif o == '-v': 

-

self.bShowVersion = True 

-

elif o == '-w': 

-

self.sMakeWritableCmd = a 

-

elif o == '-x': 

-

self.bNoGenerate = True 

-

elif o == '-z': 

-

self.bEofCanBeEnd = True 

-

elif o == '--markers': 

-

self._parse_markers(a) 

-

elif o == '--verbosity': 

-

self.verbosity = int(a) 

-

else: 

-

# Since getopt.getopt is given a list of possible flags, 

-

# this is an internal error. 

-

raise CogInternalError("Don't understand argument %s" % o) 

-

 

-

def _parse_markers(self, val): 

-

try: 

-

self.sBeginSpec, self.sEndSpec, self.sEndOutput = val.split(' ') 

-

except ValueError: 

-

raise CogUsageError( 

-

'--markers requires 3 values separated by spaces, could not parse %r' % val 

-

) 

-

 

-

def validate(self): 

-

""" Does nothing if everything is OK, raises CogError's if it's not. 

-

""" 

-

if self.bReplace and self.bDeleteCode: 

-

raise CogUsageError("Can't use -d with -r (or you would delete all your source!)") 

-

 

-

if self.bReplace and self.sOutputName: 

-

raise CogUsageError("Can't use -o with -r (they are opposites)") 

-

 

-

 

-

class Cog(Redirectable): 

-

""" The Cog engine. 

-

""" 

-

def __init__(self): 

-

Redirectable.__init__(self) 

-

self.options = CogOptions() 

-

self._fixEndOutputPatterns() 

-

self.installCogModule() 

-

 

-

def _fixEndOutputPatterns(self): 

-

end_output = re.escape(self.options.sEndOutput) 

-

self.reEndOutput = re.compile(end_output + r'(?P<hashsect> *\(checksum: (?P<hash>[a-f0-9]+)\))') 

-

self.sEndFormat = self.options.sEndOutput + ' (checksum: %s)' 

-

 

-

def showWarning(self, msg): 

-

self.prout("Warning: "+msg) 

-

 

-

def isBeginSpecLine(self, s): 

-

return self.options.sBeginSpec in s 

-

 

-

def isEndSpecLine(self, s): 

-

return self.options.sEndSpec in s and not self.isEndOutputLine(s) 

-

 

-

def isEndOutputLine(self, s): 

-

return self.options.sEndOutput in s 

-

 

-

def installCogModule(self): 

-

""" Magic mumbo-jumbo so that imported Python modules 

-

can say "import cog" and get our state. 

-

""" 

-

self.cogmodule = imp.new_module('cog') 

-

self.cogmodule.path = [] 

-

sys.modules['cog'] = self.cogmodule 

-

 

-

def openOutputFile(self, fname): 

-

""" Open an output file, taking all the details into account. 

-

""" 

-

opts = {} 

-

mode = "w" 

-

360 ↛ 361line 360 didn't jump to line 361, because the condition on line 360 was never true if PY3: 

-

opts['encoding'] = self.options.sEncoding 

-

if self.options.bNewlines: 

-

363 ↛ 364line 363 didn't jump to line 364, because the condition on line 363 was never true if PY3: 

-

opts['newline'] = "\n" 

-

else: 

-

mode = "wb" 

-

fdir = os.path.dirname(fname) 

-

if os.path.dirname(fdir) and not os.path.exists(fdir): 

-

os.makedirs(fdir) 

-

return open(fname, mode, **opts) 

-

 

-

def openInputFile(self, fname): 

-

""" Open an input file. """ 

-

if fname == "-": 

-

return sys.stdin 

-

else: 

-

opts = {} 

-

378 ↛ 379line 378 didn't jump to line 379, because the condition on line 378 was never true if PY3: 

-

opts['encoding'] = self.options.sEncoding 

-

return open(fname, "r", **opts) 

-

 

-

def processFile(self, fIn, fOut, fname=None, globals=None): 

-

""" Process an input file object to an output file object. 

-

fIn and fOut can be file objects, or file names. 

-

""" 

-

 

-

sFileIn = fname or '' 

-

sFileOut = fname or '' 

-

fInToClose = fOutToClose = None 

-

# Convert filenames to files. 

-

if isinstance(fIn, string_types): 

-

# Open the input file. 

-

sFileIn = fIn 

-

fIn = fInToClose = self.openInputFile(fIn) 

-

if isinstance(fOut, string_types): 

-

# Open the output file. 

-

sFileOut = fOut 

-

fOut = fOutToClose = self.openOutputFile(fOut) 

-

 

-

try: 

-

fIn = NumberedFileReader(fIn) 

-

 

-

bSawCog = False 

-

 

-

self.cogmodule.inFile = sFileIn 

-

self.cogmodule.outFile = sFileOut 

-

 

-

# The globals dict we'll use for this file. 

-

if globals is None: 

-

globals = {} 

-

 

-

# If there are any global defines, put them in the globals. 

-

globals.update(self.options.defines) 

-

 

-

# loop over generator chunks 

-

l = fIn.readline() 

-

while l: 

-

# Find the next spec begin 

-

while l and not self.isBeginSpecLine(l): 

-

if self.isEndSpecLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sEndSpec, 

-

file=sFileIn, line=fIn.linenumber()) 

-

if self.isEndOutputLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sEndOutput, 

-

file=sFileIn, line=fIn.linenumber()) 

-

fOut.write(l) 

-

l = fIn.readline() 

-

if not l: 

-

break 

-

if not self.options.bDeleteCode: 

-

fOut.write(l) 

-

 

-

# l is the begin spec 

-

gen = CogGenerator() 

-

gen.setOutput(stdout=self.stdout) 

-

gen.parseMarker(l) 

-

firstLineNum = fIn.linenumber() 

-

self.cogmodule.firstLineNum = firstLineNum 

-

 

-

# If the spec begin is also a spec end, then process the single 

-

# line of code inside. 

-

if self.isEndSpecLine(l): 

-

beg = l.find(self.options.sBeginSpec) 

-

end = l.find(self.options.sEndSpec) 

-

if beg > end: 

-

raise CogError("Cog code markers inverted", 

-

file=sFileIn, line=firstLineNum) 

-

else: 

-

sCode = l[beg+len(self.options.sBeginSpec):end].strip() 

-

gen.parseLine(sCode) 

-

else: 

-

# Deal with an ordinary code block. 

-

l = fIn.readline() 

-

 

-

# Get all the lines in the spec 

-

while l and not self.isEndSpecLine(l): 

-

if self.isBeginSpecLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sBeginSpec, 

-

file=sFileIn, line=fIn.linenumber()) 

-

if self.isEndOutputLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sEndOutput, 

-

file=sFileIn, line=fIn.linenumber()) 

-

if not self.options.bDeleteCode: 

-

fOut.write(l) 

-

gen.parseLine(l) 

-

l = fIn.readline() 

-

if not l: 

-

raise CogError( 

-

"Cog block begun but never ended.", 

-

file=sFileIn, line=firstLineNum) 

-

 

-

if not self.options.bDeleteCode: 

-

fOut.write(l) 

-

gen.parseMarker(l) 

-

 

-

l = fIn.readline() 

-

 

-

# Eat all the lines in the output section. While reading past 

-

# them, compute the md5 hash of the old output. 

-

previous = "" 

-

hasher = hashlib.md5() 

-

while l and not self.isEndOutputLine(l): 

-

if self.isBeginSpecLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sBeginSpec, 

-

file=sFileIn, line=fIn.linenumber()) 

-

if self.isEndSpecLine(l): 

-

raise CogError("Unexpected '%s'" % self.options.sEndSpec, 

-

file=sFileIn, line=fIn.linenumber()) 

-

previous += l 

-

hasher.update(to_bytes(l)) 

-

l = fIn.readline() 

-

curHash = hasher.hexdigest() 

-

 

-

if not l and not self.options.bEofCanBeEnd: 

-

# We reached end of file before we found the end output line. 

-

raise CogError("Missing '%s' before end of file." % self.options.sEndOutput, 

-

file=sFileIn, line=fIn.linenumber()) 

-

 

-

# Make the previous output available to the current code 

-

self.cogmodule.previous = previous 

-

 

-

# Write the output of the spec to be the new output if we're 

-

# supposed to generate code. 

-

hasher = hashlib.md5() 

-

if not self.options.bNoGenerate: 

-

sFile = "%s+%d" % (sFileIn, firstLineNum) 

-

sGen = gen.evaluate(cog=self, globals=globals, fname=sFile) 

-

sGen = self.suffixLines(sGen) 

-

hasher.update(to_bytes(sGen)) 

-

fOut.write(sGen) 

-

newHash = hasher.hexdigest() 

-

 

-

bSawCog = True 

-

 

-

# Write the ending output line 

-

hashMatch = self.reEndOutput.search(l) 

-

if self.options.bHashOutput: 

-

if hashMatch: 

-

oldHash = hashMatch.groupdict()['hash'] 

-

if oldHash != curHash: 

-

raise CogError("Output has been edited! Delete old checksum to unprotect.", 

-

file=sFileIn, line=fIn.linenumber()) 

-

# Create a new end line with the correct hash. 

-

endpieces = l.split(hashMatch.group(0), 1) 

-

else: 

-

# There was no old hash, but we want a new hash. 

-

endpieces = l.split(self.options.sEndOutput, 1) 

-

l = (self.sEndFormat % newHash).join(endpieces) 

-

else: 

-

# We don't want hashes output, so if there was one, get rid of 

-

# it. 

-

if hashMatch: 

-

l = l.replace(hashMatch.groupdict()['hashsect'], '', 1) 

-

 

-

if not self.options.bDeleteCode: 

-

fOut.write(l) 

-

l = fIn.readline() 

-

 

-

if not bSawCog and self.options.bWarnEmpty: 

-

self.showWarning("no cog code found in %s" % sFileIn) 

-

finally: 

-

if fInToClose: 

-

fInToClose.close() 

-

if fOutToClose: 

-

fOutToClose.close() 

-

 

-

 

-

# A regex for non-empty lines, used by suffixLines. 

-

reNonEmptyLines = re.compile("^\s*\S+.*$", re.MULTILINE) 

-

 

-

def suffixLines(self, text): 

-

""" Add suffixes to the lines in text, if our options desire it. 

-

text is many lines, as a single string. 

-

""" 

-

if self.options.sSuffix: 

-

# Find all non-blank lines, and add the suffix to the end. 

-

repl = r"\g<0>" + self.options.sSuffix.replace('\\', '\\\\') 

-

text = self.reNonEmptyLines.sub(repl, text) 

-

return text 

-

 

-

def processString(self, sInput, fname=None): 

-

""" Process sInput as the text to cog. 

-

Return the cogged output as a string. 

-

""" 

-

fOld = StringIO(sInput) 

-

fNew = StringIO() 

-

self.processFile(fOld, fNew, fname=fname) 

-

return fNew.getvalue() 

-

 

-

def replaceFile(self, sOldPath, sNewText): 

-

""" Replace file sOldPath with the contents sNewText 

-

""" 

-

if not os.access(sOldPath, os.W_OK): 

-

# Need to ensure we can write. 

-

if self.options.sMakeWritableCmd: 

-

# Use an external command to make the file writable. 

-

cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath) 

-

self.stdout.write(os.popen(cmd).read()) 

-

if not os.access(sOldPath, os.W_OK): 

-

raise CogError("Couldn't make %s writable" % sOldPath) 

-

else: 

-

# Can't write! 

-

raise CogError("Can't overwrite %s" % sOldPath) 

-

f = self.openOutputFile(sOldPath) 

-

f.write(sNewText) 

-

f.close() 

-

 

-

def saveIncludePath(self): 

-

self.savedInclude = self.options.includePath[:] 

-

self.savedSysPath = sys.path[:] 

-

 

-

def restoreIncludePath(self): 

-

self.options.includePath = self.savedInclude 

-

self.cogmodule.path = self.options.includePath 

-

sys.path = self.savedSysPath 

-

 

-

def addToIncludePath(self, includePath): 

-

self.cogmodule.path.extend(includePath) 

-

sys.path.extend(includePath) 

-

 

-

def processOneFile(self, sFile): 

-

""" Process one filename through cog. 

-

""" 

-

 

-

self.saveIncludePath() 

-

bNeedNewline = False 

-

 

-

try: 

-

self.addToIncludePath(self.options.includePath) 

-

# Since we know where the input file came from, 

-

# push its directory onto the include path. 

-

self.addToIncludePath([os.path.dirname(sFile)]) 

-

 

-

# How we process the file depends on where the output is going. 

-

if self.options.sOutputName: 

-

self.processFile(sFile, self.options.sOutputName, sFile) 

-

elif self.options.bReplace: 

-

# We want to replace the cog file with the output, 

-

# but only if they differ. 

-

if self.options.verbosity >= 2: 

-

self.prout("Cogging %s" % sFile, end="") 

-

bNeedNewline = True 

-

 

-

try: 

-

fOldFile = self.openInputFile(sFile) 

-

sOldText = fOldFile.read() 

-

fOldFile.close() 

-

sNewText = self.processString(sOldText, fname=sFile) 

-

if sOldText != sNewText: 

-

if self.options.verbosity >= 1: 

-

if self.options.verbosity < 2: 

-

self.prout("Cogging %s" % sFile, end="") 

-

self.prout(" (changed)") 

-

bNeedNewline = False 

-

self.replaceFile(sFile, sNewText) 

-

finally: 

-

# The try-finally block is so we can print a partial line 

-

# with the name of the file, and print (changed) on the 

-

# same line, but also make sure to break the line before 

-

# any traceback. 

-

if bNeedNewline: 

-

self.prout("") 

-

else: 

-

self.processFile(sFile, self.stdout, sFile) 

-

finally: 

-

self.restoreIncludePath() 

-

 

-

def processFileList(self, sFileList): 

-

""" Process the files in a file list. 

-

""" 

-

flist = self.openInputFile(sFileList) 

-

lines = flist.readlines() 

-

flist.close() 

-

for l in lines: 

-

# Use shlex to parse the line like a shell. 

-

lex = shlex.shlex(l, posix=True) 

-

lex.whitespace_split = True 

-

lex.commenters = '#' 

-

# No escapes, so that backslash can be part of the path 

-

lex.escape = '' 

-

args = list(lex) 

-

if args: 

-

self.processArguments(args) 

-

 

-

def processArguments(self, args): 

-

""" Process one command-line. 

-

""" 

-

saved_options = self.options 

-

self.options = self.options.clone() 

-

 

-

self.options.parseArgs(args[1:]) 

-

self.options.validate() 

-

 

-

if args[0][0] == '@': 

-

if self.options.sOutputName: 

-

raise CogUsageError("Can't use -o with @file") 

-

self.processFileList(args[0][1:]) 

-

else: 

-

self.processOneFile(args[0]) 

-

 

-

self.options = saved_options 

-

 

-

def callableMain(self, argv): 

-

""" All of command-line cog, but in a callable form. 

-

This is used by main. 

-

argv is the equivalent of sys.argv. 

-

""" 

-

argv = argv[1:] 

-

 

-

# Provide help if asked for anywhere in the command line. 

-

if '-?' in argv or '-h' in argv: 

-

self.prerr(usage, end="") 

-

return 

-

 

-

self.options.parseArgs(argv) 

-

self.options.validate() 

-

self._fixEndOutputPatterns() 

-

 

-

if self.options.bShowVersion: 

-

self.prout("Cog version %s" % __version__) 

-

return 

-

 

-

if self.options.args: 

-

for a in self.options.args: 

-

self.processArguments([a]) 

-

else: 

-

raise CogUsageError("No files to process") 

-

 

-

def main(self, argv): 

-

""" Handle the command-line execution for cog. 

-

""" 

-

 

-

try: 

-

self.callableMain(argv) 

-

return 0 

-

except CogUsageError as err: 

-

self.prerr(err) 

-

self.prerr("(for help use -?)") 

-

return 2 

-

except CogGeneratedError as err: 

-

self.prerr("Error: %s" % err) 

-

return 3 

-

except CogError as err: 

-

self.prerr(err) 

-

return 1 

-

except: 

-

traceback.print_exc(None, self.stderr) 

-

return 1 

-

 

-

# History: 

-

# 20040210: First public version. 

-

# 20040220: Text preceding the start and end marker are removed from Python lines. 

-

# -v option on the command line shows the version. 

-

# 20040311: Make sure the last line of output is properly ended with a newline. 

-

# 20040605: Fixed some blank line handling in cog. 

-

# Fixed problems with assigning to xml elements in handyxml. 

-

# 20040621: Changed all line-ends to LF from CRLF. 

-

# 20041002: Refactor some option handling to simplify unittesting the options. 

-

# 20041118: cog.out and cog.outl have optional string arguments. 

-

# 20041119: File names weren't being properly passed around for warnings, etc. 

-

# 20041122: Added cog.firstLineNum: a property with the line number of the [[[cog line. 

-

# Added cog.inFile and cog.outFile: the names of the input and output file. 

-

# 20041218: Single-line cog generators, with start marker and end marker on 

-

# the same line. 

-

# 20041230: Keep a single globals dict for all the code fragments in a single 

-

# file so they can share state. 

-

# 20050206: Added the -x switch to remove all generated output. 

-

# 20050218: Now code can be on the marker lines as well. 

-

# 20050219: Added -c switch to checksum the output so that edits can be 

-

# detected before they are obliterated. 

-

# 20050521: Added cog.error, contributed by Alexander Belchenko. 

-

# 20050720: Added code deletion and settable globals contributed by Blake Winton. 

-

# 20050724: Many tweaks to improve code coverage. 

-

# 20050726: Error messages are now printed with no traceback. 

-

# Code can no longer appear on the marker lines, 

-

# except for single-line style. 

-

# -z allows omission of the [[[end]]] marker, and it will be assumed 

-

# at the end of the file. 

-

# 20050729: Refactor option parsing into a separate class, in preparation for 

-

# future features. 

-

# 20050805: The cogmodule.path wasn't being properly maintained. 

-

# 20050808: Added the -D option to define a global value. 

-

# 20050810: The %s in the -w command is dealt with more robustly. 

-

# Added the -s option to suffix output lines with a marker. 

-

# 20050817: Now @files can have arguments on each line to change the cog's 

-

# behavior for that line. 

-

# 20051006: Version 2.0 

-

# 20080521: -U options lets you create Unix newlines on Windows. Thanks, 

-

# Alexander Belchenko. 

-

# 20080522: It's now ok to have -d with output to stdout, and now we validate 

-

# the args after each line of an @file. 

-

# 20090520: Use hashlib where it's available, to avoid a warning. 

-

# Use the builtin compile() instead of compiler, for Jython. 

-

# Explicitly close files we opened, Jython likes this. 

-

# 20120205: Port to Python 3. Lowest supported version is 2.6. 

-

# 20150104: --markers option added by Doug Hellmann. 

-

# 20150104: -n ENCODING option added by Petr Gladkiy. 

-

# 20150107: Added --verbose to control what files get listed. 

-

# 20150111: Version 2.4 

-

# 20160213: v2.5: -o makes needed directories, thanks Jean-François Giraud. 

-

# 20161019: Added a LICENSE.txt file. 

- -
+

1# coding: utf8 

+

2""" Cog content generation tool. 

+

3 http://nedbatchelder.com/code/cog 

+

4 

+

5 Copyright 2004-2019, Ned Batchelder. 

+

6""" 

+

7 

+

8from __future__ import absolute_import, print_function 

+

9 

+

10import copy 

+

11import getopt 

+

12import glob 

+

13import hashlib 

+

14import imp 

+

15import linecache 

+

16import os 

+

17import re 

+

18import shlex 

+

19import sys 

+

20import traceback 

+

21 

+

22from .backward import PY3, StringIO, string_types, to_bytes 

+

23 

+

24__all__ = ['Cog', 'CogUsageError', 'main'] 

+

25 

+

26__version__ = '3.0.0' 

+

27 

+

28usage = """\ 

+

29cog - generate content with inlined Python code. 

+

30 

+

31cog [OPTIONS] [INFILE | @FILELIST] ... 

+

32 

+

33INFILE is the name of an input file, '-' will read from stdin. 

+

34FILELIST is the name of a text file containing file names or 

+

35 other @FILELISTs. 

+

36 

+

37OPTIONS: 

+

38 -c Checksum the output to protect it against accidental change. 

+

39 -d Delete the generator code from the output file. 

+

40 -D name=val Define a global string available to your generator code. 

+

41 -e Warn if a file has no cog code in it. 

+

42 -I PATH Add PATH to the list of directories for data files and modules. 

+

43 -n ENCODING Use ENCODING when reading and writing files. 

+

44 -o OUTNAME Write the output to OUTNAME. 

+

45 -p PROLOGUE Prepend the generator source with PROLOGUE. Useful to insert an 

+

46 import line. Example: -p "import math" 

+

47 -r Replace the input file with the output. 

+

48 -s STRING Suffix all generated output lines with STRING. 

+

49 -U Write the output with Unix newlines (only LF line-endings). 

+

50 -w CMD Use CMD if the output file needs to be made writable. 

+

51 A %s in the CMD will be filled with the filename. 

+

52 -x Excise all the generated output without running the generators. 

+

53 -z The end-output marker can be omitted, and is assumed at eof. 

+

54 -v Print the version of cog and exit. 

+

55 --verbosity=VERBOSITY 

+

56 Control the amount of output. 2 (the default) lists all files, 

+

57 1 lists only changed files, 0 lists no files. 

+

58 --markers='START END END-OUTPUT' 

+

59 The patterns surrounding cog inline instructions. Should 

+

60 include three values separated by spaces, the start, end, 

+

61 and end-output markers. Defaults to '[[[cog ]]] [[[end]]]'. 

+

62 -h Print this help. 

+

63""" 

+

64 

+

65# Other package modules 

+

66from .whiteutils import * 

+

67 

+

68class CogError(Exception): 

+

69 """ Any exception raised by Cog. 

+

70 """ 

+

71 def __init__(self, msg, file='', line=0): 

+

72 if file: 

+

73 Exception.__init__(self, "%s(%d): %s" % (file, line, msg)) 

+

74 else: 

+

75 Exception.__init__(self, msg) 

+

76 

+

77class CogUsageError(CogError): 

+

78 """ An error in usage of command-line arguments in cog. 

+

79 """ 

+

80 pass 

+

81 

+

82class CogInternalError(CogError): 

+

83 """ An error in the coding of Cog. Should never happen. 

+

84 """ 

+

85 pass 

+

86 

+

87class CogGeneratedError(CogError): 

+

88 """ An error raised by a user's cog generator. 

+

89 """ 

+

90 pass 

+

91 

+

92class CogUserException(CogError): 

+

93 """ An exception caught when running a user's cog generator. 

+

94 The argument is the traceback message to print. 

+

95 """ 

+

96 pass 

+

97 

+

98class Redirectable: 

+

99 """ An object with its own stdout and stderr files. 

+

100 """ 

+

101 def __init__(self): 

+

102 self.stdout = sys.stdout 

+

103 self.stderr = sys.stderr 

+

104 

+

105 def setOutput(self, stdout=None, stderr=None): 

+

106 """ Assign new files for standard out and/or standard error. 

+

107 """ 

+

108 if stdout: 108 ↛ 110line 108 didn't jump to line 110, because the condition on line 108 was never false

+

109 self.stdout = stdout 

+

110 if stderr: 110 ↛ 111line 110 didn't jump to line 111, because the condition on line 110 was never true

+

111 self.stderr = stderr 

+

112 

+

113 def prout(self, s, end="\n"): 

+

114 print(s, file=self.stdout, end=end) 

+

115 

+

116 def prerr(self, s, end="\n"): 

+

117 print(s, file=self.stderr, end=end) 

+

118 

+

119 

+

120class CogGenerator(Redirectable): 

+

121 """ A generator pulled from a source file. 

+

122 """ 

+

123 def __init__(self, options=None): 

+

124 Redirectable.__init__(self) 

+

125 self.markers = [] 

+

126 self.lines = [] 

+

127 self.options = options or CogOptions() 

+

128 

+

129 def parseMarker(self, l): 

+

130 self.markers.append(l) 

+

131 

+

132 def parseLine(self, l): 

+

133 self.lines.append(l.strip('\n')) 

+

134 

+

135 def getCode(self): 

+

136 """ Extract the executable Python code from the generator. 

+

137 """ 

+

138 # If the markers and lines all have the same prefix 

+

139 # (end-of-line comment chars, for example), 

+

140 # then remove it from all the lines. 

+

141 prefIn = commonPrefix(self.markers + self.lines) 

+

142 if prefIn: 

+

143 self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ] 

+

144 self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ] 

+

145 

+

146 return reindentBlock(self.lines, '') 

+

147 

+

148 def evaluate(self, cog, globals, fname): 

+

149 # figure out the right whitespace prefix for the output 

+

150 prefOut = whitePrefix(self.markers) 

+

151 

+

152 intext = self.getCode() 

+

153 if not intext: 

+

154 return '' 

+

155 

+

156 prologue = "import " + cog.cogmodulename + " as cog\n" 

+

157 if self.options.sPrologue: 157 ↛ 158line 157 didn't jump to line 158, because the condition on line 157 was never true

+

158 prologue += self.options.sPrologue + '\n' 

+

159 code = compile(prologue + intext, str(fname), 'exec') 

+

160 

+

161 # Make sure the "cog" module has our state. 

+

162 cog.cogmodule.msg = self.msg 

+

163 cog.cogmodule.out = self.out 

+

164 cog.cogmodule.outl = self.outl 

+

165 cog.cogmodule.error = self.error 

+

166 

+

167 self.outstring = '' 

+

168 try: 

+

169 eval(code, globals) 

+

170 except CogError: 170 ↛ 171line 170 didn't jump to line 171, because the exception caught by line 170 didn't happen

+

171 raise 

+

172 except: 

+

173 typ, err, tb = sys.exc_info() 

+

174 frames = (tuple(fr) for fr in traceback.extract_tb(tb.tb_next)) 

+

175 frames = find_cog_source(frames, prologue) 

+

176 msg = "".join(traceback.format_list(frames)) 

+

177 msg += "{}: {}".format(typ.__name__, err) 

+

178 raise CogUserException(msg) 

+

179 

+

180 # We need to make sure that the last line in the output 

+

181 # ends with a newline, or it will be joined to the 

+

182 # end-output line, ruining cog's idempotency. 

+

183 if self.outstring and self.outstring[-1] != '\n': 

+

184 self.outstring += '\n' 

+

185 

+

186 return reindentBlock(self.outstring, prefOut) 

+

187 

+

188 def msg(self, s): 

+

189 self.prout("Message: "+s) 

+

190 

+

191 def out(self, sOut='', dedent=False, trimblanklines=False): 

+

192 """ The cog.out function. 

+

193 """ 

+

194 if trimblanklines and ('\n' in sOut): 

+

195 lines = sOut.split('\n') 

+

196 if lines[0].strip() == '': 

+

197 del lines[0] 

+

198 if lines and lines[-1].strip() == '': 

+

199 del lines[-1] 

+

200 sOut = '\n'.join(lines)+'\n' 

+

201 if dedent: 

+

202 sOut = reindentBlock(sOut) 

+

203 self.outstring += sOut 

+

204 

+

205 def outl(self, sOut='', **kw): 

+

206 """ The cog.outl function. 

+

207 """ 

+

208 self.out(sOut, **kw) 

+

209 self.out('\n') 

+

210 

+

211 def error(self, msg='Error raised by cog generator.'): 

+

212 """ The cog.error function. 

+

213 Instead of raising standard python errors, cog generators can use 

+

214 this function. It will display the error without a scary Python 

+

215 traceback. 

+

216 """ 

+

217 raise CogGeneratedError(msg) 

+

218 

+

219 

+

220class NumberedFileReader: 

+

221 """ A decorator for files that counts the readline()'s called. 

+

222 """ 

+

223 def __init__(self, f): 

+

224 self.f = f 

+

225 self.n = 0 

+

226 

+

227 def readline(self): 

+

228 l = self.f.readline() 

+

229 if l: 

+

230 self.n += 1 

+

231 return l 

+

232 

+

233 def linenumber(self): 

+

234 return self.n 

+

235 

+

236 

+

237class CogOptions: 

+

238 """ Options for a run of cog. 

+

239 """ 

+

240 def __init__(self): 

+

241 # Defaults for argument values. 

+

242 self.args = [] 

+

243 self.includePath = [] 

+

244 self.defines = {} 

+

245 self.bShowVersion = False 

+

246 self.sMakeWritableCmd = None 

+

247 self.bReplace = False 

+

248 self.bNoGenerate = False 

+

249 self.sOutputName = None 

+

250 self.bWarnEmpty = False 

+

251 self.bHashOutput = False 

+

252 self.bDeleteCode = False 

+

253 self.bEofCanBeEnd = False 

+

254 self.sSuffix = None 

+

255 self.bNewlines = False 

+

256 self.sBeginSpec = '[[[cog' 

+

257 self.sEndSpec = ']]]' 

+

258 self.sEndOutput = '[[[end]]]' 

+

259 self.sEncoding = "utf-8" 

+

260 self.verbosity = 2 

+

261 self.sPrologue = '' 

+

262 

+

263 def __eq__(self, other): 

+

264 """ Comparison operator for tests to use. 

+

265 """ 

+

266 return self.__dict__ == other.__dict__ 

+

267 

+

268 def clone(self): 

+

269 """ Make a clone of these options, for further refinement. 

+

270 """ 

+

271 return copy.deepcopy(self) 

+

272 

+

273 def addToIncludePath(self, dirs): 

+

274 """ Add directories to the include path. 

+

275 """ 

+

276 dirs = dirs.split(os.pathsep) 

+

277 self.includePath.extend(dirs) 

+

278 

+

279 def parseArgs(self, argv): 

+

280 # Parse the command line arguments. 

+

281 try: 

+

282 opts, self.args = getopt.getopt( 

+

283 argv, 

+

284 'cdD:eI:n:o:rs:p:Uvw:xz', 

+

285 [ 

+

286 'markers=', 

+

287 'verbosity=', 

+

288 ] 

+

289 ) 

+

290 except getopt.error as msg: 

+

291 raise CogUsageError(msg) 

+

292 

+

293 # Handle the command line arguments. 

+

294 for o, a in opts: 

+

295 if o == '-c': 

+

296 self.bHashOutput = True 

+

297 elif o == '-d': 

+

298 self.bDeleteCode = True 

+

299 elif o == '-D': 

+

300 if a.count('=') < 1: 

+

301 raise CogUsageError("-D takes a name=value argument") 

+

302 name, value = a.split('=', 1) 

+

303 self.defines[name] = value 

+

304 elif o == '-e': 

+

305 self.bWarnEmpty = True 

+

306 elif o == '-I': 

+

307 self.addToIncludePath(a) 

+

308 elif o == '-n': 

+

309 self.sEncoding = a 

+

310 elif o == '-o': 

+

311 self.sOutputName = a 

+

312 elif o == '-r': 

+

313 self.bReplace = True 

+

314 elif o == '-s': 

+

315 self.sSuffix = a 

+

316 elif o == '-p': 

+

317 self.sPrologue = a 

+

318 elif o == '-U': 

+

319 self.bNewlines = True 

+

320 elif o == '-v': 

+

321 self.bShowVersion = True 

+

322 elif o == '-w': 

+

323 self.sMakeWritableCmd = a 

+

324 elif o == '-x': 

+

325 self.bNoGenerate = True 

+

326 elif o == '-z': 

+

327 self.bEofCanBeEnd = True 

+

328 elif o == '--markers': 

+

329 self._parse_markers(a) 

+

330 elif o == '--verbosity': 

+

331 self.verbosity = int(a) 

+

332 else: 

+

333 # Since getopt.getopt is given a list of possible flags, 

+

334 # this is an internal error. 

+

335 raise CogInternalError("Don't understand argument %s" % o) 

+

336 

+

337 def _parse_markers(self, val): 

+

338 try: 

+

339 self.sBeginSpec, self.sEndSpec, self.sEndOutput = val.split(' ') 

+

340 except ValueError: 

+

341 raise CogUsageError( 

+

342 '--markers requires 3 values separated by spaces, could not parse %r' % val 

+

343 ) 

+

344 

+

345 def validate(self): 

+

346 """ Does nothing if everything is OK, raises CogError's if it's not. 

+

347 """ 

+

348 if self.bReplace and self.bDeleteCode: 

+

349 raise CogUsageError("Can't use -d with -r (or you would delete all your source!)") 

+

350 

+

351 if self.bReplace and self.sOutputName: 

+

352 raise CogUsageError("Can't use -o with -r (they are opposites)") 

+

353 

+

354 

+

355class Cog(Redirectable): 

+

356 """ The Cog engine. 

+

357 """ 

+

358 def __init__(self): 

+

359 Redirectable.__init__(self) 

+

360 self.options = CogOptions() 

+

361 self._fixEndOutputPatterns() 

+

362 self.cogmodulename = "cog" 

+

363 self.installCogModule() 

+

364 

+

365 def _fixEndOutputPatterns(self): 

+

366 end_output = re.escape(self.options.sEndOutput) 

+

367 self.reEndOutput = re.compile(end_output + r'(?P<hashsect> *\(checksum: (?P<hash>[a-f0-9]+)\))') 

+

368 self.sEndFormat = self.options.sEndOutput + ' (checksum: %s)' 

+

369 

+

370 def showWarning(self, msg): 

+

371 self.prout("Warning: "+msg) 

+

372 

+

373 def isBeginSpecLine(self, s): 

+

374 return self.options.sBeginSpec in s 

+

375 

+

376 def isEndSpecLine(self, s): 

+

377 return self.options.sEndSpec in s and not self.isEndOutputLine(s) 

+

378 

+

379 def isEndOutputLine(self, s): 

+

380 return self.options.sEndOutput in s 

+

381 

+

382 def installCogModule(self): 

+

383 """ Magic mumbo-jumbo so that imported Python modules 

+

384 can say "import cog" and get our state. 

+

385 """ 

+

386 self.cogmodule = imp.new_module('cog') 

+

387 self.cogmodule.path = [] 

+

388 

+

389 def openOutputFile(self, fname): 

+

390 """ Open an output file, taking all the details into account. 

+

391 """ 

+

392 opts = {} 

+

393 mode = "w" 

+

394 if PY3: 

+

395 opts['encoding'] = self.options.sEncoding 

+

396 if self.options.bNewlines: 

+

397 if PY3: 

+

398 opts['newline'] = "\n" 

+

399 else: 

+

400 mode = "wb" 

+

401 fdir = os.path.dirname(fname) 

+

402 if os.path.dirname(fdir) and not os.path.exists(fdir): 

+

403 os.makedirs(fdir) 

+

404 return open(fname, mode, **opts) 

+

405 

+

406 def openInputFile(self, fname): 

+

407 """ Open an input file. """ 

+

408 if fname == "-": 

+

409 return sys.stdin 

+

410 else: 

+

411 opts = {} 

+

412 if PY3: 

+

413 opts['encoding'] = self.options.sEncoding 

+

414 return open(fname, "r", **opts) 

+

415 

+

416 def processFile(self, fIn, fOut, fname=None, globals=None): 

+

417 """ Process an input file object to an output file object. 

+

418 fIn and fOut can be file objects, or file names. 

+

419 """ 

+

420 

+

421 sFileIn = fname or '' 

+

422 sFileOut = fname or '' 

+

423 fInToClose = fOutToClose = None 

+

424 # Convert filenames to files. 

+

425 if isinstance(fIn, string_types): 425 ↛ 427line 425 didn't jump to line 427, because the condition on line 425 was never true

+

426 # Open the input file. 

+

427 sFileIn = fIn 

+

428 fIn = fInToClose = self.openInputFile(fIn) 

+

429 if isinstance(fOut, string_types): 429 ↛ 431line 429 didn't jump to line 431, because the condition on line 429 was never true

+

430 # Open the output file. 

+

431 sFileOut = fOut 

+

432 fOut = fOutToClose = self.openOutputFile(fOut) 

+

433 

+

434 try: 

+

435 fIn = NumberedFileReader(fIn) 

+

436 

+

437 bSawCog = False 

+

438 

+

439 self.cogmodule.inFile = sFileIn 

+

440 self.cogmodule.outFile = sFileOut 

+

441 self.cogmodulename = 'cog_' + hashlib.md5(sFileOut.encode()).hexdigest() 

+

442 sys.modules[self.cogmodulename] = self.cogmodule 

+

443 # if "import cog" explicitly done in code by user, note threading will cause clashes.  

+

444 sys.modules['cog'] = self.cogmodule 

+

445 

+

446 # The globals dict we'll use for this file. 

+

447 if globals is None: 447 ↛ 451line 447 didn't jump to line 451, because the condition on line 447 was never false

+

448 globals = {} 

+

449 

+

450 # If there are any global defines, put them in the globals. 

+

451 globals.update(self.options.defines) 

+

452 

+

453 # loop over generator chunks 

+

454 l = fIn.readline() 

+

455 while l: 

+

456 # Find the next spec begin 

+

457 while l and not self.isBeginSpecLine(l): 

+

458 if self.isEndSpecLine(l): 458 ↛ 459line 458 didn't jump to line 459, because the condition on line 458 was never true

+

459 raise CogError("Unexpected '%s'" % self.options.sEndSpec, 

+

460 file=sFileIn, line=fIn.linenumber()) 

+

461 if self.isEndOutputLine(l): 461 ↛ 462line 461 didn't jump to line 462, because the condition on line 461 was never true

+

462 raise CogError("Unexpected '%s'" % self.options.sEndOutput, 

+

463 file=sFileIn, line=fIn.linenumber()) 

+

464 fOut.write(l) 

+

465 l = fIn.readline() 

+

466 if not l: 

+

467 break 

+

468 if not self.options.bDeleteCode: 468 ↛ 472line 468 didn't jump to line 472, because the condition on line 468 was never false

+

469 fOut.write(l) 

+

470 

+

471 # l is the begin spec 

+

472 gen = CogGenerator(options=self.options) 

+

473 gen.setOutput(stdout=self.stdout) 

+

474 gen.parseMarker(l) 

+

475 firstLineNum = fIn.linenumber() 

+

476 self.cogmodule.firstLineNum = firstLineNum 

+

477 

+

478 # If the spec begin is also a spec end, then process the single 

+

479 # line of code inside. 

+

480 if self.isEndSpecLine(l): 

+

481 beg = l.find(self.options.sBeginSpec) 

+

482 end = l.find(self.options.sEndSpec) 

+

483 if beg > end: 

+

484 raise CogError("Cog code markers inverted", 

+

485 file=sFileIn, line=firstLineNum) 

+

486 else: 

+

487 sCode = l[beg+len(self.options.sBeginSpec):end].strip() 

+

488 gen.parseLine(sCode) 

+

489 else: 

+

490 # Deal with an ordinary code block. 

+

491 l = fIn.readline() 

+

492 

+

493 # Get all the lines in the spec 

+

494 while l and not self.isEndSpecLine(l): 

+

495 if self.isBeginSpecLine(l): 495 ↛ 496line 495 didn't jump to line 496, because the condition on line 495 was never true

+

496 raise CogError("Unexpected '%s'" % self.options.sBeginSpec, 

+

497 file=sFileIn, line=fIn.linenumber()) 

+

498 if self.isEndOutputLine(l): 498 ↛ 499line 498 didn't jump to line 499, because the condition on line 498 was never true

+

499 raise CogError("Unexpected '%s'" % self.options.sEndOutput, 

+

500 file=sFileIn, line=fIn.linenumber()) 

+

501 if not self.options.bDeleteCode: 501 ↛ 503line 501 didn't jump to line 503, because the condition on line 501 was never false

+

502 fOut.write(l) 

+

503 gen.parseLine(l) 

+

504 l = fIn.readline() 

+

505 if not l: 505 ↛ 506line 505 didn't jump to line 506, because the condition on line 505 was never true

+

506 raise CogError( 

+

507 "Cog block begun but never ended.", 

+

508 file=sFileIn, line=firstLineNum) 

+

509 

+

510 if not self.options.bDeleteCode: 510 ↛ 512line 510 didn't jump to line 512, because the condition on line 510 was never false

+

511 fOut.write(l) 

+

512 gen.parseMarker(l) 

+

513 

+

514 l = fIn.readline() 

+

515 

+

516 # Eat all the lines in the output section. While reading past 

+

517 # them, compute the md5 hash of the old output. 

+

518 previous = "" 

+

519 hasher = hashlib.md5() 

+

520 while l and not self.isEndOutputLine(l): 

+

521 if self.isBeginSpecLine(l): 521 ↛ 522line 521 didn't jump to line 522, because the condition on line 521 was never true

+

522 raise CogError("Unexpected '%s'" % self.options.sBeginSpec, 

+

523 file=sFileIn, line=fIn.linenumber()) 

+

524 if self.isEndSpecLine(l): 524 ↛ 525line 524 didn't jump to line 525, because the condition on line 524 was never true

+

525 raise CogError("Unexpected '%s'" % self.options.sEndSpec, 

+

526 file=sFileIn, line=fIn.linenumber()) 

+

527 previous += l 

+

528 hasher.update(to_bytes(l)) 

+

529 l = fIn.readline() 

+

530 curHash = hasher.hexdigest() 

+

531 

+

532 if not l and not self.options.bEofCanBeEnd: 532 ↛ 534line 532 didn't jump to line 534, because the condition on line 532 was never true

+

533 # We reached end of file before we found the end output line. 

+

534 raise CogError("Missing '%s' before end of file." % self.options.sEndOutput, 

+

535 file=sFileIn, line=fIn.linenumber()) 

+

536 

+

537 # Make the previous output available to the current code 

+

538 self.cogmodule.previous = previous 

+

539 

+

540 # Write the output of the spec to be the new output if we're 

+

541 # supposed to generate code. 

+

542 hasher = hashlib.md5() 

+

543 if not self.options.bNoGenerate: 543 ↛ 549line 543 didn't jump to line 549, because the condition on line 543 was never false

+

544 sFile = "<cog %s:%d>" % (sFileIn, firstLineNum) 

+

545 sGen = gen.evaluate(cog=self, globals=globals, fname=sFile) 

+

546 sGen = self.suffixLines(sGen) 

+

547 hasher.update(to_bytes(sGen)) 

+

548 fOut.write(sGen) 

+

549 newHash = hasher.hexdigest() 

+

550 

+

551 bSawCog = True 

+

552 

+

553 # Write the ending output line 

+

554 hashMatch = self.reEndOutput.search(l) 

+

555 if self.options.bHashOutput: 555 ↛ 556line 555 didn't jump to line 556, because the condition on line 555 was never true

+

556 if hashMatch: 

+

557 oldHash = hashMatch.groupdict()['hash'] 

+

558 if oldHash != curHash: 

+

559 raise CogError("Output has been edited! Delete old checksum to unprotect.", 

+

560 file=sFileIn, line=fIn.linenumber()) 

+

561 # Create a new end line with the correct hash. 

+

562 endpieces = l.split(hashMatch.group(0), 1) 

+

563 else: 

+

564 # There was no old hash, but we want a new hash. 

+

565 endpieces = l.split(self.options.sEndOutput, 1) 

+

566 l = (self.sEndFormat % newHash).join(endpieces) 

+

567 else: 

+

568 # We don't want hashes output, so if there was one, get rid of 

+

569 # it. 

+

570 if hashMatch: 570 ↛ 571line 570 didn't jump to line 571, because the condition on line 570 was never true

+

571 l = l.replace(hashMatch.groupdict()['hashsect'], '', 1) 

+

572 

+

573 if not self.options.bDeleteCode: 573 ↛ 575line 573 didn't jump to line 575, because the condition on line 573 was never false

+

574 fOut.write(l) 

+

575 l = fIn.readline() 

+

576 

+

577 if not bSawCog and self.options.bWarnEmpty: 577 ↛ 578line 577 didn't jump to line 578, because the condition on line 577 was never true

+

578 self.showWarning("no cog code found in %s" % sFileIn) 

+

579 finally: 

+

580 if fInToClose: 580 ↛ 581line 580 didn't jump to line 581, because the condition on line 580 was never true

+

581 fInToClose.close() 

+

582 if fOutToClose: 582 ↛ 583line 582 didn't jump to line 583, because the condition on line 582 was never true

+

583 fOutToClose.close() 

+

584 

+

585 

+

586 # A regex for non-empty lines, used by suffixLines. 

+

587 reNonEmptyLines = re.compile(r"^\s*\S+.*$", re.MULTILINE) 

+

588 

+

589 def suffixLines(self, text): 

+

590 """ Add suffixes to the lines in text, if our options desire it. 

+

591 text is many lines, as a single string. 

+

592 """ 

+

593 if self.options.sSuffix: 593 ↛ 595line 593 didn't jump to line 595, because the condition on line 593 was never true

+

594 # Find all non-blank lines, and add the suffix to the end. 

+

595 repl = r"\g<0>" + self.options.sSuffix.replace('\\', '\\\\') 

+

596 text = self.reNonEmptyLines.sub(repl, text) 

+

597 return text 

+

598 

+

599 def processString(self, sInput, fname=None): 

+

600 """ Process sInput as the text to cog. 

+

601 Return the cogged output as a string. 

+

602 """ 

+

603 fOld = StringIO(sInput) 

+

604 fNew = StringIO() 

+

605 self.processFile(fOld, fNew, fname=fname) 

+

606 return fNew.getvalue() 

+

607 

+

608 def replaceFile(self, sOldPath, sNewText): 

+

609 """ Replace file sOldPath with the contents sNewText 

+

610 """ 

+

611 if not os.access(sOldPath, os.W_OK): 

+

612 # Need to ensure we can write. 

+

613 if self.options.sMakeWritableCmd: 

+

614 # Use an external command to make the file writable. 

+

615 cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath) 

+

616 self.stdout.write(os.popen(cmd).read()) 

+

617 if not os.access(sOldPath, os.W_OK): 

+

618 raise CogError("Couldn't make %s writable" % sOldPath) 

+

619 else: 

+

620 # Can't write! 

+

621 raise CogError("Can't overwrite %s" % sOldPath) 

+

622 f = self.openOutputFile(sOldPath) 

+

623 f.write(sNewText) 

+

624 f.close() 

+

625 

+

626 def saveIncludePath(self): 

+

627 self.savedInclude = self.options.includePath[:] 

+

628 self.savedSysPath = sys.path[:] 

+

629 

+

630 def restoreIncludePath(self): 

+

631 self.options.includePath = self.savedInclude 

+

632 self.cogmodule.path = self.options.includePath 

+

633 sys.path = self.savedSysPath 

+

634 

+

635 def addToIncludePath(self, includePath): 

+

636 self.cogmodule.path.extend(includePath) 

+

637 sys.path.extend(includePath) 

+

638 

+

639 def processOneFile(self, sFile): 

+

640 """ Process one filename through cog. 

+

641 """ 

+

642 

+

643 self.saveIncludePath() 

+

644 bNeedNewline = False 

+

645 

+

646 try: 

+

647 self.addToIncludePath(self.options.includePath) 

+

648 # Since we know where the input file came from, 

+

649 # push its directory onto the include path. 

+

650 self.addToIncludePath([os.path.dirname(sFile)]) 

+

651 

+

652 # How we process the file depends on where the output is going. 

+

653 if self.options.sOutputName: 

+

654 self.processFile(sFile, self.options.sOutputName, sFile) 

+

655 elif self.options.bReplace: 

+

656 # We want to replace the cog file with the output, 

+

657 # but only if they differ. 

+

658 if self.options.verbosity >= 2: 

+

659 self.prout("Cogging %s" % sFile, end="") 

+

660 bNeedNewline = True 

+

661 

+

662 try: 

+

663 fOldFile = self.openInputFile(sFile) 

+

664 sOldText = fOldFile.read() 

+

665 fOldFile.close() 

+

666 sNewText = self.processString(sOldText, fname=sFile) 

+

667 if sOldText != sNewText: 

+

668 if self.options.verbosity >= 1: 

+

669 if self.options.verbosity < 2: 

+

670 self.prout("Cogging %s" % sFile, end="") 

+

671 self.prout(" (changed)") 

+

672 bNeedNewline = False 

+

673 self.replaceFile(sFile, sNewText) 

+

674 finally: 

+

675 # The try-finally block is so we can print a partial line 

+

676 # with the name of the file, and print (changed) on the 

+

677 # same line, but also make sure to break the line before 

+

678 # any traceback. 

+

679 if bNeedNewline: 

+

680 self.prout("") 

+

681 else: 

+

682 self.processFile(sFile, self.stdout, sFile) 

+

683 finally: 

+

684 self.restoreIncludePath() 

+

685 

+

686 def processWildcards(self, sFile): 

+

687 files = glob.glob(sFile) 

+

688 if files: 

+

689 for sMatchingFile in files: 

+

690 self.processOneFile(sMatchingFile) 

+

691 else: 

+

692 self.processOneFile(sFile) 

+

693 

+

694 def processFileList(self, sFileList): 

+

695 """ Process the files in a file list. 

+

696 """ 

+

697 flist = self.openInputFile(sFileList) 

+

698 lines = flist.readlines() 

+

699 flist.close() 

+

700 for l in lines: 

+

701 # Use shlex to parse the line like a shell. 

+

702 lex = shlex.shlex(l, posix=True) 

+

703 lex.whitespace_split = True 

+

704 lex.commenters = '#' 

+

705 # No escapes, so that backslash can be part of the path 

+

706 lex.escape = '' 

+

707 args = list(lex) 

+

708 if args: 

+

709 self.processArguments(args) 

+

710 

+

711 def processArguments(self, args): 

+

712 """ Process one command-line. 

+

713 """ 

+

714 saved_options = self.options 

+

715 self.options = self.options.clone() 

+

716 

+

717 self.options.parseArgs(args[1:]) 

+

718 self.options.validate() 

+

719 

+

720 if args[0][0] == '@': 

+

721 if self.options.sOutputName: 

+

722 raise CogUsageError("Can't use -o with @file") 

+

723 self.processFileList(args[0][1:]) 

+

724 else: 

+

725 self.processWildcards(args[0]) 

+

726 

+

727 self.options = saved_options 

+

728 

+

729 def callableMain(self, argv): 

+

730 """ All of command-line cog, but in a callable form. 

+

731 This is used by main. 

+

732 argv is the equivalent of sys.argv. 

+

733 """ 

+

734 argv = argv[1:] 

+

735 

+

736 # Provide help if asked for anywhere in the command line. 

+

737 if '-?' in argv or '-h' in argv: 

+

738 self.prerr(usage, end="") 

+

739 return 

+

740 

+

741 self.options.parseArgs(argv) 

+

742 self.options.validate() 

+

743 self._fixEndOutputPatterns() 

+

744 

+

745 if self.options.bShowVersion: 

+

746 self.prout("Cog version %s" % __version__) 

+

747 return 

+

748 

+

749 if self.options.args: 

+

750 for a in self.options.args: 

+

751 self.processArguments([a]) 

+

752 else: 

+

753 raise CogUsageError("No files to process") 

+

754 

+

755 def main(self, argv): 

+

756 """ Handle the command-line execution for cog. 

+

757 """ 

+

758 

+

759 try: 

+

760 self.callableMain(argv) 

+

761 return 0 

+

762 except CogUsageError as err: 

+

763 self.prerr(err) 

+

764 self.prerr("(for help use -?)") 

+

765 return 2 

+

766 except CogGeneratedError as err: 

+

767 self.prerr("Error: %s" % err) 

+

768 return 3 

+

769 except CogUserException as err: 

+

770 self.prerr("Traceback (most recent call last):") 

+

771 self.prerr(err.args[0]) 

+

772 return 4 

+

773 except CogError as err: 

+

774 self.prerr(err) 

+

775 return 1 

+

776 

+

777 

+

778def find_cog_source(frame_summary, prologue): 

+

779 """Find cog source lines in a frame summary list, for printing tracebacks. 

+

780 

+

781 Arguments: 

+

782 frame_summary: a list of 4-item tuples, as returned by traceback.extract_tb. 

+

783 prologue: the text of the code prologue. 

+

784 

+

785 Returns 

+

786 A list of 4-item tuples, updated to correct the cog entries. 

+

787 

+

788 """ 

+

789 prolines = prologue.splitlines() 

+

790 for filename, lineno, funcname, source in frame_summary: 

+

791 if not source: 791 ↛ 803line 791 didn't jump to line 803, because the condition on line 791 was never false

+

792 m = re.search(r"^<cog ([^:]+):(\d+)>$", filename) 

+

793 if m: 793 ↛ 794line 793 didn't jump to line 794, because the condition on line 793 was never true

+

794 if lineno <= len(prolines): 

+

795 filename = '<prologue>' 

+

796 source = prolines[lineno-1] 

+

797 lineno -= 1 # Because "import cog" is the first line in the prologue 

+

798 else: 

+

799 filename, coglineno = m.groups() 

+

800 coglineno = int(coglineno) 

+

801 lineno += coglineno - len(prolines) 

+

802 source = linecache.getline(filename, lineno).strip() 

+

803 yield filename, lineno, funcname, source 

+

804 

+

805 

+

806def main(): 

+

807 """Main function for entry_points to use.""" 

+

808 return Cog().main(sys.argv) 

- - diff --git a/doc/sample_html/cogapp_makefiles_py.html b/doc/sample_html/cogapp_makefiles_py.html index 404f2496..59ecc3e2 100644 --- a/doc/sample_html/cogapp_makefiles_py.html +++ b/doc/sample_html/cogapp_makefiles_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/makefiles.py: 92.86% + Coverage for cogapp/makefiles.py: 17.07% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,154 +51,61 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

- -
-

""" Dictionary-to-filetree functions, to create test files for testing. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

import os.path 

-

from .whiteutils import reindentBlock 

-

from .backward import string_types, bytes_types 

-

 

-

__version__ = '1.0.20040126' 

-

__all__ = ['makeFiles', 'removeFiles'] 

-

 

-

def makeFiles(d, basedir='.'): 

-

""" Create files from the dictionary `d`, in the directory named by `basedir`. 

-

""" 

-

for name, contents in d.items(): 

-

child = os.path.join(basedir, name) 

-

if isinstance(contents, string_types): 

-

mode = 'w' 

-

22 ↛ 24line 22 didn't jump to line 24, because the condition on line 22 was never false if isinstance(contents, bytes_types): 

-

mode += "b" 

-

f = open(child, mode) 

-

contents = reindentBlock(contents) 

-

f.write(contents) 

-

f.close() 

-

else: 

-

29 ↛ 31line 29 didn't jump to line 31, because the condition on line 29 was never false if not os.path.exists(child): 

-

os.mkdir(child) 

-

makeFiles(contents, child) 

-

 

-

def removeFiles(d, basedir='.'): 

-

""" Remove the files created by makeFiles. 

-

Directories are removed if they are empty. 

-

""" 

-

for name, contents in d.items(): 

-

child = os.path.join(basedir, name) 

-

if isinstance(contents, string_types): 

-

os.remove(child) 

-

else: 

-

removeFiles(contents, child) 

-

43 ↛ 37line 43 didn't jump to line 37, because the condition on line 43 was never false if not os.listdir(child): 

-

os.rmdir(child) 

-

 

-

if __name__ == '__main__': #pragma: no cover 

-

# Try it a little. 

-

d = { 

-

'test_makefiles': { 

-

'hey.txt': """\ 

-

This is hey.txt. 

-

It's very simple. 

-

""", 

-

'subdir': { 

-

'fooey': """\ 

-

# Fooey 

-

Kablooey 

-

Ew. 

-

""" 

-

} 

-

} 

-

} 

-

makeFiles(d) 

- -
+

1""" Dictionary-to-filetree functions, to create test files for testing. 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2019, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9import os.path 

+

10 

+

11from .backward import string_types, bytes_types 

+

12from .whiteutils import reindentBlock 

+

13 

+

14__all__ = ['makeFiles', 'removeFiles'] 

+

15 

+

16def makeFiles(d, basedir='.', bytes=False): 

+

17 """ Create files from the dictionary `d`, in the directory named by `basedir`. 

+

18 If `bytes` is true, then treat bytestrings as bytes, else as text. 

+

19 """ 

+

20 for name, contents in d.items(): 

+

21 child = os.path.join(basedir, name) 

+

22 if isinstance(contents, string_types): 

+

23 mode = 'w' 

+

24 if bytes and isinstance(contents, bytes_types): 

+

25 mode += "b" 

+

26 f = open(child, mode) 

+

27 contents = reindentBlock(contents) 

+

28 f.write(contents) 

+

29 f.close() 

+

30 else: 

+

31 if not os.path.exists(child): 

+

32 os.mkdir(child) 

+

33 makeFiles(contents, child) 

+

34 

+

35def removeFiles(d, basedir='.'): 

+

36 """ Remove the files created by makeFiles. 

+

37 Directories are removed if they are empty. 

+

38 """ 

+

39 for name, contents in d.items(): 

+

40 child = os.path.join(basedir, name) 

+

41 if isinstance(contents, string_types): 

+

42 os.remove(child) 

+

43 else: 

+

44 removeFiles(contents, child) 

+

45 if not os.listdir(child): 

+

46 os.rmdir(child) 

- - diff --git a/doc/sample_html/cogapp_test_cogapp_py.html b/doc/sample_html/cogapp_test_cogapp_py.html index 5f14aa40..8a9d66cc 100644 --- a/doc/sample_html/cogapp_test_cogapp_py.html +++ b/doc/sample_html/cogapp_test_cogapp_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/test_cogapp.py: 99.86% + Coverage for cogapp/test_cogapp.py: 30.00% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,4472 +51,2493 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

-

533

-

534

-

535

-

536

-

537

-

538

-

539

-

540

-

541

-

542

-

543

-

544

-

545

-

546

-

547

-

548

-

549

-

550

-

551

-

552

-

553

-

554

-

555

-

556

-

557

-

558

-

559

-

560

-

561

-

562

-

563

-

564

-

565

-

566

-

567

-

568

-

569

-

570

-

571

-

572

-

573

-

574

-

575

-

576

-

577

-

578

-

579

-

580

-

581

-

582

-

583

-

584

-

585

-

586

-

587

-

588

-

589

-

590

-

591

-

592

-

593

-

594

-

595

-

596

-

597

-

598

-

599

-

600

-

601

-

602

-

603

-

604

-

605

-

606

-

607

-

608

-

609

-

610

-

611

-

612

-

613

-

614

-

615

-

616

-

617

-

618

-

619

-

620

-

621

-

622

-

623

-

624

-

625

-

626

-

627

-

628

-

629

-

630

-

631

-

632

-

633

-

634

-

635

-

636

-

637

-

638

-

639

-

640

-

641

-

642

-

643

-

644

-

645

-

646

-

647

-

648

-

649

-

650

-

651

-

652

-

653

-

654

-

655

-

656

-

657

-

658

-

659

-

660

-

661

-

662

-

663

-

664

-

665

-

666

-

667

-

668

-

669

-

670

-

671

-

672

-

673

-

674

-

675

-

676

-

677

-

678

-

679

-

680

-

681

-

682

-

683

-

684

-

685

-

686

-

687

-

688

-

689

-

690

-

691

-

692

-

693

-

694

-

695

-

696

-

697

-

698

-

699

-

700

-

701

-

702

-

703

-

704

-

705

-

706

-

707

-

708

-

709

-

710

-

711

-

712

-

713

-

714

-

715

-

716

-

717

-

718

-

719

-

720

-

721

-

722

-

723

-

724

-

725

-

726

-

727

-

728

-

729

-

730

-

731

-

732

-

733

-

734

-

735

-

736

-

737

-

738

-

739

-

740

-

741

-

742

-

743

-

744

-

745

-

746

-

747

-

748

-

749

-

750

-

751

-

752

-

753

-

754

-

755

-

756

-

757

-

758

-

759

-

760

-

761

-

762

-

763

-

764

-

765

-

766

-

767

-

768

-

769

-

770

-

771

-

772

-

773

-

774

-

775

-

776

-

777

-

778

-

779

-

780

-

781

-

782

-

783

-

784

-

785

-

786

-

787

-

788

-

789

-

790

-

791

-

792

-

793

-

794

-

795

-

796

-

797

-

798

-

799

-

800

-

801

-

802

-

803

-

804

-

805

-

806

-

807

-

808

-

809

-

810

-

811

-

812

-

813

-

814

-

815

-

816

-

817

-

818

-

819

-

820

-

821

-

822

-

823

-

824

-

825

-

826

-

827

-

828

-

829

-

830

-

831

-

832

-

833

-

834

-

835

-

836

-

837

-

838

-

839

-

840

-

841

-

842

-

843

-

844

-

845

-

846

-

847

-

848

-

849

-

850

-

851

-

852

-

853

-

854

-

855

-

856

-

857

-

858

-

859

-

860

-

861

-

862

-

863

-

864

-

865

-

866

-

867

-

868

-

869

-

870

-

871

-

872

-

873

-

874

-

875

-

876

-

877

-

878

-

879

-

880

-

881

-

882

-

883

-

884

-

885

-

886

-

887

-

888

-

889

-

890

-

891

-

892

-

893

-

894

-

895

-

896

-

897

-

898

-

899

-

900

-

901

-

902

-

903

-

904

-

905

-

906

-

907

-

908

-

909

-

910

-

911

-

912

-

913

-

914

-

915

-

916

-

917

-

918

-

919

-

920

-

921

-

922

-

923

-

924

-

925

-

926

-

927

-

928

-

929

-

930

-

931

-

932

-

933

-

934

-

935

-

936

-

937

-

938

-

939

-

940

-

941

-

942

-

943

-

944

-

945

-

946

-

947

-

948

-

949

-

950

-

951

-

952

-

953

-

954

-

955

-

956

-

957

-

958

-

959

-

960

-

961

-

962

-

963

-

964

-

965

-

966

-

967

-

968

-

969

-

970

-

971

-

972

-

973

-

974

-

975

-

976

-

977

-

978

-

979

-

980

-

981

-

982

-

983

-

984

-

985

-

986

-

987

-

988

-

989

-

990

-

991

-

992

-

993

-

994

-

995

-

996

-

997

-

998

-

999

-

1000

-

1001

-

1002

-

1003

-

1004

-

1005

-

1006

-

1007

-

1008

-

1009

-

1010

-

1011

-

1012

-

1013

-

1014

-

1015

-

1016

-

1017

-

1018

-

1019

-

1020

-

1021

-

1022

-

1023

-

1024

-

1025

-

1026

-

1027

-

1028

-

1029

-

1030

-

1031

-

1032

-

1033

-

1034

-

1035

-

1036

-

1037

-

1038

-

1039

-

1040

-

1041

-

1042

-

1043

-

1044

-

1045

-

1046

-

1047

-

1048

-

1049

-

1050

-

1051

-

1052

-

1053

-

1054

-

1055

-

1056

-

1057

-

1058

-

1059

-

1060

-

1061

-

1062

-

1063

-

1064

-

1065

-

1066

-

1067

-

1068

-

1069

-

1070

-

1071

-

1072

-

1073

-

1074

-

1075

-

1076

-

1077

-

1078

-

1079

-

1080

-

1081

-

1082

-

1083

-

1084

-

1085

-

1086

-

1087

-

1088

-

1089

-

1090

-

1091

-

1092

-

1093

-

1094

-

1095

-

1096

-

1097

-

1098

-

1099

-

1100

-

1101

-

1102

-

1103

-

1104

-

1105

-

1106

-

1107

-

1108

-

1109

-

1110

-

1111

-

1112

-

1113

-

1114

-

1115

-

1116

-

1117

-

1118

-

1119

-

1120

-

1121

-

1122

-

1123

-

1124

-

1125

-

1126

-

1127

-

1128

-

1129

-

1130

-

1131

-

1132

-

1133

-

1134

-

1135

-

1136

-

1137

-

1138

-

1139

-

1140

-

1141

-

1142

-

1143

-

1144

-

1145

-

1146

-

1147

-

1148

-

1149

-

1150

-

1151

-

1152

-

1153

-

1154

-

1155

-

1156

-

1157

-

1158

-

1159

-

1160

-

1161

-

1162

-

1163

-

1164

-

1165

-

1166

-

1167

-

1168

-

1169

-

1170

-

1171

-

1172

-

1173

-

1174

-

1175

-

1176

-

1177

-

1178

-

1179

-

1180

-

1181

-

1182

-

1183

-

1184

-

1185

-

1186

-

1187

-

1188

-

1189

-

1190

-

1191

-

1192

-

1193

-

1194

-

1195

-

1196

-

1197

-

1198

-

1199

-

1200

-

1201

-

1202

-

1203

-

1204

-

1205

-

1206

-

1207

-

1208

-

1209

-

1210

-

1211

-

1212

-

1213

-

1214

-

1215

-

1216

-

1217

-

1218

-

1219

-

1220

-

1221

-

1222

-

1223

-

1224

-

1225

-

1226

-

1227

-

1228

-

1229

-

1230

-

1231

-

1232

-

1233

-

1234

-

1235

-

1236

-

1237

-

1238

-

1239

-

1240

-

1241

-

1242

-

1243

-

1244

-

1245

-

1246

-

1247

-

1248

-

1249

-

1250

-

1251

-

1252

-

1253

-

1254

-

1255

-

1256

-

1257

-

1258

-

1259

-

1260

-

1261

-

1262

-

1263

-

1264

-

1265

-

1266

-

1267

-

1268

-

1269

-

1270

-

1271

-

1272

-

1273

-

1274

-

1275

-

1276

-

1277

-

1278

-

1279

-

1280

-

1281

-

1282

-

1283

-

1284

-

1285

-

1286

-

1287

-

1288

-

1289

-

1290

-

1291

-

1292

-

1293

-

1294

-

1295

-

1296

-

1297

-

1298

-

1299

-

1300

-

1301

-

1302

-

1303

-

1304

-

1305

-

1306

-

1307

-

1308

-

1309

-

1310

-

1311

-

1312

-

1313

-

1314

-

1315

-

1316

-

1317

-

1318

-

1319

-

1320

-

1321

-

1322

-

1323

-

1324

-

1325

-

1326

-

1327

-

1328

-

1329

-

1330

-

1331

-

1332

-

1333

-

1334

-

1335

-

1336

-

1337

-

1338

-

1339

-

1340

-

1341

-

1342

-

1343

-

1344

-

1345

-

1346

-

1347

-

1348

-

1349

-

1350

-

1351

-

1352

-

1353

-

1354

-

1355

-

1356

-

1357

-

1358

-

1359

-

1360

-

1361

-

1362

-

1363

-

1364

-

1365

-

1366

-

1367

-

1368

-

1369

-

1370

-

1371

-

1372

-

1373

-

1374

-

1375

-

1376

-

1377

-

1378

-

1379

-

1380

-

1381

-

1382

-

1383

-

1384

-

1385

-

1386

-

1387

-

1388

-

1389

-

1390

-

1391

-

1392

-

1393

-

1394

-

1395

-

1396

-

1397

-

1398

-

1399

-

1400

-

1401

-

1402

-

1403

-

1404

-

1405

-

1406

-

1407

-

1408

-

1409

-

1410

-

1411

-

1412

-

1413

-

1414

-

1415

-

1416

-

1417

-

1418

-

1419

-

1420

-

1421

-

1422

-

1423

-

1424

-

1425

-

1426

-

1427

-

1428

-

1429

-

1430

-

1431

-

1432

-

1433

-

1434

-

1435

-

1436

-

1437

-

1438

-

1439

-

1440

-

1441

-

1442

-

1443

-

1444

-

1445

-

1446

-

1447

-

1448

-

1449

-

1450

-

1451

-

1452

-

1453

-

1454

-

1455

-

1456

-

1457

-

1458

-

1459

-

1460

-

1461

-

1462

-

1463

-

1464

-

1465

-

1466

-

1467

-

1468

-

1469

-

1470

-

1471

-

1472

-

1473

-

1474

-

1475

-

1476

-

1477

-

1478

-

1479

-

1480

-

1481

-

1482

-

1483

-

1484

-

1485

-

1486

-

1487

-

1488

-

1489

-

1490

-

1491

-

1492

-

1493

-

1494

-

1495

-

1496

-

1497

-

1498

-

1499

-

1500

-

1501

-

1502

-

1503

-

1504

-

1505

-

1506

-

1507

-

1508

-

1509

-

1510

-

1511

-

1512

-

1513

-

1514

-

1515

-

1516

-

1517

-

1518

-

1519

-

1520

-

1521

-

1522

-

1523

-

1524

-

1525

-

1526

-

1527

-

1528

-

1529

-

1530

-

1531

-

1532

-

1533

-

1534

-

1535

-

1536

-

1537

-

1538

-

1539

-

1540

-

1541

-

1542

-

1543

-

1544

-

1545

-

1546

-

1547

-

1548

-

1549

-

1550

-

1551

-

1552

-

1553

-

1554

-

1555

-

1556

-

1557

-

1558

-

1559

-

1560

-

1561

-

1562

-

1563

-

1564

-

1565

-

1566

-

1567

-

1568

-

1569

-

1570

-

1571

-

1572

-

1573

-

1574

-

1575

-

1576

-

1577

-

1578

-

1579

-

1580

-

1581

-

1582

-

1583

-

1584

-

1585

-

1586

-

1587

-

1588

-

1589

-

1590

-

1591

-

1592

-

1593

-

1594

-

1595

-

1596

-

1597

-

1598

-

1599

-

1600

-

1601

-

1602

-

1603

-

1604

-

1605

-

1606

-

1607

-

1608

-

1609

-

1610

-

1611

-

1612

-

1613

-

1614

-

1615

-

1616

-

1617

-

1618

-

1619

-

1620

-

1621

-

1622

-

1623

-

1624

-

1625

-

1626

-

1627

-

1628

-

1629

-

1630

-

1631

-

1632

-

1633

-

1634

-

1635

-

1636

-

1637

-

1638

-

1639

-

1640

-

1641

-

1642

-

1643

-

1644

-

1645

-

1646

-

1647

-

1648

-

1649

-

1650

-

1651

-

1652

-

1653

-

1654

-

1655

-

1656

-

1657

-

1658

-

1659

-

1660

-

1661

-

1662

-

1663

-

1664

-

1665

-

1666

-

1667

-

1668

-

1669

-

1670

-

1671

-

1672

-

1673

-

1674

-

1675

-

1676

-

1677

-

1678

-

1679

-

1680

-

1681

-

1682

-

1683

-

1684

-

1685

-

1686

-

1687

-

1688

-

1689

-

1690

-

1691

-

1692

-

1693

-

1694

-

1695

-

1696

-

1697

-

1698

-

1699

-

1700

-

1701

-

1702

-

1703

-

1704

-

1705

-

1706

-

1707

-

1708

-

1709

-

1710

-

1711

-

1712

-

1713

-

1714

-

1715

-

1716

-

1717

-

1718

-

1719

-

1720

-

1721

-

1722

-

1723

-

1724

-

1725

-

1726

-

1727

-

1728

-

1729

-

1730

-

1731

-

1732

-

1733

-

1734

-

1735

-

1736

-

1737

-

1738

-

1739

-

1740

-

1741

-

1742

-

1743

-

1744

-

1745

-

1746

-

1747

-

1748

-

1749

-

1750

-

1751

-

1752

-

1753

-

1754

-

1755

-

1756

-

1757

-

1758

-

1759

-

1760

-

1761

-

1762

-

1763

-

1764

-

1765

-

1766

-

1767

-

1768

-

1769

-

1770

-

1771

-

1772

-

1773

-

1774

-

1775

-

1776

-

1777

-

1778

-

1779

-

1780

-

1781

-

1782

-

1783

-

1784

-

1785

-

1786

-

1787

-

1788

-

1789

-

1790

-

1791

-

1792

-

1793

-

1794

-

1795

-

1796

-

1797

-

1798

-

1799

-

1800

-

1801

-

1802

-

1803

-

1804

-

1805

-

1806

-

1807

-

1808

-

1809

-

1810

-

1811

-

1812

-

1813

-

1814

-

1815

-

1816

-

1817

-

1818

-

1819

-

1820

-

1821

-

1822

-

1823

-

1824

-

1825

-

1826

-

1827

-

1828

-

1829

-

1830

-

1831

-

1832

-

1833

-

1834

-

1835

-

1836

-

1837

-

1838

-

1839

-

1840

-

1841

-

1842

-

1843

-

1844

-

1845

-

1846

-

1847

-

1848

-

1849

-

1850

-

1851

-

1852

-

1853

-

1854

-

1855

-

1856

-

1857

-

1858

-

1859

-

1860

-

1861

-

1862

-

1863

-

1864

-

1865

-

1866

-

1867

-

1868

-

1869

-

1870

-

1871

-

1872

-

1873

-

1874

-

1875

-

1876

-

1877

-

1878

-

1879

-

1880

-

1881

-

1882

-

1883

-

1884

-

1885

-

1886

-

1887

-

1888

-

1889

-

1890

-

1891

-

1892

-

1893

-

1894

-

1895

-

1896

-

1897

-

1898

-

1899

-

1900

-

1901

-

1902

-

1903

-

1904

-

1905

-

1906

-

1907

-

1908

-

1909

-

1910

-

1911

-

1912

-

1913

-

1914

-

1915

-

1916

-

1917

-

1918

-

1919

-

1920

-

1921

-

1922

-

1923

-

1924

-

1925

-

1926

-

1927

-

1928

-

1929

-

1930

-

1931

-

1932

-

1933

-

1934

-

1935

-

1936

-

1937

-

1938

-

1939

-

1940

-

1941

-

1942

-

1943

-

1944

-

1945

-

1946

-

1947

-

1948

-

1949

-

1950

-

1951

-

1952

-

1953

-

1954

-

1955

-

1956

-

1957

-

1958

-

1959

-

1960

-

1961

-

1962

-

1963

-

1964

-

1965

-

1966

-

1967

-

1968

-

1969

-

1970

-

1971

-

1972

-

1973

-

1974

-

1975

-

1976

-

1977

-

1978

-

1979

-

1980

-

1981

-

1982

-

1983

-

1984

-

1985

-

1986

-

1987

-

1988

-

1989

-

1990

-

1991

-

1992

-

1993

-

1994

-

1995

-

1996

-

1997

-

1998

-

1999

-

2000

-

2001

-

2002

-

2003

-

2004

-

2005

-

2006

-

2007

-

2008

-

2009

-

2010

-

2011

-

2012

-

2013

-

2014

-

2015

-

2016

-

2017

-

2018

-

2019

-

2020

-

2021

-

2022

-

2023

-

2024

-

2025

-

2026

-

2027

-

2028

-

2029

-

2030

-

2031

-

2032

-

2033

-

2034

-

2035

-

2036

-

2037

-

2038

-

2039

-

2040

-

2041

-

2042

-

2043

-

2044

-

2045

-

2046

-

2047

-

2048

-

2049

-

2050

-

2051

-

2052

-

2053

-

2054

-

2055

-

2056

-

2057

-

2058

-

2059

-

2060

-

2061

-

2062

-

2063

-

2064

-

2065

-

2066

-

2067

-

2068

-

2069

-

2070

-

2071

-

2072

-

2073

-

2074

-

2075

-

2076

-

2077

-

2078

-

2079

-

2080

-

2081

-

2082

-

2083

-

2084

-

2085

-

2086

-

2087

-

2088

-

2089

-

2090

-

2091

-

2092

-

2093

-

2094

-

2095

-

2096

-

2097

-

2098

-

2099

-

2100

-

2101

-

2102

-

2103

-

2104

-

2105

-

2106

-

2107

-

2108

-

2109

-

2110

-

2111

-

2112

-

2113

-

2114

-

2115

-

2116

-

2117

-

2118

-

2119

-

2120

-

2121

-

2122

-

2123

-

2124

-

2125

-

2126

-

2127

-

2128

-

2129

-

2130

-

2131

-

2132

-

2133

-

2134

-

2135

-

2136

-

2137

-

2138

-

2139

-

2140

-

2141

-

2142

-

2143

-

2144

-

2145

-

2146

-

2147

-

2148

-

2149

-

2150

-

2151

-

2152

-

2153

-

2154

-

2155

-

2156

-

2157

-

2158

-

2159

-

2160

-

2161

-

2162

-

2163

-

2164

-

2165

-

2166

-

2167

-

2168

-

2169

-

2170

-

2171

-

2172

-

2173

-

2174

-

2175

-

2176

-

2177

-

2178

-

2179

-

2180

-

2181

-

2182

-

2183

-

2184

-

2185

-

2186

-

2187

-

2188

-

2189

-

2190

-

2191

-

2192

-

2193

-

2194

-

2195

-

2196

-

2197

-

2198

-

2199

-

2200

-

2201

-

2202

-

2203

-

2204

-

2205

-

2206

-

2207

-

2208

-

2209

-

2210

-

2211

-

2212

-

2213

-

2214

-

2215

-

2216

-

2217

-

2218

-

2219

-

2220

-

2221

-

2222

- -
-

""" Test cogapp. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

 

-

import os, os.path, random, re, shutil, stat, sys, tempfile 

-

 

-

# Use unittest2 if it's available, otherwise unittest. This gives us 

-

# back-ported features for 2.6. 

-

try: 

-

import unittest2 as unittest 

-

except ImportError: 

-

import unittest 

-

 

-

from .backward import StringIO, to_bytes, b 

-

from .cogapp import Cog, CogOptions, CogGenerator 

-

from .cogapp import CogError, CogUsageError, CogGeneratedError 

-

from .cogapp import usage, __version__ 

-

from .whiteutils import reindentBlock 

-

from .makefiles import * 

-

 

-

 

-

TestCase = unittest.TestCase 

-

 

-

 

-

class CogTestsInMemory(TestCase): 

-

""" Test cases for cogapp.Cog() 

-

""" 

-

 

-

def testNoCog(self): 

-

strings = [ 

-

'', 

-

' ', 

-

' \t \t \tx', 

-

'hello', 

-

'the cat\nin the\nhat.', 

-

'Horton\n\tHears A\n\t\tWho' 

-

] 

-

for s in strings: 

-

self.assertEqual(Cog().processString(s), s) 

-

 

-

def testSimple(self): 

-

infile = """\ 

-

Some text. 

-

//[[[cog 

-

import cog 

-

cog.outl("This is line one\\n") 

-

cog.outl("This is line two") 

-

//]]] 

-

gobbledegook. 

-

//[[[end]]] 

-

epilogue. 

-

""" 

-

 

-

outfile = """\ 

-

Some text. 

-

//[[[cog 

-

import cog 

-

cog.outl("This is line one\\n") 

-

cog.outl("This is line two") 

-

//]]] 

-

This is line one 

-

 

-

This is line two 

-

//[[[end]]] 

-

epilogue. 

-

""" 

-

 

-

self.assertEqual(Cog().processString(infile), outfile) 

-

 

-

def testEmptyCog(self): 

-

# The cog clause can be totally empty. Not sure why you'd want it, 

-

# but it works. 

-

infile = """\ 

-

hello 

-

//[[[cog 

-

//]]] 

-

//[[[end]]] 

-

goodbye 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testMultipleCogs(self): 

-

# One file can have many cog chunks, even abutting each other. 

-

infile = """\ 

-

//[[[cog 

-

cog.out("chunk1") 

-

//]]] 

-

chunk1 

-

//[[[end]]] 

-

//[[[cog 

-

cog.out("chunk2") 

-

//]]] 

-

chunk2 

-

//[[[end]]] 

-

between chunks 

-

//[[[cog 

-

cog.out("chunk3") 

-

//]]] 

-

chunk3 

-

//[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testTrimBlankLines(self): 

-

infile = """\ 

-

//[[[cog 

-

cog.out("This is line one\\n", trimblanklines=True) 

-

cog.out(''' 

-

This is line two 

-

''', dedent=True, trimblanklines=True) 

-

cog.outl("This is line three", trimblanklines=True) 

-

//]]] 

-

This is line one 

-

This is line two 

-

This is line three 

-

//[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testTrimEmptyBlankLines(self): 

-

infile = """\ 

-

//[[[cog 

-

cog.out("This is line one\\n", trimblanklines=True) 

-

cog.out(''' 

-

This is line two 

-

''', dedent=True, trimblanklines=True) 

-

cog.out('', dedent=True, trimblanklines=True) 

-

cog.outl("This is line three", trimblanklines=True) 

-

//]]] 

-

This is line one 

-

This is line two 

-

This is line three 

-

//[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def test22EndOfLine(self): 

-

# In Python 2.2, this cog file was not parsing because the 

-

# last line is indented but didn't end with a newline. 

-

infile = """\ 

-

//[[[cog 

-

import cog 

-

for i in range(3): 

-

cog.out("%d\\n" % i) 

-

//]]] 

-

0 

-

1 

-

2 

-

//[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testIndentedCode(self): 

-

infile = """\ 

-

first line 

-

[[[cog 

-

import cog 

-

for i in range(3): 

-

cog.out("xx%d\\n" % i) 

-

]]] 

-

xx0 

-

xx1 

-

xx2 

-

[[[end]]] 

-

last line 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testPrefixedCode(self): 

-

infile = """\ 

-

--[[[cog 

-

--import cog 

-

--for i in range(3): 

-

-- cog.out("xx%d\\n" % i) 

-

--]]] 

-

xx0 

-

xx1 

-

xx2 

-

--[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testPrefixedIndentedCode(self): 

-

infile = """\ 

-

prologue 

-

--[[[cog 

-

-- import cog 

-

-- for i in range(3): 

-

-- cog.out("xy%d\\n" % i) 

-

--]]] 

-

xy0 

-

xy1 

-

xy2 

-

--[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testBogusPrefixMatch(self): 

-

infile = """\ 

-

prologue 

-

#[[[cog 

-

import cog 

-

# This comment should not be clobbered by removing the pound sign. 

-

for i in range(3): 

-

cog.out("xy%d\\n" % i) 

-

#]]] 

-

xy0 

-

xy1 

-

xy2 

-

#[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testNoFinalNewline(self): 

-

# If the cog'ed output has no final newline, 

-

# it shouldn't eat up the cog terminator. 

-

infile = """\ 

-

prologue 

-

[[[cog 

-

import cog 

-

for i in range(3): 

-

cog.out("%d" % i) 

-

]]] 

-

012 

-

[[[end]]] 

-

epilogue 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testNoOutputAtAll(self): 

-

# If there is absolutely no cog output, that's ok. 

-

infile = """\ 

-

prologue 

-

[[[cog 

-

i = 1 

-

]]] 

-

[[[end]]] 

-

epilogue 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testPurelyBlankLine(self): 

-

# If there is a blank line in the cog code with no whitespace 

-

# prefix, that should be OK. 

-

 

-

infile = """\ 

-

prologue 

-

[[[cog 

-

import sys 

-

cog.out("Hello") 

-

$ 

-

cog.out("There") 

-

]]] 

-

HelloThere 

-

[[[end]]] 

-

epilogue 

-

""" 

-

 

-

infile = reindentBlock(infile.replace('$', '')) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testEmptyOutl(self): 

-

# Alexander Belchenko suggested the string argument to outl should 

-

# be optional. Does it work? 

-

 

-

infile = """\ 

-

prologue 

-

[[[cog 

-

cog.outl("x") 

-

cog.outl() 

-

cog.outl("y") 

-

cog.outl(trimblanklines=True) 

-

cog.outl("z") 

-

]]] 

-

x 

-

 

-

y 

-

 

-

z 

-

[[[end]]] 

-

epilogue 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testFirstLineNum(self): 

-

infile = """\ 

-

fooey 

-

[[[cog 

-

cog.outl("started at line number %d" % cog.firstLineNum) 

-

]]] 

-

started at line number 2 

-

[[[end]]] 

-

blah blah 

-

[[[cog 

-

cog.outl("and again at line %d" % cog.firstLineNum) 

-

]]] 

-

and again at line 8 

-

[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

def testCompactOneLineCode(self): 

-

infile = """\ 

-

first line 

-

hey: [[[cog cog.outl("hello %d" % (3*3*3*3)) ]]] looky! 

-

get rid of this! 

-

[[[end]]] 

-

last line 

-

""" 

-

 

-

outfile = """\ 

-

first line 

-

hey: [[[cog cog.outl("hello %d" % (3*3*3*3)) ]]] looky! 

-

hello 81 

-

[[[end]]] 

-

last line 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

-

 

-

def testInsideOutCompact(self): 

-

infile = """\ 

-

first line 

-

hey?: ]]] what is this? [[[cog strange! 

-

get rid of this! 

-

[[[end]]] 

-

last line 

-

""" 

-

with self.assertRaisesRegexp(CogError, r"infile.txt\(2\): Cog code markers inverted"): 

-

Cog().processString(reindentBlock(infile), "infile.txt") 

-

 

-

def testSharingGlobals(self): 

-

infile = """\ 

-

first line 

-

hey: [[[cog s="hey there" ]]] looky! 

-

[[[end]]] 

-

more literal junk. 

-

[[[cog cog.outl(s) ]]] 

-

[[[end]]] 

-

last line 

-

""" 

-

 

-

outfile = """\ 

-

first line 

-

hey: [[[cog s="hey there" ]]] looky! 

-

[[[end]]] 

-

more literal junk. 

-

[[[cog cog.outl(s) ]]] 

-

hey there 

-

[[[end]]] 

-

last line 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

-

 

-

def testAssertInCogCode(self): 

-

# Check that we can test assertions in cog code in the test framework. 

-

infile = """\ 

-

[[[cog 

-

assert 1 == 2, "Oops" 

-

]]] 

-

[[[end]]] 

-

""" 

-

infile = reindentBlock(infile) 

-

with self.assertRaisesRegexp(AssertionError, "Oops"): 

-

Cog().processString(infile) 

-

 

-

def testCogPrevious(self): 

-

# Check that we can access the previous run's output. 

-

infile = """\ 

-

[[[cog 

-

assert cog.previous == "Hello there!\\n", "WTF??" 

-

cog.out(cog.previous) 

-

cog.outl("Ran again!") 

-

]]] 

-

Hello there! 

-

[[[end]]] 

-

""" 

-

 

-

outfile = """\ 

-

[[[cog 

-

assert cog.previous == "Hello there!\\n", "WTF??" 

-

cog.out(cog.previous) 

-

cog.outl("Ran again!") 

-

]]] 

-

Hello there! 

-

Ran again! 

-

[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

-

 

-

 

-

class CogOptionsTests(TestCase): 

-

""" Test the CogOptions class. 

-

""" 

-

 

-

def testEquality(self): 

-

o = CogOptions() 

-

p = CogOptions() 

-

self.assertEqual(o, p) 

-

o.parseArgs(['-r']) 

-

self.assertNotEqual(o, p) 

-

p.parseArgs(['-r']) 

-

self.assertEqual(o, p) 

-

 

-

def testCloning(self): 

-

o = CogOptions() 

-

o.parseArgs(['-I', 'fooey', '-I', 'booey', '-s', ' /*x*/']) 

-

p = o.clone() 

-

self.assertEqual(o, p) 

-

p.parseArgs(['-I', 'huey', '-D', 'foo=quux']) 

-

self.assertNotEqual(o, p) 

-

q = CogOptions() 

-

q.parseArgs(['-I', 'fooey', '-I', 'booey', '-s', ' /*x*/', '-I', 'huey', '-D', 'foo=quux']) 

-

self.assertEqual(p, q) 

-

 

-

def testCombiningFlags(self): 

-

# Single-character flags can be combined. 

-

o = CogOptions() 

-

o.parseArgs(['-e', '-r', '-z']) 

-

p = CogOptions() 

-

p.parseArgs(['-erz']) 

-

self.assertEqual(o, p) 

-

 

-

def testMarkers(self): 

-

o = CogOptions() 

-

o._parse_markers('a b c') 

-

self.assertEqual('a', o.sBeginSpec) 

-

self.assertEqual('b', o.sEndSpec) 

-

self.assertEqual('c', o.sEndOutput) 

-

 

-

def testMarkersSwitch(self): 

-

o = CogOptions() 

-

o.parseArgs(['--markers', 'a b c']) 

-

self.assertEqual('a', o.sBeginSpec) 

-

self.assertEqual('b', o.sEndSpec) 

-

self.assertEqual('c', o.sEndOutput) 

-

 

-

 

-

class FileStructureTests(TestCase): 

-

""" Test cases to check that we're properly strict about the structure 

-

of files. 

-

""" 

-

 

-

def isBad(self, infile, msg=None): 

-

infile = reindentBlock(infile) 

-

with self.assertRaisesRegexp(CogError, re.escape(msg)): 

-

Cog().processString(infile, 'infile.txt') 

-

 

-

def testBeginNoEnd(self): 

-

infile = """\ 

-

Fooey 

-

#[[[cog 

-

cog.outl('hello') 

-

""" 

-

self.isBad(infile, "infile.txt(2): Cog block begun but never ended.") 

-

 

-

def testNoEoo(self): 

-

infile = """\ 

-

Fooey 

-

#[[[cog 

-

cog.outl('hello') 

-

#]]] 

-

""" 

-

self.isBad(infile, "infile.txt(4): Missing '[[[end]]]' before end of file.") 

-

 

-

infile2 = """\ 

-

Fooey 

-

#[[[cog 

-

cog.outl('hello') 

-

#]]] 

-

#[[[cog 

-

cog.outl('goodbye') 

-

#]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(5): Unexpected '[[[cog'") 

-

 

-

def testStartWithEnd(self): 

-

infile = """\ 

-

#]]] 

-

""" 

-

self.isBad(infile, "infile.txt(1): Unexpected ']]]'") 

-

 

-

infile2 = """\ 

-

#[[[cog 

-

cog.outl('hello') 

-

#]]] 

-

#[[[end]]] 

-

#]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(5): Unexpected ']]]'") 

-

 

-

def testStartWithEoo(self): 

-

infile = """\ 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile, "infile.txt(1): Unexpected '[[[end]]]'") 

-

 

-

infile2 = """\ 

-

#[[[cog 

-

cog.outl('hello') 

-

#]]] 

-

#[[[end]]] 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(5): Unexpected '[[[end]]]'") 

-

 

-

def testNoEnd(self): 

-

infile = """\ 

-

#[[[cog 

-

cog.outl("hello") 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile, "infile.txt(3): Unexpected '[[[end]]]'") 

-

 

-

infile2 = """\ 

-

#[[[cog 

-

cog.outl('hello') 

-

#]]] 

-

#[[[end]]] 

-

#[[[cog 

-

cog.outl("hello") 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(7): Unexpected '[[[end]]]'") 

-

 

-

def testTwoBegins(self): 

-

infile = """\ 

-

#[[[cog 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile, "infile.txt(2): Unexpected '[[[cog'") 

-

 

-

infile2 = """\ 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#[[[end]]] 

-

#[[[cog 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(6): Unexpected '[[[cog'") 

-

 

-

def testTwoEnds(self): 

-

infile = """\ 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#]]] 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile, "infile.txt(4): Unexpected ']]]'") 

-

 

-

infile2 = """\ 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#[[[end]]] 

-

#[[[cog 

-

cog.outl("hello") 

-

#]]] 

-

#]]] 

-

#[[[end]]] 

-

""" 

-

self.isBad(infile2, "infile.txt(8): Unexpected ']]]'") 

-

 

-

 

-

class CogErrorTests(TestCase): 

-

""" Test cases for cog.error(). 

-

""" 

-

 

-

def testErrorMsg(self): 

-

infile = """\ 

-

[[[cog cog.error("This ain't right!")]]] 

-

[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

with self.assertRaisesRegexp(CogGeneratedError, "This ain't right!"): 

-

Cog().processString(infile) 

-

 

-

def testErrorNoMsg(self): 

-

infile = """\ 

-

[[[cog cog.error()]]] 

-

[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

with self.assertRaisesRegexp(CogGeneratedError, "Error raised by cog generator."): 

-

Cog().processString(infile) 

-

 

-

def testNoErrorIfErrorNotCalled(self): 

-

infile = """\ 

-

--[[[cog 

-

--import cog 

-

--for i in range(3): 

-

-- if i > 10: 

-

-- cog.error("Something is amiss!") 

-

-- cog.out("xx%d\\n" % i) 

-

--]]] 

-

xx0 

-

xx1 

-

xx2 

-

--[[[end]]] 

-

""" 

-

 

-

infile = reindentBlock(infile) 

-

self.assertEqual(Cog().processString(infile), infile) 

-

 

-

 

-

class CogGeneratorGetCodeTests(TestCase): 

-

""" Unit tests against CogGenerator to see if its getCode() method works 

-

properly. 

-

""" 

-

 

-

def setUp(self): 

-

""" All tests get a generator to use, and short same-length names for 

-

the functions we're going to use. 

-

""" 

-

self.gen = CogGenerator() 

-

self.m = self.gen.parseMarker 

-

self.l = self.gen.parseLine 

-

 

-

def testEmpty(self): 

-

self.m('// [[[cog') 

-

self.m('// ]]]') 

-

self.assertEqual(self.gen.getCode(), '') 

-

 

-

def testSimple(self): 

-

self.m('// [[[cog') 

-

self.l(' print "hello"') 

-

self.l(' print "bye"') 

-

self.m('// ]]]') 

-

self.assertEqual(self.gen.getCode(), 'print "hello"\nprint "bye"') 

-

 

-

def testCompressed1(self): 

-

# For a while, I supported compressed code blocks, but no longer. 

-

self.m('// [[[cog: print """') 

-

self.l('// hello') 

-

self.l('// bye') 

-

self.m('// """)]]]') 

-

self.assertEqual(self.gen.getCode(), 'hello\nbye') 

-

 

-

def testCompressed2(self): 

-

# For a while, I supported compressed code blocks, but no longer. 

-

self.m('// [[[cog: print """') 

-

self.l('hello') 

-

self.l('bye') 

-

self.m('// """)]]]') 

-

self.assertEqual(self.gen.getCode(), 'hello\nbye') 

-

 

-

def testCompressed3(self): 

-

# For a while, I supported compressed code blocks, but no longer. 

-

self.m('// [[[cog') 

-

self.l('print """hello') 

-

self.l('bye') 

-

self.m('// """)]]]') 

-

self.assertEqual(self.gen.getCode(), 'print """hello\nbye') 

-

 

-

def testCompressed4(self): 

-

# For a while, I supported compressed code blocks, but no longer. 

-

self.m('// [[[cog: print """') 

-

self.l('hello') 

-

self.l('bye""")') 

-

self.m('// ]]]') 

-

self.assertEqual(self.gen.getCode(), 'hello\nbye""")') 

-

 

-

def testNoCommonPrefixForMarkers(self): 

-

# It's important to be able to use #if 0 to hide lines from a 

-

# C++ compiler. 

-

self.m('#if 0 //[[[cog') 

-

self.l('\timport cog, sys') 

-

self.l('') 

-

self.l('\tprint sys.argv') 

-

self.m('#endif //]]]') 

-

self.assertEqual(self.gen.getCode(), 'import cog, sys\n\nprint sys.argv') 

-

 

-

 

-

class TestCaseWithTempDir(TestCase): 

-

 

-

def newCog(self): 

-

""" Initialize the cog members for another run. 

-

""" 

-

# Create a cog engine, and catch its output. 

-

self.cog = Cog() 

-

self.output = StringIO() 

-

self.cog.setOutput(stdout=self.output, stderr=self.output) 

-

 

-

def setUp(self): 

-

# Create a temporary directory. 

-

self.tempdir = os.path.join(tempfile.gettempdir(), 'testcog_tempdir_' + str(random.random())[2:]) 

-

os.mkdir(self.tempdir) 

-

self.olddir = os.getcwd() 

-

os.chdir(self.tempdir) 

-

self.newCog() 

-

 

-

def tearDown(self): 

-

os.chdir(self.olddir) 

-

# Get rid of the temporary directory. 

-

shutil.rmtree(self.tempdir) 

-

 

-

def assertFilesSame(self, sFName1, sFName2): 

-

text1 = open(os.path.join(self.tempdir, sFName1), 'rb').read() 

-

text2 = open(os.path.join(self.tempdir, sFName2), 'rb').read() 

-

self.assertEqual(text1, text2) 

-

 

-

def assertFileContent(self, sFName, sContent): 

-

sAbsName = os.path.join(self.tempdir, sFName) 

-

f = open(sAbsName, 'rb') 

-

try: 

-

sFileContent = f.read() 

-

finally: 

-

f.close() 

-

self.assertEqual(sFileContent, to_bytes(sContent)) 

-

 

-

 

-

class ArgumentHandlingTests(TestCaseWithTempDir): 

-

 

-

def testArgumentFailure(self): 

-

# Return value 2 means usage problem. 

-

self.assertEqual(self.cog.main(['argv0', '-j']), 2) 

-

output = self.output.getvalue() 

-

self.assertIn("option -j not recognized", output) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0']) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-j']) 

-

 

-

def testNoDashOAndAtFile(self): 

-

d = { 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-o', 'foo', '@cogfiles.txt']) 

-

 

-

def testDashV(self): 

-

self.assertEqual(self.cog.main(['argv0', '-v']), 0) 

-

output = self.output.getvalue() 

-

self.assertEqual('Cog version %s\n' % __version__, output) 

-

 

-

def producesHelp(self, args): 

-

self.newCog() 

-

argv = ['argv0'] + args.split() 

-

self.assertEqual(self.cog.main(argv), 0) 

-

self.assertEqual(usage, self.output.getvalue()) 

-

 

-

def testDashH(self): 

-

# -h or -? anywhere on the command line should just print help. 

-

self.producesHelp("-h") 

-

self.producesHelp("-?") 

-

self.producesHelp("fooey.txt -h") 

-

self.producesHelp("-o -r @fooey.txt -? @booey.txt") 

-

 

-

def testDashOAndDashR(self): 

-

d = { 

-

'cogfile.txt': """\ 

-

# Please run cog 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-o', 'foo', '-r', 'cogfile.txt']) 

-

 

-

def testDashZ(self): 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

""", 

-

 

-

'test.out': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

void DoSomething(); 

-

void DoAnotherThing(); 

-

void DoLastThing(); 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaisesRegexp(CogError, re.escape("test.cog(6): Missing '[[[end]]]' before end of file.")): 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-r', '-z', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testBadDashD(self): 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-Dfooey', 'cog.txt']) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-D', 'fooey', 'cog.txt']) 

-

 

-

def testBadMarkers(self): 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '--markers=X']) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '--markers=A B C D']) 

-

 

-

 

-

class TestFileHandling(TestCaseWithTempDir): 

-

 

-

def testSimple(self): 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

void DoSomething(); 

-

void DoAnotherThing(); 

-

void DoLastThing(); 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

def testOutputFile(self): 

-

# -o sets the output file. 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

void DoSomething(); 

-

void DoAnotherThing(); 

-

void DoLastThing(); 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-o', 'in/a/dir/test.cogged', 'test.cog']) 

-

self.assertFilesSame('in/a/dir/test.cogged', 'test.out') 

-

 

-

def testAtFile(self): 

-

d = { 

-

'one.cog': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'one.out': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

hello world 

-

//[[[end]]] 

-

""", 

-

 

-

'two.cog': """\ 

-

//[[[cog 

-

cog.outl("goodbye cruel world") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'two.out': """\ 

-

//[[[cog 

-

cog.outl("goodbye cruel world") 

-

//]]] 

-

goodbye cruel world 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

one.cog 

-

 

-

two.cog 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

-

self.assertFilesSame('one.cog', 'one.out') 

-

self.assertFilesSame('two.cog', 'two.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

def testNestedAtFile(self): 

-

d = { 

-

'one.cog': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'one.out': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

hello world 

-

//[[[end]]] 

-

""", 

-

 

-

'two.cog': """\ 

-

//[[[cog 

-

cog.outl("goodbye cruel world") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'two.out': """\ 

-

//[[[cog 

-

cog.outl("goodbye cruel world") 

-

//]]] 

-

goodbye cruel world 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

one.cog 

-

@cogfiles2.txt 

-

""", 

-

 

-

'cogfiles2.txt': """\ 

-

# This one too, please. 

-

two.cog 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

-

self.assertFilesSame('one.cog', 'one.out') 

-

self.assertFilesSame('two.cog', 'two.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

def testAtFileWithArgs(self): 

-

d = { 

-

'both.cog': """\ 

-

//[[[cog 

-

cog.outl("one: %s" % ('one' in globals())) 

-

cog.outl("two: %s" % ('two' in globals())) 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'one.out': """\ 

-

//[[[cog 

-

cog.outl("one: %s" % ('one' in globals())) 

-

cog.outl("two: %s" % ('two' in globals())) 

-

//]]] 

-

one: True // ONE 

-

two: False // ONE 

-

//[[[end]]] 

-

""", 

-

 

-

'two.out': """\ 

-

//[[[cog 

-

cog.outl("one: %s" % ('one' in globals())) 

-

cog.outl("two: %s" % ('two' in globals())) 

-

//]]] 

-

one: False // TWO 

-

two: True // TWO 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

both.cog -o in/a/dir/both.one -s ' // ONE' -D one=x 

-

both.cog -o in/a/dir/both.two -s ' // TWO' -D two=x 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '@cogfiles.txt']) 

-

self.assertFilesSame('in/a/dir/both.one', 'one.out') 

-

self.assertFilesSame('in/a/dir/both.two', 'two.out') 

-

 

-

def testAtFileWithBadArgCombo(self): 

-

d = { 

-

'both.cog': """\ 

-

//[[[cog 

-

cog.outl("one: %s" % ('one' in globals())) 

-

cog.outl("two: %s" % ('two' in globals())) 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

both.cog 

-

both.cog -d # This is bad: -r and -d 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

-

 

-

def testAtFileWithTrickyFilenames(self): 

-

def fix_backslashes(files_txt): 

-

"""Make the contents of a files.txt sensitive to the platform.""" 

-

1082 ↛ 1084line 1082 didn't jump to line 1084, because the condition on line 1082 was never false if sys.platform != "win32": 

-

files_txt = files_txt.replace("\\", "/") 

-

return files_txt 

-

 

-

d = { 

-

'one 1.cog': """\ 

-

//[[[cog cog.outl("hello world") ]]] 

-

""", 

-

 

-

'one.out': """\ 

-

//[[[cog cog.outl("hello world") ]]] 

-

hello world //xxx 

-

""", 

-

 

-

'subdir': { 

-

'subback.cog': """\ 

-

//[[[cog cog.outl("down deep with backslashes") ]]] 

-

""", 

-

 

-

'subfwd.cog': """\ 

-

//[[[cog cog.outl("down deep with slashes") ]]] 

-

""", 

-

}, 

-

 

-

'subback.out': """\ 

-

//[[[cog cog.outl("down deep with backslashes") ]]] 

-

down deep with backslashes //yyy 

-

""", 

-

 

-

'subfwd.out': """\ 

-

//[[[cog cog.outl("down deep with slashes") ]]] 

-

down deep with slashes //zzz 

-

""", 

-

 

-

'cogfiles.txt': fix_backslashes("""\ 

-

# Please run cog 

-

'one 1.cog' -s ' //xxx' 

-

subdir\\subback.cog -s ' //yyy' 

-

subdir/subfwd.cog -s ' //zzz' 

-

""") 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-z', '-r', '@cogfiles.txt']) 

-

self.assertFilesSame('one 1.cog', 'one.out') 

-

self.assertFilesSame('subdir/subback.cog', 'subback.out') 

-

self.assertFilesSame('subdir/subfwd.cog', 'subfwd.out') 

-

 

-

def run_with_verbosity(self, verbosity): 

-

d = { 

-

'unchanged.cog': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

hello world 

-

//[[[end]]] 

-

""", 

-

 

-

'changed.cog': """\ 

-

//[[[cog 

-

cog.outl("goodbye cruel world") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

unchanged.cog 

-

changed.cog 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '--verbosity='+verbosity, '@cogfiles.txt']) 

-

output = self.output.getvalue() 

-

return output 

-

 

-

def test_verbosity0(self): 

-

output = self.run_with_verbosity("0") 

-

self.assertEqual(output, "") 

-

 

-

def test_verbosity1(self): 

-

output = self.run_with_verbosity("1") 

-

self.assertEqual(output, "Cogging changed.cog (changed)\n") 

-

 

-

def test_verbosity2(self): 

-

output = self.run_with_verbosity("2") 

-

self.assertEqual(output, "Cogging unchanged.cog\nCogging changed.cog (changed)\n") 

-

 

-

 

-

class CogTestLineEndings(TestCaseWithTempDir): 

-

"""Tests for -U option (force LF line-endings in output).""" 

-

 

-

lines_in = ['Some text.', 

-

'//[[[cog', 

-

'cog.outl("Cog text")', 

-

'//]]]', 

-

'gobbledegook.', 

-

'//[[[end]]]', 

-

'epilogue.', 

-

''] 

-

 

-

lines_out = ['Some text.', 

-

'//[[[cog', 

-

'cog.outl("Cog text")', 

-

'//]]]', 

-

'Cog text', 

-

'//[[[end]]]', 

-

'epilogue.', 

-

''] 

-

 

-

def testOutputNativeEol(self): 

-

makeFiles({'infile': '\n'.join(self.lines_in)}) 

-

self.cog.callableMain(['argv0', '-o', 'outfile', 'infile']) 

-

self.assertFileContent('outfile', os.linesep.join(self.lines_out)) 

-

 

-

def testOutputLfEol(self): 

-

makeFiles({'infile': '\n'.join(self.lines_in)}) 

-

self.cog.callableMain(['argv0', '-U', '-o', 'outfile', 'infile']) 

-

self.assertFileContent('outfile', '\n'.join(self.lines_out)) 

-

 

-

def testReplaceNativeEol(self): 

-

makeFiles({'test.cog': '\n'.join(self.lines_in)}) 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

self.assertFileContent('test.cog', os.linesep.join(self.lines_out)) 

-

 

-

def testReplaceLfEol(self): 

-

makeFiles({'test.cog': '\n'.join(self.lines_in)}) 

-

self.cog.callableMain(['argv0', '-U', '-r', 'test.cog']) 

-

self.assertFileContent('test.cog', '\n'.join(self.lines_out)) 

-

 

-

 

-

class CogTestCharacterEncoding(TestCaseWithTempDir): 

-

 

-

def testSimple(self): 

-

d = { 

-

'test.cog': b("""\ 

-

// This is my C++ file. 

-

//[[[cog 

-

cog.outl("// Unicode: \xe1\x88\xb4 (U+1234)") 

-

//]]] 

-

//[[[end]]] 

-

"""), 

-

 

-

'test.out': b("""\ 

-

// This is my C++ file. 

-

//[[[cog 

-

cog.outl("// Unicode: \xe1\x88\xb4 (U+1234)") 

-

//]]] 

-

// Unicode: \xe1\x88\xb4 (U+1234) 

-

//[[[end]]] 

-

"""), 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

def testFileEncodingOption(self): 

-

d = { 

-

'test.cog': b("""\ 

-

// \xca\xee\xe4\xe8\xf0\xe2\xea\xe0 Windows 

-

//[[[cog 

-

cog.outl("\xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe") 

-

//]]] 

-

//[[[end]]] 

-

"""), 

-

 

-

'test.out': b("""\ 

-

// \xca\xee\xe4\xe8\xf0\xe2\xea\xe0 Windows 

-

//[[[cog 

-

cog.outl("\xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe") 

-

//]]] 

-

\xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe 

-

//[[[end]]] 

-

"""), 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-n', 'cp1251', '-r', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

 

-

class TestCaseWithImports(TestCaseWithTempDir): 

-

""" When running tests which import modules, the sys.modules list 

-

leaks from one test to the next. This test case class scrubs 

-

the list after each run to keep the tests isolated from each other. 

-

""" 

-

 

-

def setUp(self): 

-

TestCaseWithTempDir.setUp(self) 

-

self.sysmodulekeys = list(sys.modules) 

-

 

-

def tearDown(self): 

-

modstoscrub = [ 

-

modname 

-

for modname in sys.modules 

-

if modname not in self.sysmodulekeys 

-

] 

-

for modname in modstoscrub: 

-

del sys.modules[modname] 

-

TestCaseWithTempDir.tearDown(self) 

-

 

-

 

-

class CogIncludeTests(TestCaseWithImports): 

-

dincludes = { 

-

'test.cog': """\ 

-

//[[[cog 

-

import mymodule 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

//[[[cog 

-

import mymodule 

-

//]]] 

-

Hello from mymodule 

-

//[[[end]]] 

-

""", 

-

 

-

'test2.out': """\ 

-

//[[[cog 

-

import mymodule 

-

//]]] 

-

Hello from mymodule in inc2 

-

//[[[end]]] 

-

""", 

-

 

-

'include': { 

-

'mymodule.py': """\ 

-

import cog 

-

cog.outl("Hello from mymodule") 

-

""" 

-

}, 

-

 

-

'inc2': { 

-

'mymodule.py': """\ 

-

import cog 

-

cog.outl("Hello from mymodule in inc2") 

-

""" 

-

}, 

-

 

-

'inc3': { 

-

'someothermodule.py': """\ 

-

import cog 

-

cog.outl("This is some other module.") 

-

""" 

-

}, 

-

} 

-

 

-

def testNeedIncludePath(self): 

-

# Try it without the -I, to see that an ImportError happens. 

-

makeFiles(self.dincludes) 

-

with self.assertRaises(ImportError): 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

 

-

def testIncludePath(self): 

-

# Test that -I adds include directories properly. 

-

makeFiles(self.dincludes) 

-

self.cog.callableMain(['argv0', '-r', '-I', 'include', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testTwoIncludePaths(self): 

-

# Test that two -I's add include directories properly. 

-

makeFiles(self.dincludes) 

-

self.cog.callableMain(['argv0', '-r', '-I', 'include', '-I', 'inc2', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testTwoIncludePaths2(self): 

-

# Test that two -I's add include directories properly. 

-

makeFiles(self.dincludes) 

-

self.cog.callableMain(['argv0', '-r', '-I', 'inc2', '-I', 'include', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test2.out') 

-

 

-

def testUselessIncludePath(self): 

-

# Test that the search will continue past the first directory. 

-

makeFiles(self.dincludes) 

-

self.cog.callableMain(['argv0', '-r', '-I', 'inc3', '-I', 'include', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testSysPathIsUnchanged(self): 

-

d = { 

-

'bad.cog': """\ 

-

//[[[cog cog.error("Oh no!") ]]] 

-

//[[[end]]] 

-

""", 

-

'good.cog': """\ 

-

//[[[cog cog.outl("Oh yes!") ]]] 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

# Is it unchanged just by creating a cog engine? 

-

oldsyspath = sys.path[:] 

-

self.newCog() 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a successful run? 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-r', 'good.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a successful run with includes? 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', 'good.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a successful run with two includes? 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', '-I', 'quux', 'good.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a failed run? 

-

self.newCog() 

-

with self.assertRaises(CogError): 

-

self.cog.callableMain(['argv0', '-r', 'bad.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a failed run with includes? 

-

self.newCog() 

-

with self.assertRaises(CogError): 

-

self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', 'bad.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

# Is it unchanged for a failed run with two includes? 

-

self.newCog() 

-

with self.assertRaises(CogError): 

-

self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', '-I', 'quux', 'bad.cog']) 

-

self.assertEqual(oldsyspath, sys.path) 

-

 

-

def testSubDirectories(self): 

-

# Test that relative paths on the command line work, with includes. 

-

 

-

d = { 

-

'code': { 

-

'test.cog': """\ 

-

//[[[cog 

-

import mysubmodule 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

//[[[cog 

-

import mysubmodule 

-

//]]] 

-

Hello from mysubmodule 

-

//[[[end]]] 

-

""", 

-

 

-

'mysubmodule.py': """\ 

-

import cog 

-

cog.outl("Hello from mysubmodule") 

-

""" 

-

} 

-

} 

-

 

-

makeFiles(d) 

-

# We should be able to invoke cog without the -I switch, and it will 

-

# auto-include the current directory 

-

self.cog.callableMain(['argv0', '-r', 'code/test.cog']) 

-

self.assertFilesSame('code/test.cog', 'code/test.out') 

-

 

-

 

-

class CogTestsInFiles(TestCaseWithTempDir): 

-

 

-

def testWarnIfNoCogCode(self): 

-

# Test that the -e switch warns if there is no Cog code. 

-

d = { 

-

'with.cog': """\ 

-

//[[[cog 

-

cog.outl("hello world") 

-

//]]] 

-

hello world 

-

//[[[end]]] 

-

""", 

-

 

-

'without.cog': """\ 

-

There's no cog 

-

code in this file. 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-e', 'with.cog']) 

-

output = self.output.getvalue() 

-

self.assertNotIn("Warning", output) 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-e', 'without.cog']) 

-

output = self.output.getvalue() 

-

self.assertIn("Warning: no cog code found in without.cog", output) 

-

self.newCog() 

-

self.cog.callableMain(['argv0', 'without.cog']) 

-

output = self.output.getvalue() 

-

self.assertNotIn("Warning", output) 

-

 

-

def testFileNameProps(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

-

//]]] 

-

this is cog1.txt in, cog1.txt out 

-

[[[end]]] 

-

""", 

-

 

-

'cog1.out': """\ 

-

//[[[cog 

-

cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

-

//]]] 

-

This is cog1.txt in, cog1.txt out 

-

[[[end]]] 

-

""", 

-

 

-

'cog1out.out': """\ 

-

//[[[cog 

-

cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

-

//]]] 

-

This is cog1.txt in, cog1out.txt out 

-

[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

self.newCog() 

-

self.cog.callableMain(['argv0', '-o', 'cog1out.txt', 'cog1.txt']) 

-

self.assertFilesSame('cog1out.txt', 'cog1out.out') 

-

 

-

def testGlobalsDontCrossFiles(self): 

-

# Make sure that global values don't get shared between files. 

-

d = { 

-

'one.cog': """\ 

-

//[[[cog s = "This was set in one.cog" ]]] 

-

//[[[end]]] 

-

//[[[cog cog.outl(s) ]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'one.out': """\ 

-

//[[[cog s = "This was set in one.cog" ]]] 

-

//[[[end]]] 

-

//[[[cog cog.outl(s) ]]] 

-

This was set in one.cog 

-

//[[[end]]] 

-

""", 

-

 

-

'two.cog': """\ 

-

//[[[cog 

-

try: 

-

cog.outl(s) 

-

except NameError: 

-

cog.outl("s isn't set!") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'two.out': """\ 

-

//[[[cog 

-

try: 

-

cog.outl(s) 

-

except NameError: 

-

cog.outl("s isn't set!") 

-

//]]] 

-

s isn't set! 

-

//[[[end]]] 

-

""", 

-

 

-

'cogfiles.txt': """\ 

-

# Please run cog 

-

one.cog 

-

 

-

two.cog 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

-

self.assertFilesSame('one.cog', 'one.out') 

-

self.assertFilesSame('two.cog', 'two.out') 

-

output = self.output.getvalue() 

-

self.assertIn("(changed)", output) 

-

 

-

def testRemoveGeneratedOutput(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was generated.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] 

-

This line was not. 

-

""", 

-

 

-

'cog1.out': """\ 

-

//[[[cog 

-

cog.outl("This line was generated.") 

-

//]]] 

-

//[[[end]]] 

-

This line was not. 

-

""", 

-

 

-

'cog1.out2': """\ 

-

//[[[cog 

-

cog.outl("This line was generated.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] 

-

This line was not. 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

# Remove generated output. 

-

self.cog.callableMain(['argv0', '-r', '-x', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

self.newCog() 

-

# Regenerate the generated output. 

-

self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out2') 

-

self.newCog() 

-

# Remove the generated output again. 

-

self.cog.callableMain(['argv0', '-r', '-x', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

 

-

def testMsgCall(self): 

-

infile = """\ 

-

#[[[cog 

-

cog.msg("Hello there!") 

-

#]]] 

-

#[[[end]]] 

-

""" 

-

infile = reindentBlock(infile) 

-

self.assertEqual(self.cog.processString(infile), infile) 

-

output = self.output.getvalue() 

-

self.assertEqual(output, "Message: Hello there!\n") 

-

 

-

def testErrorMessageHasNoTraceback(self): 

-

# Test that a Cog error is printed to stderr with no traceback. 

-

 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

Xhis line was newly 

-

generated by cog 

-

blah blah. 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

stderr = StringIO() 

-

self.cog.setOutput(stderr=stderr) 

-

self.cog.main(['argv0', '-c', '-r', "cog1.txt"]) 

-

self.assertEqual(self.output.getvalue(), "Cogging cog1.txt\n") 

-

self.assertEqual(stderr.getvalue(), "cog1.txt(9): Output has been edited! Delete old checksum to unprotect.\n") 

-

 

-

def testDashD(self): 

-

d = { 

-

'test.cog': """\ 

-

--[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

-

--[[[end]]] 

-

""", 

-

 

-

'test.kablooey': """\ 

-

--[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

-

Defined fooey as kablooey 

-

--[[[end]]] 

-

""", 

-

 

-

'test.einstein': """\ 

-

--[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

-

Defined fooey as e=mc2 

-

--[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-D', 'fooey=kablooey', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.kablooey') 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-Dfooey=kablooey', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.kablooey') 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-Dfooey=e=mc2', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.einstein') 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-Dbar=quux', '-Dfooey=kablooey', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.kablooey') 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-Dfooey=kablooey', '-Dbar=quux', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.kablooey') 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-Dfooey=gooey', '-Dfooey=kablooey', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.kablooey') 

-

 

-

def testOutputToStdout(self): 

-

d = { 

-

'test.cog': """\ 

-

--[[[cog cog.outl('Hey there!') ]]] 

-

--[[[end]]] 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

stderr = StringIO() 

-

self.cog.setOutput(stderr=stderr) 

-

self.cog.callableMain(['argv0', 'test.cog']) 

-

output = self.output.getvalue() 

-

outerr = stderr.getvalue() 

-

self.assertEqual(output, "--[[[cog cog.outl('Hey there!') ]]]\nHey there!\n--[[[end]]]\n") 

-

self.assertEqual(outerr, "") 

-

 

-

def testReadFromStdin(self): 

-

stdin = StringIO("--[[[cog cog.outl('Wow') ]]]\n--[[[end]]]\n") 

-

def restore_stdin(old_stdin): 

-

sys.stdin = old_stdin 

-

self.addCleanup(restore_stdin, sys.stdin) 

-

sys.stdin = stdin 

-

 

-

stderr = StringIO() 

-

self.cog.setOutput(stderr=stderr) 

-

self.cog.callableMain(['argv0', '-']) 

-

output = self.output.getvalue() 

-

outerr = stderr.getvalue() 

-

self.assertEqual(output, "--[[[cog cog.outl('Wow') ]]]\nWow\n--[[[end]]]\n") 

-

self.assertEqual(outerr, "") 

-

 

-

 

-

def testSuffixOutputLines(self): 

-

d = { 

-

'test.cog': """\ 

-

Hey there. 

-

;[[[cog cog.outl('a\\nb\\n \\nc') ]]] 

-

;[[[end]]] 

-

Good bye. 

-

""", 

-

 

-

'test.out': """\ 

-

Hey there. 

-

;[[[cog cog.outl('a\\nb\\n \\nc') ]]] 

-

a (foo) 

-

b (foo) 

-

""" # These three trailing spaces are important. 

-

# The suffix is not applied to completely blank lines. 

-

""" 

-

c (foo) 

-

;[[[end]]] 

-

Good bye. 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-s', ' (foo)', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testEmptySuffix(self): 

-

d = { 

-

'test.cog': """\ 

-

;[[[cog cog.outl('a\\nb\\nc') ]]] 

-

;[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

;[[[cog cog.outl('a\\nb\\nc') ]]] 

-

a 

-

b 

-

c 

-

;[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-s', '', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testHellishSuffix(self): 

-

d = { 

-

'test.cog': """\ 

-

;[[[cog cog.outl('a\\n\\nb') ]]] 

-

""", 

-

 

-

'test.out': """\ 

-

;[[[cog cog.outl('a\\n\\nb') ]]] 

-

a /\\n*+([)]>< 

-

 

-

b /\\n*+([)]>< 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-z', '-r', '-s', r' /\n*+([)]><', 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

 

-

class WritabilityTests(TestCaseWithTempDir): 

-

 

-

d = { 

-

'test.cog': """\ 

-

//[[[cog 

-

for fn in ['DoSomething', 'DoAnotherThing', 'DoLastThing']: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

//[[[cog 

-

for fn in ['DoSomething', 'DoAnotherThing', 'DoLastThing']: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

void DoSomething(); 

-

void DoAnotherThing(); 

-

void DoLastThing(); 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

if os.name == 'nt': #pragma: no cover 

-

# for Windows 

-

cmd_w_args = 'attrib -R %s' 

-

cmd_w_asterisk = 'attrib -R *' 

-

else: #pragma: no cover 

-

# for unix-like 

-

cmd_w_args = 'chmod +w %s' 

-

cmd_w_asterisk = 'chmod +w *' 

-

 

-

def setUp(self): 

-

TestCaseWithTempDir.setUp(self) 

-

makeFiles(self.d) 

-

self.testcog = os.path.join(self.tempdir, 'test.cog') 

-

os.chmod(self.testcog, stat.S_IREAD) # Make the file readonly. 

-

assert not os.access(self.testcog, os.W_OK) 

-

 

-

def tearDown(self): 

-

os.chmod(self.testcog, stat.S_IWRITE) # Make the file writable again. 

-

TestCaseWithTempDir.tearDown(self) 

-

 

-

def testReadonlyNoCommand(self): 

-

with self.assertRaisesRegexp(CogError, "Can't overwrite test.cog"): 

-

self.cog.callableMain(['argv0', '-r', 'test.cog']) 

-

assert not os.access(self.testcog, os.W_OK) 

-

 

-

def testReadonlyWithCommand(self): 

-

self.cog.callableMain(['argv0', '-r', '-w', self.cmd_w_args, 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

assert os.access(self.testcog, os.W_OK) 

-

 

-

def testReadonlyWithCommandWithNoSlot(self): 

-

self.cog.callableMain(['argv0', '-r', '-w', self.cmd_w_asterisk, 'test.cog']) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

assert os.access(self.testcog, os.W_OK) 

-

 

-

def testReadonlyWithIneffectualCommand(self): 

-

with self.assertRaisesRegexp(CogError, "Couldn't make test.cog writable"): 

-

self.cog.callableMain(['argv0', '-r', '-w', 'echo %s', 'test.cog']) 

-

assert not os.access(self.testcog, os.W_OK) 

-

 

-

 

-

class ChecksumTests(TestCaseWithTempDir): 

-

 

-

def testCreateChecksumOutput(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was generated.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] 

-

This line was not. 

-

""", 

-

 

-

'cog1.out': """\ 

-

//[[[cog 

-

cog.outl("This line was generated.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) 

-

This line was not. 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-c', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

 

-

def testCheckChecksumOutput(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) 

-

""", 

-

 

-

'cog1.out': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was newly 

-

generated by cog 

-

blah blah. 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', '-c', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

 

-

def testRemoveChecksumOutput(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was generated. 

-

//[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) fooey 

-

""", 

-

 

-

'cog1.out': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was newly 

-

generated by cog 

-

blah blah. 

-

//[[[end]]] fooey 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

-

self.assertFilesSame('cog1.txt', 'cog1.out') 

-

 

-

def testTamperedChecksumOutput(self): 

-

d = { 

-

'cog1.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

Xhis line was newly 

-

generated by cog 

-

blah blah. 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

 

-

'cog2.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was newly 

-

generated by cog 

-

blah blah! 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

 

-

'cog3.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

 

-

This line was newly 

-

generated by cog 

-

blah blah. 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

 

-

'cog4.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was newly 

-

generated by cog 

-

blah blah.. 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

 

-

'cog5.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

This line was newly 

-

generated by cog 

-

blah blah. 

-

extra 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

 

-

'cog6.txt': """\ 

-

//[[[cog 

-

cog.outl("This line was newly") 

-

cog.outl("generated by cog") 

-

cog.outl("blah blah.") 

-

//]]] 

-

//[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog1.txt\(9\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog1.txt"]) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog2.txt\(9\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog2.txt"]) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog3.txt\(10\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog3.txt"]) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog4.txt\(9\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog4.txt"]) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog5.txt\(10\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog5.txt"]) 

-

with self.assertRaisesRegexp(CogError, 

-

r"cog6.txt\(6\): Output has been edited! Delete old checksum to unprotect."): 

-

self.cog.callableMain(['argv0', '-c', "cog6.txt"]) 

-

 

-

def testArgvIsntModified(self): 

-

argv = ['argv0', '-v'] 

-

orig_argv = argv[:] 

-

self.cog.callableMain(argv) 

-

self.assertEqual(argv, orig_argv) 

-

 

-

 

-

class CustomMarkerTests(TestCaseWithTempDir): 

-

 

-

def testCustomerMarkers(self): 

-

d = { 

-

'test.cog': """\ 

-

//{{ 

-

cog.outl("void %s();" % "MyFunction") 

-

//}} 

-

//{{end}} 

-

""", 

-

 

-

'test.out': """\ 

-

//{{ 

-

cog.outl("void %s();" % "MyFunction") 

-

//}} 

-

void MyFunction(); 

-

//{{end}} 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain([ 

-

'argv0', '-r', 

-

'--markers={{ }} {{end}}', 

-

'test.cog' 

-

]) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testTrulyWackyMarkers(self): 

-

# Make sure the markers are properly re-escaped. 

-

d = { 

-

'test.cog': """\ 

-

//**( 

-

cog.outl("void %s();" % "MyFunction") 

-

//**) 

-

//**(end)** 

-

""", 

-

 

-

'test.out': """\ 

-

//**( 

-

cog.outl("void %s();" % "MyFunction") 

-

//**) 

-

void MyFunction(); 

-

//**(end)** 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain([ 

-

'argv0', '-r', 

-

'--markers=**( **) **(end)**', 

-

'test.cog' 

-

]) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

def testChangeJustOneMarker(self): 

-

d = { 

-

'test.cog': """\ 

-

//**( 

-

cog.outl("void %s();" % "MyFunction") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

 

-

'test.out': """\ 

-

//**( 

-

cog.outl("void %s();" % "MyFunction") 

-

//]]] 

-

void MyFunction(); 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain([ 

-

'argv0', '-r', 

-

'--markers=**( ]]] [[[end]]]', 

-

'test.cog' 

-

]) 

-

self.assertFilesSame('test.cog', 'test.out') 

-

 

-

 

-

class BlakeTests(TestCaseWithTempDir): 

-

 

-

# Blake Winton's contributions. 

-

def testDeleteCode(self): 

-

# -o sets the output file. 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

Some Sample Code Here 

-

//[[[end]]]Data Data 

-

And Some More 

-

""", 

-

 

-

'test.out': """\ 

-

// This is my C++ file. 

-

void DoSomething(); 

-

void DoAnotherThing(); 

-

void DoLastThing(); 

-

And Some More 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.callableMain(['argv0', '-d', '-o', 'test.cogged', 'test.cog']) 

-

self.assertFilesSame('test.cogged', 'test.out') 

-

 

-

def testDeleteCodeWithDashRFails(self): 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

""" 

-

} 

-

 

-

makeFiles(d) 

-

with self.assertRaises(CogUsageError): 

-

self.cog.callableMain(['argv0', '-r', '-d', 'test.cog']) 

-

 

-

def testSettingGlobals(self): 

-

# Blake Winton contributed a way to set the globals that will be used in 

-

# processFile(). 

-

d = { 

-

'test.cog': """\ 

-

// This is my C++ file. 

-

//[[[cog 

-

for fn in fnames: 

-

cog.outl("void %s();" % fn) 

-

//]]] 

-

Some Sample Code Here 

-

//[[[end]]]""", 

-

 

-

'test.out': """\ 

-

// This is my C++ file. 

-

void DoBlake(); 

-

void DoWinton(); 

-

void DoContribution(); 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

globals = {} 

-

globals['fnames'] = ['DoBlake', 'DoWinton', 'DoContribution'] 

-

self.cog.options.bDeleteCode = True 

-

self.cog.processFile('test.cog', 'test.cogged', globals=globals) 

-

self.assertFilesSame('test.cogged', 'test.out') 

-

 

-

 

-

class ErrorCallTests(TestCaseWithTempDir): 

-

 

-

def testErrorCallHasNoTraceback(self): 

-

# Test that cog.error() doesn't show a traceback. 

-

d = { 

-

'error.cog': """\ 

-

//[[[cog 

-

cog.error("Something Bad!") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.main(['argv0', '-r', 'error.cog']) 

-

output = self.output.getvalue() 

-

self.assertEqual(output, "Cogging error.cog\nError: Something Bad!\n") 

-

 

-

def testRealErrorHasTraceback(self): 

-

# Test that a genuine error does show a traceback. 

-

d = { 

-

'error.cog': """\ 

-

//[[[cog 

-

raise RuntimeError("Hey!") 

-

//]]] 

-

//[[[end]]] 

-

""", 

-

} 

-

 

-

makeFiles(d) 

-

self.cog.main(['argv0', '-r', 'error.cog']) 

-

output = self.output.getvalue() 

-

msg = 'Actual output:\n' + output 

-

self.assert_(output.startswith("Cogging error.cog\nTraceback (most recent"), msg) 

-

self.assertIn("RuntimeError: Hey!", output) 

-

 

-

 

-

# Things not yet tested: 

-

# - A bad -w command (currently fails silently). 

- -
+

1""" Test cogapp. 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2019, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9import os 

+

10import os.path 

+

11import random 

+

12import re 

+

13import shutil 

+

14import stat 

+

15import sys 

+

16import tempfile 

+

17import threading 

+

18 

+

19from .backward import StringIO, to_bytes, TestCase, PY3 

+

20from .cogapp import Cog, CogOptions, CogGenerator 

+

21from .cogapp import CogError, CogUsageError, CogGeneratedError, CogUserException 

+

22from .cogapp import usage, __version__, main 

+

23from .makefiles import * 

+

24from .whiteutils import reindentBlock 

+

25 

+

26 

+

27class CogTestsInMemory(TestCase): 

+

28 """ Test cases for cogapp.Cog() 

+

29 """ 

+

30 

+

31 def testNoCog(self): 

+

32 strings = [ 

+

33 '', 

+

34 ' ', 

+

35 ' \t \t \tx', 

+

36 'hello', 

+

37 'the cat\nin the\nhat.', 

+

38 'Horton\n\tHears A\n\t\tWho' 

+

39 ] 

+

40 for s in strings: 

+

41 self.assertEqual(Cog().processString(s), s) 

+

42 

+

43 def testSimple(self): 

+

44 infile = """\ 

+

45 Some text. 

+

46 //[[[cog 

+

47 import cog 

+

48 cog.outl("This is line one\\n") 

+

49 cog.outl("This is line two") 

+

50 //]]] 

+

51 gobbledegook. 

+

52 //[[[end]]] 

+

53 epilogue. 

+

54 """ 

+

55 

+

56 outfile = """\ 

+

57 Some text. 

+

58 //[[[cog 

+

59 import cog 

+

60 cog.outl("This is line one\\n") 

+

61 cog.outl("This is line two") 

+

62 //]]] 

+

63 This is line one 

+

64 

+

65 This is line two 

+

66 //[[[end]]] 

+

67 epilogue. 

+

68 """ 

+

69 

+

70 self.assertEqual(Cog().processString(infile), outfile) 

+

71 

+

72 def testEmptyCog(self): 

+

73 # The cog clause can be totally empty. Not sure why you'd want it, 

+

74 # but it works. 

+

75 infile = """\ 

+

76 hello 

+

77 //[[[cog 

+

78 //]]] 

+

79 //[[[end]]] 

+

80 goodbye 

+

81 """ 

+

82 

+

83 infile = reindentBlock(infile) 

+

84 self.assertEqual(Cog().processString(infile), infile) 

+

85 

+

86 def testMultipleCogs(self): 

+

87 # One file can have many cog chunks, even abutting each other. 

+

88 infile = """\ 

+

89 //[[[cog 

+

90 cog.out("chunk1") 

+

91 //]]] 

+

92 chunk1 

+

93 //[[[end]]] 

+

94 //[[[cog 

+

95 cog.out("chunk2") 

+

96 //]]] 

+

97 chunk2 

+

98 //[[[end]]] 

+

99 between chunks 

+

100 //[[[cog 

+

101 cog.out("chunk3") 

+

102 //]]] 

+

103 chunk3 

+

104 //[[[end]]] 

+

105 """ 

+

106 

+

107 infile = reindentBlock(infile) 

+

108 self.assertEqual(Cog().processString(infile), infile) 

+

109 

+

110 def testTrimBlankLines(self): 

+

111 infile = """\ 

+

112 //[[[cog 

+

113 cog.out("This is line one\\n", trimblanklines=True) 

+

114 cog.out(''' 

+

115 This is line two 

+

116 ''', dedent=True, trimblanklines=True) 

+

117 cog.outl("This is line three", trimblanklines=True) 

+

118 //]]] 

+

119 This is line one 

+

120 This is line two 

+

121 This is line three 

+

122 //[[[end]]] 

+

123 """ 

+

124 

+

125 infile = reindentBlock(infile) 

+

126 self.assertEqual(Cog().processString(infile), infile) 

+

127 

+

128 def testTrimEmptyBlankLines(self): 

+

129 infile = """\ 

+

130 //[[[cog 

+

131 cog.out("This is line one\\n", trimblanklines=True) 

+

132 cog.out(''' 

+

133 This is line two 

+

134 ''', dedent=True, trimblanklines=True) 

+

135 cog.out('', dedent=True, trimblanklines=True) 

+

136 cog.outl("This is line three", trimblanklines=True) 

+

137 //]]] 

+

138 This is line one 

+

139 This is line two 

+

140 This is line three 

+

141 //[[[end]]] 

+

142 """ 

+

143 

+

144 infile = reindentBlock(infile) 

+

145 self.assertEqual(Cog().processString(infile), infile) 

+

146 

+

147 def testTrimBlankLinesWithLastPartial(self): 

+

148 infile = """\ 

+

149 //[[[cog 

+

150 cog.out("This is line one\\n", trimblanklines=True) 

+

151 cog.out("\\nLine two\\nLine three", trimblanklines=True) 

+

152 //]]] 

+

153 This is line one 

+

154 Line two 

+

155 Line three 

+

156 //[[[end]]] 

+

157 """ 

+

158 

+

159 infile = reindentBlock(infile) 

+

160 self.assertEqual(Cog().processString(infile), infile) 

+

161 

+

162 def testCogOutDedent(self): 

+

163 infile = """\ 

+

164 //[[[cog 

+

165 cog.out("This is the first line\\n") 

+

166 cog.out(''' 

+

167 This is dedent=True 1 

+

168 This is dedent=True 2 

+

169 ''', dedent=True, trimblanklines=True) 

+

170 cog.out(''' 

+

171 This is dedent=False 1 

+

172 This is dedent=False 2 

+

173 ''', dedent=False, trimblanklines=True) 

+

174 cog.out(''' 

+

175 This is dedent=default 1 

+

176 This is dedent=default 2 

+

177 ''', trimblanklines=True) 

+

178 cog.out("This is the last line\\n") 

+

179 //]]] 

+

180 This is the first line 

+

181 This is dedent=True 1 

+

182 This is dedent=True 2 

+

183 This is dedent=False 1 

+

184 This is dedent=False 2 

+

185 This is dedent=default 1 

+

186 This is dedent=default 2 

+

187 This is the last line 

+

188 //[[[end]]] 

+

189 """ 

+

190 

+

191 infile = reindentBlock(infile) 

+

192 self.assertEqual(Cog().processString(infile), infile) 

+

193 

+

194 def test22EndOfLine(self): 

+

195 # In Python 2.2, this cog file was not parsing because the 

+

196 # last line is indented but didn't end with a newline. 

+

197 infile = """\ 

+

198 //[[[cog 

+

199 import cog 

+

200 for i in range(3): 

+

201 cog.out("%d\\n" % i) 

+

202 //]]] 

+

203 0 

+

204 1 

+

205 2 

+

206 //[[[end]]] 

+

207 """ 

+

208 

+

209 infile = reindentBlock(infile) 

+

210 self.assertEqual(Cog().processString(infile), infile) 

+

211 

+

212 def testIndentedCode(self): 

+

213 infile = """\ 

+

214 first line 

+

215 [[[cog 

+

216 import cog 

+

217 for i in range(3): 

+

218 cog.out("xx%d\\n" % i) 

+

219 ]]] 

+

220 xx0 

+

221 xx1 

+

222 xx2 

+

223 [[[end]]] 

+

224 last line 

+

225 """ 

+

226 

+

227 infile = reindentBlock(infile) 

+

228 self.assertEqual(Cog().processString(infile), infile) 

+

229 

+

230 def testPrefixedCode(self): 

+

231 infile = """\ 

+

232 --[[[cog 

+

233 --import cog 

+

234 --for i in range(3): 

+

235 -- cog.out("xx%d\\n" % i) 

+

236 --]]] 

+

237 xx0 

+

238 xx1 

+

239 xx2 

+

240 --[[[end]]] 

+

241 """ 

+

242 

+

243 infile = reindentBlock(infile) 

+

244 self.assertEqual(Cog().processString(infile), infile) 

+

245 

+

246 def testPrefixedIndentedCode(self): 

+

247 infile = """\ 

+

248 prologue 

+

249 --[[[cog 

+

250 -- import cog 

+

251 -- for i in range(3): 

+

252 -- cog.out("xy%d\\n" % i) 

+

253 --]]] 

+

254 xy0 

+

255 xy1 

+

256 xy2 

+

257 --[[[end]]] 

+

258 """ 

+

259 

+

260 infile = reindentBlock(infile) 

+

261 self.assertEqual(Cog().processString(infile), infile) 

+

262 

+

263 def testBogusPrefixMatch(self): 

+

264 infile = """\ 

+

265 prologue 

+

266 #[[[cog 

+

267 import cog 

+

268 # This comment should not be clobbered by removing the pound sign. 

+

269 for i in range(3): 

+

270 cog.out("xy%d\\n" % i) 

+

271 #]]] 

+

272 xy0 

+

273 xy1 

+

274 xy2 

+

275 #[[[end]]] 

+

276 """ 

+

277 

+

278 infile = reindentBlock(infile) 

+

279 self.assertEqual(Cog().processString(infile), infile) 

+

280 

+

281 def testNoFinalNewline(self): 

+

282 # If the cog'ed output has no final newline, 

+

283 # it shouldn't eat up the cog terminator. 

+

284 infile = """\ 

+

285 prologue 

+

286 [[[cog 

+

287 import cog 

+

288 for i in range(3): 

+

289 cog.out("%d" % i) 

+

290 ]]] 

+

291 012 

+

292 [[[end]]] 

+

293 epilogue 

+

294 """ 

+

295 

+

296 infile = reindentBlock(infile) 

+

297 self.assertEqual(Cog().processString(infile), infile) 

+

298 

+

299 def testNoOutputAtAll(self): 

+

300 # If there is absolutely no cog output, that's ok. 

+

301 infile = """\ 

+

302 prologue 

+

303 [[[cog 

+

304 i = 1 

+

305 ]]] 

+

306 [[[end]]] 

+

307 epilogue 

+

308 """ 

+

309 

+

310 infile = reindentBlock(infile) 

+

311 self.assertEqual(Cog().processString(infile), infile) 

+

312 

+

313 def testPurelyBlankLine(self): 

+

314 # If there is a blank line in the cog code with no whitespace 

+

315 # prefix, that should be OK. 

+

316 

+

317 infile = """\ 

+

318 prologue 

+

319 [[[cog 

+

320 import sys 

+

321 cog.out("Hello") 

+

322 $ 

+

323 cog.out("There") 

+

324 ]]] 

+

325 HelloThere 

+

326 [[[end]]] 

+

327 epilogue 

+

328 """ 

+

329 

+

330 infile = reindentBlock(infile.replace('$', '')) 

+

331 self.assertEqual(Cog().processString(infile), infile) 

+

332 

+

333 def testEmptyOutl(self): 

+

334 # Alexander Belchenko suggested the string argument to outl should 

+

335 # be optional. Does it work? 

+

336 

+

337 infile = """\ 

+

338 prologue 

+

339 [[[cog 

+

340 cog.outl("x") 

+

341 cog.outl() 

+

342 cog.outl("y") 

+

343 cog.out() # Also optional, a complete no-op. 

+

344 cog.outl(trimblanklines=True) 

+

345 cog.outl("z") 

+

346 ]]] 

+

347 x 

+

348 

+

349 y 

+

350 

+

351 z 

+

352 [[[end]]] 

+

353 epilogue 

+

354 """ 

+

355 

+

356 infile = reindentBlock(infile) 

+

357 self.assertEqual(Cog().processString(infile), infile) 

+

358 

+

359 def testFirstLineNum(self): 

+

360 infile = """\ 

+

361 fooey 

+

362 [[[cog 

+

363 cog.outl("started at line number %d" % cog.firstLineNum) 

+

364 ]]] 

+

365 started at line number 2 

+

366 [[[end]]] 

+

367 blah blah 

+

368 [[[cog 

+

369 cog.outl("and again at line %d" % cog.firstLineNum) 

+

370 ]]] 

+

371 and again at line 8 

+

372 [[[end]]] 

+

373 """ 

+

374 

+

375 infile = reindentBlock(infile) 

+

376 self.assertEqual(Cog().processString(infile), infile) 

+

377 

+

378 def testCompactOneLineCode(self): 

+

379 infile = """\ 

+

380 first line 

+

381 hey: [[[cog cog.outl("hello %d" % (3*3*3*3)) ]]] looky! 

+

382 get rid of this! 

+

383 [[[end]]] 

+

384 last line 

+

385 """ 

+

386 

+

387 outfile = """\ 

+

388 first line 

+

389 hey: [[[cog cog.outl("hello %d" % (3*3*3*3)) ]]] looky! 

+

390 hello 81 

+

391 [[[end]]] 

+

392 last line 

+

393 """ 

+

394 

+

395 infile = reindentBlock(infile) 

+

396 self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

+

397 

+

398 def testInsideOutCompact(self): 

+

399 infile = """\ 

+

400 first line 

+

401 hey?: ]]] what is this? [[[cog strange! 

+

402 get rid of this! 

+

403 [[[end]]] 

+

404 last line 

+

405 """ 

+

406 with self.assertRaisesRegex(CogError, r"^infile.txt\(2\): Cog code markers inverted$"): 

+

407 Cog().processString(reindentBlock(infile), "infile.txt") 

+

408 

+

409 def testSharingGlobals(self): 

+

410 infile = """\ 

+

411 first line 

+

412 hey: [[[cog s="hey there" ]]] looky! 

+

413 [[[end]]] 

+

414 more literal junk. 

+

415 [[[cog cog.outl(s) ]]] 

+

416 [[[end]]] 

+

417 last line 

+

418 """ 

+

419 

+

420 outfile = """\ 

+

421 first line 

+

422 hey: [[[cog s="hey there" ]]] looky! 

+

423 [[[end]]] 

+

424 more literal junk. 

+

425 [[[cog cog.outl(s) ]]] 

+

426 hey there 

+

427 [[[end]]] 

+

428 last line 

+

429 """ 

+

430 

+

431 infile = reindentBlock(infile) 

+

432 self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

+

433 

+

434 def testAssertInCogCode(self): 

+

435 # Check that we can test assertions in cog code in the test framework. 

+

436 infile = """\ 

+

437 [[[cog 

+

438 assert 1 == 2, "Oops" 

+

439 ]]] 

+

440 [[[end]]] 

+

441 """ 

+

442 infile = reindentBlock(infile) 

+

443 with self.assertRaisesRegex(CogUserException, "AssertionError: Oops"): 

+

444 Cog().processString(infile) 

+

445 

+

446 def testCogPrevious(self): 

+

447 # Check that we can access the previous run's output. 

+

448 infile = """\ 

+

449 [[[cog 

+

450 assert cog.previous == "Hello there!\\n", "WTF??" 

+

451 cog.out(cog.previous) 

+

452 cog.outl("Ran again!") 

+

453 ]]] 

+

454 Hello there! 

+

455 [[[end]]] 

+

456 """ 

+

457 

+

458 outfile = """\ 

+

459 [[[cog 

+

460 assert cog.previous == "Hello there!\\n", "WTF??" 

+

461 cog.out(cog.previous) 

+

462 cog.outl("Ran again!") 

+

463 ]]] 

+

464 Hello there! 

+

465 Ran again! 

+

466 [[[end]]] 

+

467 """ 

+

468 

+

469 infile = reindentBlock(infile) 

+

470 self.assertEqual(Cog().processString(infile), reindentBlock(outfile)) 

+

471 

+

472 

+

473class CogOptionsTests(TestCase): 

+

474 """ Test the CogOptions class. 

+

475 """ 

+

476 

+

477 def testEquality(self): 

+

478 o = CogOptions() 

+

479 p = CogOptions() 

+

480 self.assertEqual(o, p) 

+

481 o.parseArgs(['-r']) 

+

482 self.assertNotEqual(o, p) 

+

483 p.parseArgs(['-r']) 

+

484 self.assertEqual(o, p) 

+

485 

+

486 def testCloning(self): 

+

487 o = CogOptions() 

+

488 o.parseArgs(['-I', 'fooey', '-I', 'booey', '-s', ' /*x*/']) 

+

489 p = o.clone() 

+

490 self.assertEqual(o, p) 

+

491 p.parseArgs(['-I', 'huey', '-D', 'foo=quux']) 

+

492 self.assertNotEqual(o, p) 

+

493 q = CogOptions() 

+

494 q.parseArgs(['-I', 'fooey', '-I', 'booey', '-s', ' /*x*/', '-I', 'huey', '-D', 'foo=quux']) 

+

495 self.assertEqual(p, q) 

+

496 

+

497 def testCombiningFlags(self): 

+

498 # Single-character flags can be combined. 

+

499 o = CogOptions() 

+

500 o.parseArgs(['-e', '-r', '-z']) 

+

501 p = CogOptions() 

+

502 p.parseArgs(['-erz']) 

+

503 self.assertEqual(o, p) 

+

504 

+

505 def testMarkers(self): 

+

506 o = CogOptions() 

+

507 o._parse_markers('a b c') 

+

508 self.assertEqual('a', o.sBeginSpec) 

+

509 self.assertEqual('b', o.sEndSpec) 

+

510 self.assertEqual('c', o.sEndOutput) 

+

511 

+

512 def testMarkersSwitch(self): 

+

513 o = CogOptions() 

+

514 o.parseArgs(['--markers', 'a b c']) 

+

515 self.assertEqual('a', o.sBeginSpec) 

+

516 self.assertEqual('b', o.sEndSpec) 

+

517 self.assertEqual('c', o.sEndOutput) 

+

518 

+

519 

+

520class FileStructureTests(TestCase): 

+

521 """ Test cases to check that we're properly strict about the structure 

+

522 of files. 

+

523 """ 

+

524 

+

525 def isBad(self, infile, msg=None): 

+

526 infile = reindentBlock(infile) 

+

527 with self.assertRaisesRegex(CogError, "^"+re.escape(msg)+"$"): 

+

528 Cog().processString(infile, 'infile.txt') 

+

529 

+

530 def testBeginNoEnd(self): 

+

531 infile = """\ 

+

532 Fooey 

+

533 #[[[cog 

+

534 cog.outl('hello') 

+

535 """ 

+

536 self.isBad(infile, "infile.txt(2): Cog block begun but never ended.") 

+

537 

+

538 def testNoEoo(self): 

+

539 infile = """\ 

+

540 Fooey 

+

541 #[[[cog 

+

542 cog.outl('hello') 

+

543 #]]] 

+

544 """ 

+

545 self.isBad(infile, "infile.txt(4): Missing '[[[end]]]' before end of file.") 

+

546 

+

547 infile2 = """\ 

+

548 Fooey 

+

549 #[[[cog 

+

550 cog.outl('hello') 

+

551 #]]] 

+

552 #[[[cog 

+

553 cog.outl('goodbye') 

+

554 #]]] 

+

555 """ 

+

556 self.isBad(infile2, "infile.txt(5): Unexpected '[[[cog'") 

+

557 

+

558 def testStartWithEnd(self): 

+

559 infile = """\ 

+

560 #]]] 

+

561 """ 

+

562 self.isBad(infile, "infile.txt(1): Unexpected ']]]'") 

+

563 

+

564 infile2 = """\ 

+

565 #[[[cog 

+

566 cog.outl('hello') 

+

567 #]]] 

+

568 #[[[end]]] 

+

569 #]]] 

+

570 """ 

+

571 self.isBad(infile2, "infile.txt(5): Unexpected ']]]'") 

+

572 

+

573 def testStartWithEoo(self): 

+

574 infile = """\ 

+

575 #[[[end]]] 

+

576 """ 

+

577 self.isBad(infile, "infile.txt(1): Unexpected '[[[end]]]'") 

+

578 

+

579 infile2 = """\ 

+

580 #[[[cog 

+

581 cog.outl('hello') 

+

582 #]]] 

+

583 #[[[end]]] 

+

584 #[[[end]]] 

+

585 """ 

+

586 self.isBad(infile2, "infile.txt(5): Unexpected '[[[end]]]'") 

+

587 

+

588 def testNoEnd(self): 

+

589 infile = """\ 

+

590 #[[[cog 

+

591 cog.outl("hello") 

+

592 #[[[end]]] 

+

593 """ 

+

594 self.isBad(infile, "infile.txt(3): Unexpected '[[[end]]]'") 

+

595 

+

596 infile2 = """\ 

+

597 #[[[cog 

+

598 cog.outl('hello') 

+

599 #]]] 

+

600 #[[[end]]] 

+

601 #[[[cog 

+

602 cog.outl("hello") 

+

603 #[[[end]]] 

+

604 """ 

+

605 self.isBad(infile2, "infile.txt(7): Unexpected '[[[end]]]'") 

+

606 

+

607 def testTwoBegins(self): 

+

608 infile = """\ 

+

609 #[[[cog 

+

610 #[[[cog 

+

611 cog.outl("hello") 

+

612 #]]] 

+

613 #[[[end]]] 

+

614 """ 

+

615 self.isBad(infile, "infile.txt(2): Unexpected '[[[cog'") 

+

616 

+

617 infile2 = """\ 

+

618 #[[[cog 

+

619 cog.outl("hello") 

+

620 #]]] 

+

621 #[[[end]]] 

+

622 #[[[cog 

+

623 #[[[cog 

+

624 cog.outl("hello") 

+

625 #]]] 

+

626 #[[[end]]] 

+

627 """ 

+

628 self.isBad(infile2, "infile.txt(6): Unexpected '[[[cog'") 

+

629 

+

630 def testTwoEnds(self): 

+

631 infile = """\ 

+

632 #[[[cog 

+

633 cog.outl("hello") 

+

634 #]]] 

+

635 #]]] 

+

636 #[[[end]]] 

+

637 """ 

+

638 self.isBad(infile, "infile.txt(4): Unexpected ']]]'") 

+

639 

+

640 infile2 = """\ 

+

641 #[[[cog 

+

642 cog.outl("hello") 

+

643 #]]] 

+

644 #[[[end]]] 

+

645 #[[[cog 

+

646 cog.outl("hello") 

+

647 #]]] 

+

648 #]]] 

+

649 #[[[end]]] 

+

650 """ 

+

651 self.isBad(infile2, "infile.txt(8): Unexpected ']]]'") 

+

652 

+

653 

+

654class CogErrorTests(TestCase): 

+

655 """ Test cases for cog.error(). 

+

656 """ 

+

657 

+

658 def testErrorMsg(self): 

+

659 infile = """\ 

+

660 [[[cog cog.error("This ain't right!")]]] 

+

661 [[[end]]] 

+

662 """ 

+

663 

+

664 infile = reindentBlock(infile) 

+

665 with self.assertRaisesRegex(CogGeneratedError, "^This ain't right!$"): 

+

666 Cog().processString(infile) 

+

667 

+

668 def testErrorNoMsg(self): 

+

669 infile = """\ 

+

670 [[[cog cog.error()]]] 

+

671 [[[end]]] 

+

672 """ 

+

673 

+

674 infile = reindentBlock(infile) 

+

675 with self.assertRaisesRegex(CogGeneratedError, "^Error raised by cog generator.$"): 

+

676 Cog().processString(infile) 

+

677 

+

678 def testNoErrorIfErrorNotCalled(self): 

+

679 infile = """\ 

+

680 --[[[cog 

+

681 --import cog 

+

682 --for i in range(3): 

+

683 -- if i > 10: 

+

684 -- cog.error("Something is amiss!") 

+

685 -- cog.out("xx%d\\n" % i) 

+

686 --]]] 

+

687 xx0 

+

688 xx1 

+

689 xx2 

+

690 --[[[end]]] 

+

691 """ 

+

692 

+

693 infile = reindentBlock(infile) 

+

694 self.assertEqual(Cog().processString(infile), infile) 

+

695 

+

696 

+

697class CogGeneratorGetCodeTests(TestCase): 

+

698 """ Unit tests against CogGenerator to see if its getCode() method works 

+

699 properly. 

+

700 """ 

+

701 

+

702 def setUp(self): 

+

703 """ All tests get a generator to use, and short same-length names for 

+

704 the functions we're going to use. 

+

705 """ 

+

706 self.gen = CogGenerator() 

+

707 self.m = self.gen.parseMarker 

+

708 self.l = self.gen.parseLine 

+

709 

+

710 def testEmpty(self): 

+

711 self.m('// [[[cog') 

+

712 self.m('// ]]]') 

+

713 self.assertEqual(self.gen.getCode(), '') 

+

714 

+

715 def testSimple(self): 

+

716 self.m('// [[[cog') 

+

717 self.l(' print "hello"') 

+

718 self.l(' print "bye"') 

+

719 self.m('// ]]]') 

+

720 self.assertEqual(self.gen.getCode(), 'print "hello"\nprint "bye"') 

+

721 

+

722 def testCompressed1(self): 

+

723 # For a while, I supported compressed code blocks, but no longer. 

+

724 self.m('// [[[cog: print """') 

+

725 self.l('// hello') 

+

726 self.l('// bye') 

+

727 self.m('// """)]]]') 

+

728 self.assertEqual(self.gen.getCode(), 'hello\nbye') 

+

729 

+

730 def testCompressed2(self): 

+

731 # For a while, I supported compressed code blocks, but no longer. 

+

732 self.m('// [[[cog: print """') 

+

733 self.l('hello') 

+

734 self.l('bye') 

+

735 self.m('// """)]]]') 

+

736 self.assertEqual(self.gen.getCode(), 'hello\nbye') 

+

737 

+

738 def testCompressed3(self): 

+

739 # For a while, I supported compressed code blocks, but no longer. 

+

740 self.m('// [[[cog') 

+

741 self.l('print """hello') 

+

742 self.l('bye') 

+

743 self.m('// """)]]]') 

+

744 self.assertEqual(self.gen.getCode(), 'print """hello\nbye') 

+

745 

+

746 def testCompressed4(self): 

+

747 # For a while, I supported compressed code blocks, but no longer. 

+

748 self.m('// [[[cog: print """') 

+

749 self.l('hello') 

+

750 self.l('bye""")') 

+

751 self.m('// ]]]') 

+

752 self.assertEqual(self.gen.getCode(), 'hello\nbye""")') 

+

753 

+

754 def testNoCommonPrefixForMarkers(self): 

+

755 # It's important to be able to use #if 0 to hide lines from a 

+

756 # C++ compiler. 

+

757 self.m('#if 0 //[[[cog') 

+

758 self.l('\timport cog, sys') 

+

759 self.l('') 

+

760 self.l('\tprint sys.argv') 

+

761 self.m('#endif //]]]') 

+

762 self.assertEqual(self.gen.getCode(), 'import cog, sys\n\nprint sys.argv') 

+

763 

+

764 

+

765class TestCaseWithTempDir(TestCase): 

+

766 

+

767 def newCog(self): 

+

768 """ Initialize the cog members for another run. 

+

769 """ 

+

770 # Create a cog engine, and catch its output. 

+

771 self.cog = Cog() 

+

772 self.output = StringIO() 

+

773 self.cog.setOutput(stdout=self.output, stderr=self.output) 

+

774 

+

775 def setUp(self): 

+

776 # Create a temporary directory. 

+

777 self.tempdir = os.path.join(tempfile.gettempdir(), 'testcog_tempdir_' + str(random.random())[2:]) 

+

778 os.mkdir(self.tempdir) 

+

779 self.olddir = os.getcwd() 

+

780 os.chdir(self.tempdir) 

+

781 self.newCog() 

+

782 

+

783 def tearDown(self): 

+

784 os.chdir(self.olddir) 

+

785 # Get rid of the temporary directory. 

+

786 shutil.rmtree(self.tempdir) 

+

787 

+

788 def assertFilesSame(self, sFName1, sFName2): 

+

789 text1 = open(os.path.join(self.tempdir, sFName1), 'rb').read() 

+

790 text2 = open(os.path.join(self.tempdir, sFName2), 'rb').read() 

+

791 self.assertEqual(text1, text2) 

+

792 

+

793 def assertFileContent(self, sFName, sContent): 

+

794 sAbsName = os.path.join(self.tempdir, sFName) 

+

795 f = open(sAbsName, 'rb') 

+

796 try: 

+

797 sFileContent = f.read() 

+

798 finally: 

+

799 f.close() 

+

800 self.assertEqual(sFileContent, to_bytes(sContent)) 

+

801 

+

802 

+

803class ArgumentHandlingTests(TestCaseWithTempDir): 

+

804 

+

805 def testArgumentFailure(self): 

+

806 # Return value 2 means usage problem. 

+

807 self.assertEqual(self.cog.main(['argv0', '-j']), 2) 

+

808 output = self.output.getvalue() 

+

809 self.assertIn("option -j not recognized", output) 

+

810 with self.assertRaisesRegex(CogUsageError, r"^No files to process$"): 

+

811 self.cog.callableMain(['argv0']) 

+

812 with self.assertRaisesRegex(CogUsageError, r"^option -j not recognized$"): 

+

813 self.cog.callableMain(['argv0', '-j']) 

+

814 

+

815 def testNoDashOAndAtFile(self): 

+

816 d = { 

+

817 'cogfiles.txt': """\ 

+

818 # Please run cog 

+

819 """ 

+

820 } 

+

821 

+

822 makeFiles(d) 

+

823 with self.assertRaisesRegex(CogUsageError, r"^Can't use -o with @file$"): 

+

824 self.cog.callableMain(['argv0', '-o', 'foo', '@cogfiles.txt']) 

+

825 

+

826 def testDashV(self): 

+

827 self.assertEqual(self.cog.main(['argv0', '-v']), 0) 

+

828 output = self.output.getvalue() 

+

829 self.assertEqual('Cog version %s\n' % __version__, output) 

+

830 

+

831 def producesHelp(self, args): 

+

832 self.newCog() 

+

833 argv = ['argv0'] + args.split() 

+

834 self.assertEqual(self.cog.main(argv), 0) 

+

835 self.assertEqual(usage, self.output.getvalue()) 

+

836 

+

837 def testDashH(self): 

+

838 # -h or -? anywhere on the command line should just print help. 

+

839 self.producesHelp("-h") 

+

840 self.producesHelp("-?") 

+

841 self.producesHelp("fooey.txt -h") 

+

842 self.producesHelp("-o -r @fooey.txt -? @booey.txt") 

+

843 

+

844 def testDashOAndDashR(self): 

+

845 d = { 

+

846 'cogfile.txt': """\ 

+

847 # Please run cog 

+

848 """ 

+

849 } 

+

850 

+

851 makeFiles(d) 

+

852 with self.assertRaisesRegex(CogUsageError, r"^Can't use -o with -r \(they are opposites\)$"): 

+

853 self.cog.callableMain(['argv0', '-o', 'foo', '-r', 'cogfile.txt']) 

+

854 

+

855 def testDashZ(self): 

+

856 d = { 

+

857 'test.cog': """\ 

+

858 // This is my C++ file. 

+

859 //[[[cog 

+

860 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

861 for fn in fnames: 

+

862 cog.outl("void %s();" % fn) 

+

863 //]]] 

+

864 """, 

+

865 

+

866 'test.out': """\ 

+

867 // This is my C++ file. 

+

868 //[[[cog 

+

869 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

870 for fn in fnames: 

+

871 cog.outl("void %s();" % fn) 

+

872 //]]] 

+

873 void DoSomething(); 

+

874 void DoAnotherThing(); 

+

875 void DoLastThing(); 

+

876 """, 

+

877 } 

+

878 

+

879 makeFiles(d) 

+

880 with self.assertRaisesRegex(CogError, r"^test.cog\(6\): Missing '\[\[\[end\]\]\]' before end of file.$"): 

+

881 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

882 self.newCog() 

+

883 self.cog.callableMain(['argv0', '-r', '-z', 'test.cog']) 

+

884 self.assertFilesSame('test.cog', 'test.out') 

+

885 

+

886 def testBadDashD(self): 

+

887 with self.assertRaisesRegex(CogUsageError, r"^-D takes a name=value argument$"): 

+

888 self.cog.callableMain(['argv0', '-Dfooey', 'cog.txt']) 

+

889 with self.assertRaisesRegex(CogUsageError, r"^-D takes a name=value argument$"): 

+

890 self.cog.callableMain(['argv0', '-D', 'fooey', 'cog.txt']) 

+

891 

+

892 def testBadMarkers(self): 

+

893 with self.assertRaisesRegex(CogUsageError, r"^--markers requires 3 values separated by spaces, could not parse 'X'$"): 

+

894 self.cog.callableMain(['argv0', '--markers=X']) 

+

895 with self.assertRaisesRegex(CogUsageError, r"^--markers requires 3 values separated by spaces, could not parse 'A B C D'$"): 

+

896 self.cog.callableMain(['argv0', '--markers=A B C D']) 

+

897 

+

898 

+

899class TestMain(TestCaseWithTempDir): 

+

900 def setUp(self): 

+

901 super(TestMain, self).setUp() 

+

902 self.old_argv = sys.argv[:] 

+

903 self.old_stderr = sys.stderr 

+

904 sys.stderr = StringIO() 

+

905 

+

906 def tearDown(self): 

+

907 sys.stderr = self.old_stderr 

+

908 sys.argv = self.old_argv 

+

909 sys.modules.pop('mycode', None) 

+

910 super(TestMain, self).tearDown() 

+

911 

+

912 def test_main_function(self): 

+

913 sys.argv = ["argv0", "-Z"] 

+

914 ret = main() 

+

915 self.assertEqual(ret, 2) 

+

916 stderr = sys.stderr.getvalue() 

+

917 self.assertEqual(stderr, 'option -Z not recognized\n(for help use -?)\n') 

+

918 

+

919 files = { 

+

920 'test.cog': """\ 

+

921 //[[[cog 

+

922 def func(): 

+

923 import mycode 

+

924 mycode.boom() 

+

925 //]]] 

+

926 //[[[end]]] 

+

927 ----- 

+

928 //[[[cog 

+

929 func() 

+

930 //]]] 

+

931 //[[[end]]] 

+

932 """, 

+

933 

+

934 'mycode.py': """\ 

+

935 def boom(): 

+

936 [][0] 

+

937 """, 

+

938 } 

+

939 

+

940 def test_error_report(self): 

+

941 self.check_error_report() 

+

942 

+

943 def test_error_report_with_prologue(self): 

+

944 self.check_error_report("-p", "#1\n#2") 

+

945 

+

946 def check_error_report(self, *args): 

+

947 """Check that the error report is right.""" 

+

948 makeFiles(self.files) 

+

949 sys.argv = ["argv0"] + list(args) + ["-r", "test.cog"] 

+

950 main() 

+

951 expected = reindentBlock("""\ 

+

952 Traceback (most recent call last): 

+

953 File "test.cog", line 9, in <module> 

+

954 func() 

+

955 File "test.cog", line 4, in func 

+

956 mycode.boom() 

+

957 File "MYCODE", line 2, in boom 

+

958 [][0] 

+

959 IndexError: list index out of range 

+

960 """) 

+

961 if PY3: 

+

962 expected = expected.replace("MYCODE", os.path.abspath("mycode.py")) 

+

963 else: 

+

964 expected = expected.replace("MYCODE", "mycode.py") 

+

965 assert expected == sys.stderr.getvalue() 

+

966 

+

967 def test_error_in_prologue(self): 

+

968 makeFiles(self.files) 

+

969 sys.argv = ["argv0", "-p", "import mycode; mycode.boom()", "-r", "test.cog"] 

+

970 main() 

+

971 expected = reindentBlock("""\ 

+

972 Traceback (most recent call last): 

+

973 File "<prologue>", line 1, in <module> 

+

974 import mycode; mycode.boom() 

+

975 File "MYCODE", line 2, in boom 

+

976 [][0] 

+

977 IndexError: list index out of range 

+

978 """) 

+

979 if PY3: 

+

980 expected = expected.replace("MYCODE", os.path.abspath("mycode.py")) 

+

981 else: 

+

982 expected = expected.replace("MYCODE", "mycode.py") 

+

983 assert expected == sys.stderr.getvalue() 

+

984 

+

985 

+

986 

+

987class TestFileHandling(TestCaseWithTempDir): 

+

988 

+

989 def testSimple(self): 

+

990 d = { 

+

991 'test.cog': """\ 

+

992 // This is my C++ file. 

+

993 //[[[cog 

+

994 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

995 for fn in fnames: 

+

996 cog.outl("void %s();" % fn) 

+

997 //]]] 

+

998 //[[[end]]] 

+

999 """, 

+

1000 

+

1001 'test.out': """\ 

+

1002 // This is my C++ file. 

+

1003 //[[[cog 

+

1004 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1005 for fn in fnames: 

+

1006 cog.outl("void %s();" % fn) 

+

1007 //]]] 

+

1008 void DoSomething(); 

+

1009 void DoAnotherThing(); 

+

1010 void DoLastThing(); 

+

1011 //[[[end]]] 

+

1012 """, 

+

1013 } 

+

1014 

+

1015 makeFiles(d) 

+

1016 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

1017 self.assertFilesSame('test.cog', 'test.out') 

+

1018 output = self.output.getvalue() 

+

1019 self.assertIn("(changed)", output) 

+

1020 

+

1021 def testWildcards(self): 

+

1022 d = { 

+

1023 'test.cog': """\ 

+

1024 // This is my C++ file. 

+

1025 //[[[cog 

+

1026 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1027 for fn in fnames: 

+

1028 cog.outl("void %s();" % fn) 

+

1029 //]]] 

+

1030 //[[[end]]] 

+

1031 """, 

+

1032 

+

1033 'test2.cog': """\ 

+

1034 // This is my C++ file. 

+

1035 //[[[cog 

+

1036 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1037 for fn in fnames: 

+

1038 cog.outl("void %s();" % fn) 

+

1039 //]]] 

+

1040 //[[[end]]] 

+

1041 """, 

+

1042 

+

1043 'test.out': """\ 

+

1044 // This is my C++ file. 

+

1045 //[[[cog 

+

1046 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1047 for fn in fnames: 

+

1048 cog.outl("void %s();" % fn) 

+

1049 //]]] 

+

1050 void DoSomething(); 

+

1051 void DoAnotherThing(); 

+

1052 void DoLastThing(); 

+

1053 //[[[end]]] 

+

1054 """, 

+

1055 

+

1056 'not_this_one.cog': """\ 

+

1057 // This is my C++ file. 

+

1058 //[[[cog 

+

1059 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1060 for fn in fnames: 

+

1061 cog.outl("void %s();" % fn) 

+

1062 //]]] 

+

1063 //[[[end]]] 

+

1064 """, 

+

1065 

+

1066 'not_this_one.out': """\ 

+

1067 // This is my C++ file. 

+

1068 //[[[cog 

+

1069 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1070 for fn in fnames: 

+

1071 cog.outl("void %s();" % fn) 

+

1072 //]]] 

+

1073 //[[[end]]] 

+

1074 """, 

+

1075 } 

+

1076 

+

1077 makeFiles(d) 

+

1078 self.cog.callableMain(['argv0', '-r', 't*.cog']) 

+

1079 self.assertFilesSame('test.cog', 'test.out') 

+

1080 self.assertFilesSame('test2.cog', 'test.out') 

+

1081 self.assertFilesSame('not_this_one.cog', 'not_this_one.out') 

+

1082 output = self.output.getvalue() 

+

1083 self.assertIn("(changed)", output) 

+

1084 

+

1085 def testOutputFile(self): 

+

1086 # -o sets the output file. 

+

1087 d = { 

+

1088 'test.cog': """\ 

+

1089 // This is my C++ file. 

+

1090 //[[[cog 

+

1091 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1092 for fn in fnames: 

+

1093 cog.outl("void %s();" % fn) 

+

1094 //]]] 

+

1095 //[[[end]]] 

+

1096 """, 

+

1097 

+

1098 'test.out': """\ 

+

1099 // This is my C++ file. 

+

1100 //[[[cog 

+

1101 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

1102 for fn in fnames: 

+

1103 cog.outl("void %s();" % fn) 

+

1104 //]]] 

+

1105 void DoSomething(); 

+

1106 void DoAnotherThing(); 

+

1107 void DoLastThing(); 

+

1108 //[[[end]]] 

+

1109 """, 

+

1110 } 

+

1111 

+

1112 makeFiles(d) 

+

1113 self.cog.callableMain(['argv0', '-o', 'in/a/dir/test.cogged', 'test.cog']) 

+

1114 self.assertFilesSame('in/a/dir/test.cogged', 'test.out') 

+

1115 

+

1116 def testAtFile(self): 

+

1117 d = { 

+

1118 'one.cog': """\ 

+

1119 //[[[cog 

+

1120 cog.outl("hello world") 

+

1121 //]]] 

+

1122 //[[[end]]] 

+

1123 """, 

+

1124 

+

1125 'one.out': """\ 

+

1126 //[[[cog 

+

1127 cog.outl("hello world") 

+

1128 //]]] 

+

1129 hello world 

+

1130 //[[[end]]] 

+

1131 """, 

+

1132 

+

1133 'two.cog': """\ 

+

1134 //[[[cog 

+

1135 cog.outl("goodbye cruel world") 

+

1136 //]]] 

+

1137 //[[[end]]] 

+

1138 """, 

+

1139 

+

1140 'two.out': """\ 

+

1141 //[[[cog 

+

1142 cog.outl("goodbye cruel world") 

+

1143 //]]] 

+

1144 goodbye cruel world 

+

1145 //[[[end]]] 

+

1146 """, 

+

1147 

+

1148 'cogfiles.txt': """\ 

+

1149 # Please run cog 

+

1150 one.cog 

+

1151 

+

1152 two.cog 

+

1153 """ 

+

1154 } 

+

1155 

+

1156 makeFiles(d) 

+

1157 self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

+

1158 self.assertFilesSame('one.cog', 'one.out') 

+

1159 self.assertFilesSame('two.cog', 'two.out') 

+

1160 output = self.output.getvalue() 

+

1161 self.assertIn("(changed)", output) 

+

1162 

+

1163 def testNestedAtFile(self): 

+

1164 d = { 

+

1165 'one.cog': """\ 

+

1166 //[[[cog 

+

1167 cog.outl("hello world") 

+

1168 //]]] 

+

1169 //[[[end]]] 

+

1170 """, 

+

1171 

+

1172 'one.out': """\ 

+

1173 //[[[cog 

+

1174 cog.outl("hello world") 

+

1175 //]]] 

+

1176 hello world 

+

1177 //[[[end]]] 

+

1178 """, 

+

1179 

+

1180 'two.cog': """\ 

+

1181 //[[[cog 

+

1182 cog.outl("goodbye cruel world") 

+

1183 //]]] 

+

1184 //[[[end]]] 

+

1185 """, 

+

1186 

+

1187 'two.out': """\ 

+

1188 //[[[cog 

+

1189 cog.outl("goodbye cruel world") 

+

1190 //]]] 

+

1191 goodbye cruel world 

+

1192 //[[[end]]] 

+

1193 """, 

+

1194 

+

1195 'cogfiles.txt': """\ 

+

1196 # Please run cog 

+

1197 one.cog 

+

1198 @cogfiles2.txt 

+

1199 """, 

+

1200 

+

1201 'cogfiles2.txt': """\ 

+

1202 # This one too, please. 

+

1203 two.cog 

+

1204 """, 

+

1205 } 

+

1206 

+

1207 makeFiles(d) 

+

1208 self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

+

1209 self.assertFilesSame('one.cog', 'one.out') 

+

1210 self.assertFilesSame('two.cog', 'two.out') 

+

1211 output = self.output.getvalue() 

+

1212 self.assertIn("(changed)", output) 

+

1213 

+

1214 def testAtFileWithArgs(self): 

+

1215 d = { 

+

1216 'both.cog': """\ 

+

1217 //[[[cog 

+

1218 cog.outl("one: %s" % ('one' in globals())) 

+

1219 cog.outl("two: %s" % ('two' in globals())) 

+

1220 //]]] 

+

1221 //[[[end]]] 

+

1222 """, 

+

1223 

+

1224 'one.out': """\ 

+

1225 //[[[cog 

+

1226 cog.outl("one: %s" % ('one' in globals())) 

+

1227 cog.outl("two: %s" % ('two' in globals())) 

+

1228 //]]] 

+

1229 one: True // ONE 

+

1230 two: False // ONE 

+

1231 //[[[end]]] 

+

1232 """, 

+

1233 

+

1234 'two.out': """\ 

+

1235 //[[[cog 

+

1236 cog.outl("one: %s" % ('one' in globals())) 

+

1237 cog.outl("two: %s" % ('two' in globals())) 

+

1238 //]]] 

+

1239 one: False // TWO 

+

1240 two: True // TWO 

+

1241 //[[[end]]] 

+

1242 """, 

+

1243 

+

1244 'cogfiles.txt': """\ 

+

1245 # Please run cog 

+

1246 both.cog -o in/a/dir/both.one -s ' // ONE' -D one=x 

+

1247 both.cog -o in/a/dir/both.two -s ' // TWO' -D two=x 

+

1248 """ 

+

1249 } 

+

1250 

+

1251 makeFiles(d) 

+

1252 self.cog.callableMain(['argv0', '@cogfiles.txt']) 

+

1253 self.assertFilesSame('in/a/dir/both.one', 'one.out') 

+

1254 self.assertFilesSame('in/a/dir/both.two', 'two.out') 

+

1255 

+

1256 def testAtFileWithBadArgCombo(self): 

+

1257 d = { 

+

1258 'both.cog': """\ 

+

1259 //[[[cog 

+

1260 cog.outl("one: %s" % ('one' in globals())) 

+

1261 cog.outl("two: %s" % ('two' in globals())) 

+

1262 //]]] 

+

1263 //[[[end]]] 

+

1264 """, 

+

1265 

+

1266 'cogfiles.txt': """\ 

+

1267 # Please run cog 

+

1268 both.cog 

+

1269 both.cog -d # This is bad: -r and -d 

+

1270 """ 

+

1271 } 

+

1272 

+

1273 makeFiles(d) 

+

1274 with self.assertRaisesRegex(CogUsageError, r"^Can't use -d with -r \(or you would delete all your source!\)$"): 

+

1275 self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

+

1276 

+

1277 def testAtFileWithTrickyFilenames(self): 

+

1278 def fix_backslashes(files_txt): 

+

1279 """Make the contents of a files.txt sensitive to the platform.""" 

+

1280 if sys.platform != "win32": 

+

1281 files_txt = files_txt.replace("\\", "/") 

+

1282 return files_txt 

+

1283 

+

1284 d = { 

+

1285 'one 1.cog': """\ 

+

1286 //[[[cog cog.outl("hello world") ]]] 

+

1287 """, 

+

1288 

+

1289 'one.out': """\ 

+

1290 //[[[cog cog.outl("hello world") ]]] 

+

1291 hello world //xxx 

+

1292 """, 

+

1293 

+

1294 'subdir': { 

+

1295 'subback.cog': """\ 

+

1296 //[[[cog cog.outl("down deep with backslashes") ]]] 

+

1297 """, 

+

1298 

+

1299 'subfwd.cog': """\ 

+

1300 //[[[cog cog.outl("down deep with slashes") ]]] 

+

1301 """, 

+

1302 }, 

+

1303 

+

1304 'subback.out': """\ 

+

1305 //[[[cog cog.outl("down deep with backslashes") ]]] 

+

1306 down deep with backslashes //yyy 

+

1307 """, 

+

1308 

+

1309 'subfwd.out': """\ 

+

1310 //[[[cog cog.outl("down deep with slashes") ]]] 

+

1311 down deep with slashes //zzz 

+

1312 """, 

+

1313 

+

1314 'cogfiles.txt': fix_backslashes("""\ 

+

1315 # Please run cog 

+

1316 'one 1.cog' -s ' //xxx' 

+

1317 subdir\\subback.cog -s ' //yyy' 

+

1318 subdir/subfwd.cog -s ' //zzz' 

+

1319 """) 

+

1320 } 

+

1321 

+

1322 makeFiles(d) 

+

1323 self.cog.callableMain(['argv0', '-z', '-r', '@cogfiles.txt']) 

+

1324 self.assertFilesSame('one 1.cog', 'one.out') 

+

1325 self.assertFilesSame('subdir/subback.cog', 'subback.out') 

+

1326 self.assertFilesSame('subdir/subfwd.cog', 'subfwd.out') 

+

1327 

+

1328 def run_with_verbosity(self, verbosity): 

+

1329 d = { 

+

1330 'unchanged.cog': """\ 

+

1331 //[[[cog 

+

1332 cog.outl("hello world") 

+

1333 //]]] 

+

1334 hello world 

+

1335 //[[[end]]] 

+

1336 """, 

+

1337 

+

1338 'changed.cog': """\ 

+

1339 //[[[cog 

+

1340 cog.outl("goodbye cruel world") 

+

1341 //]]] 

+

1342 //[[[end]]] 

+

1343 """, 

+

1344 

+

1345 'cogfiles.txt': """\ 

+

1346 unchanged.cog 

+

1347 changed.cog 

+

1348 """ 

+

1349 } 

+

1350 

+

1351 makeFiles(d) 

+

1352 self.cog.callableMain(['argv0', '-r', '--verbosity='+verbosity, '@cogfiles.txt']) 

+

1353 output = self.output.getvalue() 

+

1354 return output 

+

1355 

+

1356 def test_verbosity0(self): 

+

1357 output = self.run_with_verbosity("0") 

+

1358 self.assertEqual(output, "") 

+

1359 

+

1360 def test_verbosity1(self): 

+

1361 output = self.run_with_verbosity("1") 

+

1362 self.assertEqual(output, "Cogging changed.cog (changed)\n") 

+

1363 

+

1364 def test_verbosity2(self): 

+

1365 output = self.run_with_verbosity("2") 

+

1366 self.assertEqual(output, "Cogging unchanged.cog\nCogging changed.cog (changed)\n") 

+

1367 

+

1368 

+

1369class CogTestLineEndings(TestCaseWithTempDir): 

+

1370 """Tests for -U option (force LF line-endings in output).""" 

+

1371 

+

1372 lines_in = ['Some text.', 

+

1373 '//[[[cog', 

+

1374 'cog.outl("Cog text")', 

+

1375 '//]]]', 

+

1376 'gobbledegook.', 

+

1377 '//[[[end]]]', 

+

1378 'epilogue.', 

+

1379 ''] 

+

1380 

+

1381 lines_out = ['Some text.', 

+

1382 '//[[[cog', 

+

1383 'cog.outl("Cog text")', 

+

1384 '//]]]', 

+

1385 'Cog text', 

+

1386 '//[[[end]]]', 

+

1387 'epilogue.', 

+

1388 ''] 

+

1389 

+

1390 def testOutputNativeEol(self): 

+

1391 makeFiles({'infile': '\n'.join(self.lines_in)}) 

+

1392 self.cog.callableMain(['argv0', '-o', 'outfile', 'infile']) 

+

1393 self.assertFileContent('outfile', os.linesep.join(self.lines_out)) 

+

1394 

+

1395 def testOutputLfEol(self): 

+

1396 makeFiles({'infile': '\n'.join(self.lines_in)}) 

+

1397 self.cog.callableMain(['argv0', '-U', '-o', 'outfile', 'infile']) 

+

1398 self.assertFileContent('outfile', '\n'.join(self.lines_out)) 

+

1399 

+

1400 def testReplaceNativeEol(self): 

+

1401 makeFiles({'test.cog': '\n'.join(self.lines_in)}) 

+

1402 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

1403 self.assertFileContent('test.cog', os.linesep.join(self.lines_out)) 

+

1404 

+

1405 def testReplaceLfEol(self): 

+

1406 makeFiles({'test.cog': '\n'.join(self.lines_in)}) 

+

1407 self.cog.callableMain(['argv0', '-U', '-r', 'test.cog']) 

+

1408 self.assertFileContent('test.cog', '\n'.join(self.lines_out)) 

+

1409 

+

1410 

+

1411class CogTestCharacterEncoding(TestCaseWithTempDir): 

+

1412 

+

1413 def testSimple(self): 

+

1414 d = { 

+

1415 'test.cog': b"""\ 

+

1416 // This is my C++ file. 

+

1417 //[[[cog 

+

1418 cog.outl("// Unicode: \xe1\x88\xb4 (U+1234)") 

+

1419 //]]] 

+

1420 //[[[end]]] 

+

1421 """, 

+

1422 

+

1423 'test.out': b"""\ 

+

1424 // This is my C++ file. 

+

1425 //[[[cog 

+

1426 cog.outl("// Unicode: \xe1\x88\xb4 (U+1234)") 

+

1427 //]]] 

+

1428 // Unicode: \xe1\x88\xb4 (U+1234) 

+

1429 //[[[end]]] 

+

1430 """.replace(b"\n", os.linesep.encode()), 

+

1431 } 

+

1432 

+

1433 makeFiles(d, bytes=True) 

+

1434 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

1435 self.assertFilesSame('test.cog', 'test.out') 

+

1436 output = self.output.getvalue() 

+

1437 self.assertIn("(changed)", output) 

+

1438 

+

1439 def testFileEncodingOption(self): 

+

1440 d = { 

+

1441 'test.cog': b"""\ 

+

1442 // \xca\xee\xe4\xe8\xf0\xe2\xea\xe0 Windows 

+

1443 //[[[cog 

+

1444 cog.outl("\xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe") 

+

1445 //]]] 

+

1446 //[[[end]]] 

+

1447 """, 

+

1448 

+

1449 'test.out': b"""\ 

+

1450 // \xca\xee\xe4\xe8\xf0\xe2\xea\xe0 Windows 

+

1451 //[[[cog 

+

1452 cog.outl("\xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe") 

+

1453 //]]] 

+

1454 \xd1\xfa\xe5\xf8\xfc \xe5\xf9\xb8 \xfd\xf2\xe8\xf5 \xec\xff\xe3\xea\xe8\xf5 \xf4\xf0\xe0\xed\xf6\xf3\xe7\xf1\xea\xe8\xf5 \xe1\xf3\xeb\xee\xea \xe4\xe0 \xe2\xfb\xef\xe5\xe9 \xf7\xe0\xfe 

+

1455 //[[[end]]] 

+

1456 """.replace(b"\n", os.linesep.encode()), 

+

1457 } 

+

1458 

+

1459 makeFiles(d, bytes=True) 

+

1460 self.cog.callableMain(['argv0', '-n', 'cp1251', '-r', 'test.cog']) 

+

1461 self.assertFilesSame('test.cog', 'test.out') 

+

1462 output = self.output.getvalue() 

+

1463 self.assertIn("(changed)", output) 

+

1464 

+

1465 

+

1466class TestCaseWithImports(TestCaseWithTempDir): 

+

1467 """ When running tests which import modules, the sys.modules list 

+

1468 leaks from one test to the next. This test case class scrubs 

+

1469 the list after each run to keep the tests isolated from each other. 

+

1470 """ 

+

1471 

+

1472 def setUp(self): 

+

1473 super(TestCaseWithImports, self).setUp() 

+

1474 self.sysmodulekeys = list(sys.modules) 

+

1475 

+

1476 def tearDown(self): 

+

1477 modstoscrub = [ 

+

1478 modname 

+

1479 for modname in sys.modules 

+

1480 if modname not in self.sysmodulekeys 

+

1481 ] 

+

1482 for modname in modstoscrub: 

+

1483 del sys.modules[modname] 

+

1484 super(TestCaseWithImports, self).tearDown() 

+

1485 

+

1486 

+

1487class CogIncludeTests(TestCaseWithImports): 

+

1488 dincludes = { 

+

1489 'test.cog': """\ 

+

1490 //[[[cog 

+

1491 import mymodule 

+

1492 //]]] 

+

1493 //[[[end]]] 

+

1494 """, 

+

1495 

+

1496 'test.out': """\ 

+

1497 //[[[cog 

+

1498 import mymodule 

+

1499 //]]] 

+

1500 Hello from mymodule 

+

1501 //[[[end]]] 

+

1502 """, 

+

1503 

+

1504 'test2.out': """\ 

+

1505 //[[[cog 

+

1506 import mymodule 

+

1507 //]]] 

+

1508 Hello from mymodule in inc2 

+

1509 //[[[end]]] 

+

1510 """, 

+

1511 

+

1512 'include': { 

+

1513 'mymodule.py': """\ 

+

1514 import cog 

+

1515 cog.outl("Hello from mymodule") 

+

1516 """ 

+

1517 }, 

+

1518 

+

1519 'inc2': { 

+

1520 'mymodule.py': """\ 

+

1521 import cog 

+

1522 cog.outl("Hello from mymodule in inc2") 

+

1523 """ 

+

1524 }, 

+

1525 

+

1526 'inc3': { 

+

1527 'someothermodule.py': """\ 

+

1528 import cog 

+

1529 cog.outl("This is some other module.") 

+

1530 """ 

+

1531 }, 

+

1532 } 

+

1533 

+

1534 def testNeedIncludePath(self): 

+

1535 # Try it without the -I, to see that an ImportError happens. 

+

1536 makeFiles(self.dincludes) 

+

1537 msg = "(ImportError|ModuleNotFoundError): No module named '?mymodule'?" 

+

1538 with self.assertRaisesRegex(CogUserException, msg): 

+

1539 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

1540 

+

1541 def testIncludePath(self): 

+

1542 # Test that -I adds include directories properly. 

+

1543 makeFiles(self.dincludes) 

+

1544 self.cog.callableMain(['argv0', '-r', '-I', 'include', 'test.cog']) 

+

1545 self.assertFilesSame('test.cog', 'test.out') 

+

1546 

+

1547 def testTwoIncludePaths(self): 

+

1548 # Test that two -I's add include directories properly. 

+

1549 makeFiles(self.dincludes) 

+

1550 self.cog.callableMain(['argv0', '-r', '-I', 'include', '-I', 'inc2', 'test.cog']) 

+

1551 self.assertFilesSame('test.cog', 'test.out') 

+

1552 

+

1553 def testTwoIncludePaths2(self): 

+

1554 # Test that two -I's add include directories properly. 

+

1555 makeFiles(self.dincludes) 

+

1556 self.cog.callableMain(['argv0', '-r', '-I', 'inc2', '-I', 'include', 'test.cog']) 

+

1557 self.assertFilesSame('test.cog', 'test2.out') 

+

1558 

+

1559 def testUselessIncludePath(self): 

+

1560 # Test that the search will continue past the first directory. 

+

1561 makeFiles(self.dincludes) 

+

1562 self.cog.callableMain(['argv0', '-r', '-I', 'inc3', '-I', 'include', 'test.cog']) 

+

1563 self.assertFilesSame('test.cog', 'test.out') 

+

1564 

+

1565 def testSysPathIsUnchanged(self): 

+

1566 d = { 

+

1567 'bad.cog': """\ 

+

1568 //[[[cog cog.error("Oh no!") ]]] 

+

1569 //[[[end]]] 

+

1570 """, 

+

1571 'good.cog': """\ 

+

1572 //[[[cog cog.outl("Oh yes!") ]]] 

+

1573 //[[[end]]] 

+

1574 """, 

+

1575 } 

+

1576 

+

1577 makeFiles(d) 

+

1578 # Is it unchanged just by creating a cog engine? 

+

1579 oldsyspath = sys.path[:] 

+

1580 self.newCog() 

+

1581 self.assertEqual(oldsyspath, sys.path) 

+

1582 # Is it unchanged for a successful run? 

+

1583 self.newCog() 

+

1584 self.cog.callableMain(['argv0', '-r', 'good.cog']) 

+

1585 self.assertEqual(oldsyspath, sys.path) 

+

1586 # Is it unchanged for a successful run with includes? 

+

1587 self.newCog() 

+

1588 self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', 'good.cog']) 

+

1589 self.assertEqual(oldsyspath, sys.path) 

+

1590 # Is it unchanged for a successful run with two includes? 

+

1591 self.newCog() 

+

1592 self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', '-I', 'quux', 'good.cog']) 

+

1593 self.assertEqual(oldsyspath, sys.path) 

+

1594 # Is it unchanged for a failed run? 

+

1595 self.newCog() 

+

1596 with self.assertRaisesRegex(CogError, r"^Oh no!$"): 

+

1597 self.cog.callableMain(['argv0', '-r', 'bad.cog']) 

+

1598 self.assertEqual(oldsyspath, sys.path) 

+

1599 # Is it unchanged for a failed run with includes? 

+

1600 self.newCog() 

+

1601 with self.assertRaisesRegex(CogError, r"^Oh no!$"): 

+

1602 self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', 'bad.cog']) 

+

1603 self.assertEqual(oldsyspath, sys.path) 

+

1604 # Is it unchanged for a failed run with two includes? 

+

1605 self.newCog() 

+

1606 with self.assertRaisesRegex(CogError, r"^Oh no!$"): 

+

1607 self.cog.callableMain(['argv0', '-r', '-I', 'xyzzy', '-I', 'quux', 'bad.cog']) 

+

1608 self.assertEqual(oldsyspath, sys.path) 

+

1609 

+

1610 def testSubDirectories(self): 

+

1611 # Test that relative paths on the command line work, with includes. 

+

1612 

+

1613 d = { 

+

1614 'code': { 

+

1615 'test.cog': """\ 

+

1616 //[[[cog 

+

1617 import mysubmodule 

+

1618 //]]] 

+

1619 //[[[end]]] 

+

1620 """, 

+

1621 

+

1622 'test.out': """\ 

+

1623 //[[[cog 

+

1624 import mysubmodule 

+

1625 //]]] 

+

1626 Hello from mysubmodule 

+

1627 //[[[end]]] 

+

1628 """, 

+

1629 

+

1630 'mysubmodule.py': """\ 

+

1631 import cog 

+

1632 cog.outl("Hello from mysubmodule") 

+

1633 """ 

+

1634 } 

+

1635 } 

+

1636 

+

1637 makeFiles(d) 

+

1638 # We should be able to invoke cog without the -I switch, and it will 

+

1639 # auto-include the current directory 

+

1640 self.cog.callableMain(['argv0', '-r', 'code/test.cog']) 

+

1641 self.assertFilesSame('code/test.cog', 'code/test.out') 

+

1642 

+

1643 

+

1644class CogTestsInFiles(TestCaseWithTempDir): 

+

1645 

+

1646 def testWarnIfNoCogCode(self): 

+

1647 # Test that the -e switch warns if there is no Cog code. 

+

1648 d = { 

+

1649 'with.cog': """\ 

+

1650 //[[[cog 

+

1651 cog.outl("hello world") 

+

1652 //]]] 

+

1653 hello world 

+

1654 //[[[end]]] 

+

1655 """, 

+

1656 

+

1657 'without.cog': """\ 

+

1658 There's no cog 

+

1659 code in this file. 

+

1660 """, 

+

1661 } 

+

1662 

+

1663 makeFiles(d) 

+

1664 self.cog.callableMain(['argv0', '-e', 'with.cog']) 

+

1665 output = self.output.getvalue() 

+

1666 self.assertNotIn("Warning", output) 

+

1667 self.newCog() 

+

1668 self.cog.callableMain(['argv0', '-e', 'without.cog']) 

+

1669 output = self.output.getvalue() 

+

1670 self.assertIn("Warning: no cog code found in without.cog", output) 

+

1671 self.newCog() 

+

1672 self.cog.callableMain(['argv0', 'without.cog']) 

+

1673 output = self.output.getvalue() 

+

1674 self.assertNotIn("Warning", output) 

+

1675 

+

1676 def testFileNameProps(self): 

+

1677 d = { 

+

1678 'cog1.txt': """\ 

+

1679 //[[[cog 

+

1680 cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

+

1681 //]]] 

+

1682 this is cog1.txt in, cog1.txt out 

+

1683 [[[end]]] 

+

1684 """, 

+

1685 

+

1686 'cog1.out': """\ 

+

1687 //[[[cog 

+

1688 cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

+

1689 //]]] 

+

1690 This is cog1.txt in, cog1.txt out 

+

1691 [[[end]]] 

+

1692 """, 

+

1693 

+

1694 'cog1out.out': """\ 

+

1695 //[[[cog 

+

1696 cog.outl("This is %s in, %s out" % (cog.inFile, cog.outFile)) 

+

1697 //]]] 

+

1698 This is cog1.txt in, cog1out.txt out 

+

1699 [[[end]]] 

+

1700 """, 

+

1701 } 

+

1702 

+

1703 makeFiles(d) 

+

1704 self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

+

1705 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

1706 self.newCog() 

+

1707 self.cog.callableMain(['argv0', '-o', 'cog1out.txt', 'cog1.txt']) 

+

1708 self.assertFilesSame('cog1out.txt', 'cog1out.out') 

+

1709 

+

1710 def testGlobalsDontCrossFiles(self): 

+

1711 # Make sure that global values don't get shared between files. 

+

1712 d = { 

+

1713 'one.cog': """\ 

+

1714 //[[[cog s = "This was set in one.cog" ]]] 

+

1715 //[[[end]]] 

+

1716 //[[[cog cog.outl(s) ]]] 

+

1717 //[[[end]]] 

+

1718 """, 

+

1719 

+

1720 'one.out': """\ 

+

1721 //[[[cog s = "This was set in one.cog" ]]] 

+

1722 //[[[end]]] 

+

1723 //[[[cog cog.outl(s) ]]] 

+

1724 This was set in one.cog 

+

1725 //[[[end]]] 

+

1726 """, 

+

1727 

+

1728 'two.cog': """\ 

+

1729 //[[[cog 

+

1730 try: 

+

1731 cog.outl(s) 

+

1732 except NameError: 

+

1733 cog.outl("s isn't set!") 

+

1734 //]]] 

+

1735 //[[[end]]] 

+

1736 """, 

+

1737 

+

1738 'two.out': """\ 

+

1739 //[[[cog 

+

1740 try: 

+

1741 cog.outl(s) 

+

1742 except NameError: 

+

1743 cog.outl("s isn't set!") 

+

1744 //]]] 

+

1745 s isn't set! 

+

1746 //[[[end]]] 

+

1747 """, 

+

1748 

+

1749 'cogfiles.txt': """\ 

+

1750 # Please run cog 

+

1751 one.cog 

+

1752 

+

1753 two.cog 

+

1754 """ 

+

1755 } 

+

1756 

+

1757 makeFiles(d) 

+

1758 self.cog.callableMain(['argv0', '-r', '@cogfiles.txt']) 

+

1759 self.assertFilesSame('one.cog', 'one.out') 

+

1760 self.assertFilesSame('two.cog', 'two.out') 

+

1761 output = self.output.getvalue() 

+

1762 self.assertIn("(changed)", output) 

+

1763 

+

1764 def testRemoveGeneratedOutput(self): 

+

1765 d = { 

+

1766 'cog1.txt': """\ 

+

1767 //[[[cog 

+

1768 cog.outl("This line was generated.") 

+

1769 //]]] 

+

1770 This line was generated. 

+

1771 //[[[end]]] 

+

1772 This line was not. 

+

1773 """, 

+

1774 

+

1775 'cog1.out': """\ 

+

1776 //[[[cog 

+

1777 cog.outl("This line was generated.") 

+

1778 //]]] 

+

1779 //[[[end]]] 

+

1780 This line was not. 

+

1781 """, 

+

1782 

+

1783 'cog1.out2': """\ 

+

1784 //[[[cog 

+

1785 cog.outl("This line was generated.") 

+

1786 //]]] 

+

1787 This line was generated. 

+

1788 //[[[end]]] 

+

1789 This line was not. 

+

1790 """, 

+

1791 } 

+

1792 

+

1793 makeFiles(d) 

+

1794 # Remove generated output. 

+

1795 self.cog.callableMain(['argv0', '-r', '-x', 'cog1.txt']) 

+

1796 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

1797 self.newCog() 

+

1798 # Regenerate the generated output. 

+

1799 self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

+

1800 self.assertFilesSame('cog1.txt', 'cog1.out2') 

+

1801 self.newCog() 

+

1802 # Remove the generated output again. 

+

1803 self.cog.callableMain(['argv0', '-r', '-x', 'cog1.txt']) 

+

1804 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

1805 

+

1806 def testMsgCall(self): 

+

1807 infile = """\ 

+

1808 #[[[cog 

+

1809 cog.msg("Hello there!") 

+

1810 #]]] 

+

1811 #[[[end]]] 

+

1812 """ 

+

1813 infile = reindentBlock(infile) 

+

1814 self.assertEqual(self.cog.processString(infile), infile) 

+

1815 output = self.output.getvalue() 

+

1816 self.assertEqual(output, "Message: Hello there!\n") 

+

1817 

+

1818 def testErrorMessageHasNoTraceback(self): 

+

1819 # Test that a Cog error is printed to stderr with no traceback. 

+

1820 

+

1821 d = { 

+

1822 'cog1.txt': """\ 

+

1823 //[[[cog 

+

1824 cog.outl("This line was newly") 

+

1825 cog.outl("generated by cog") 

+

1826 cog.outl("blah blah.") 

+

1827 //]]] 

+

1828 Xhis line was newly 

+

1829 generated by cog 

+

1830 blah blah. 

+

1831 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

1832 """, 

+

1833 } 

+

1834 

+

1835 makeFiles(d) 

+

1836 stderr = StringIO() 

+

1837 self.cog.setOutput(stderr=stderr) 

+

1838 self.cog.main(['argv0', '-c', '-r', "cog1.txt"]) 

+

1839 self.assertEqual(self.output.getvalue(), "Cogging cog1.txt\n") 

+

1840 self.assertEqual(stderr.getvalue(), "cog1.txt(9): Output has been edited! Delete old checksum to unprotect.\n") 

+

1841 

+

1842 def testDashD(self): 

+

1843 d = { 

+

1844 'test.cog': """\ 

+

1845 --[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

+

1846 --[[[end]]] 

+

1847 """, 

+

1848 

+

1849 'test.kablooey': """\ 

+

1850 --[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

+

1851 Defined fooey as kablooey 

+

1852 --[[[end]]] 

+

1853 """, 

+

1854 

+

1855 'test.einstein': """\ 

+

1856 --[[[cog cog.outl("Defined fooey as " + fooey) ]]] 

+

1857 Defined fooey as e=mc2 

+

1858 --[[[end]]] 

+

1859 """, 

+

1860 } 

+

1861 

+

1862 makeFiles(d) 

+

1863 self.cog.callableMain(['argv0', '-r', '-D', 'fooey=kablooey', 'test.cog']) 

+

1864 self.assertFilesSame('test.cog', 'test.kablooey') 

+

1865 makeFiles(d) 

+

1866 self.cog.callableMain(['argv0', '-r', '-Dfooey=kablooey', 'test.cog']) 

+

1867 self.assertFilesSame('test.cog', 'test.kablooey') 

+

1868 makeFiles(d) 

+

1869 self.cog.callableMain(['argv0', '-r', '-Dfooey=e=mc2', 'test.cog']) 

+

1870 self.assertFilesSame('test.cog', 'test.einstein') 

+

1871 makeFiles(d) 

+

1872 self.cog.callableMain(['argv0', '-r', '-Dbar=quux', '-Dfooey=kablooey', 'test.cog']) 

+

1873 self.assertFilesSame('test.cog', 'test.kablooey') 

+

1874 makeFiles(d) 

+

1875 self.cog.callableMain(['argv0', '-r', '-Dfooey=kablooey', '-Dbar=quux', 'test.cog']) 

+

1876 self.assertFilesSame('test.cog', 'test.kablooey') 

+

1877 makeFiles(d) 

+

1878 self.cog.callableMain(['argv0', '-r', '-Dfooey=gooey', '-Dfooey=kablooey', 'test.cog']) 

+

1879 self.assertFilesSame('test.cog', 'test.kablooey') 

+

1880 

+

1881 def testOutputToStdout(self): 

+

1882 d = { 

+

1883 'test.cog': """\ 

+

1884 --[[[cog cog.outl('Hey there!') ]]] 

+

1885 --[[[end]]] 

+

1886 """ 

+

1887 } 

+

1888 

+

1889 makeFiles(d) 

+

1890 stderr = StringIO() 

+

1891 self.cog.setOutput(stderr=stderr) 

+

1892 self.cog.callableMain(['argv0', 'test.cog']) 

+

1893 output = self.output.getvalue() 

+

1894 outerr = stderr.getvalue() 

+

1895 self.assertEqual(output, "--[[[cog cog.outl('Hey there!') ]]]\nHey there!\n--[[[end]]]\n") 

+

1896 self.assertEqual(outerr, "") 

+

1897 

+

1898 def testReadFromStdin(self): 

+

1899 stdin = StringIO("--[[[cog cog.outl('Wow') ]]]\n--[[[end]]]\n") 

+

1900 def restore_stdin(old_stdin): 

+

1901 sys.stdin = old_stdin 

+

1902 self.addCleanup(restore_stdin, sys.stdin) 

+

1903 sys.stdin = stdin 

+

1904 

+

1905 stderr = StringIO() 

+

1906 self.cog.setOutput(stderr=stderr) 

+

1907 self.cog.callableMain(['argv0', '-']) 

+

1908 output = self.output.getvalue() 

+

1909 outerr = stderr.getvalue() 

+

1910 self.assertEqual(output, "--[[[cog cog.outl('Wow') ]]]\nWow\n--[[[end]]]\n") 

+

1911 self.assertEqual(outerr, "") 

+

1912 

+

1913 def testSuffixOutputLines(self): 

+

1914 d = { 

+

1915 'test.cog': """\ 

+

1916 Hey there. 

+

1917 ;[[[cog cog.outl('a\\nb\\n \\nc') ]]] 

+

1918 ;[[[end]]] 

+

1919 Good bye. 

+

1920 """, 

+

1921 

+

1922 'test.out': """\ 

+

1923 Hey there. 

+

1924 ;[[[cog cog.outl('a\\nb\\n \\nc') ]]] 

+

1925 a (foo) 

+

1926 b (foo) 

+

1927 """ # These three trailing spaces are important. 

+

1928 # The suffix is not applied to completely blank lines. 

+

1929 """ 

+

1930 c (foo) 

+

1931 ;[[[end]]] 

+

1932 Good bye. 

+

1933 """, 

+

1934 } 

+

1935 

+

1936 makeFiles(d) 

+

1937 self.cog.callableMain(['argv0', '-r', '-s', ' (foo)', 'test.cog']) 

+

1938 self.assertFilesSame('test.cog', 'test.out') 

+

1939 

+

1940 def testEmptySuffix(self): 

+

1941 d = { 

+

1942 'test.cog': """\ 

+

1943 ;[[[cog cog.outl('a\\nb\\nc') ]]] 

+

1944 ;[[[end]]] 

+

1945 """, 

+

1946 

+

1947 'test.out': """\ 

+

1948 ;[[[cog cog.outl('a\\nb\\nc') ]]] 

+

1949 a 

+

1950 b 

+

1951 c 

+

1952 ;[[[end]]] 

+

1953 """, 

+

1954 } 

+

1955 

+

1956 makeFiles(d) 

+

1957 self.cog.callableMain(['argv0', '-r', '-s', '', 'test.cog']) 

+

1958 self.assertFilesSame('test.cog', 'test.out') 

+

1959 

+

1960 def testHellishSuffix(self): 

+

1961 d = { 

+

1962 'test.cog': """\ 

+

1963 ;[[[cog cog.outl('a\\n\\nb') ]]] 

+

1964 """, 

+

1965 

+

1966 'test.out': """\ 

+

1967 ;[[[cog cog.outl('a\\n\\nb') ]]] 

+

1968 a /\\n*+([)]>< 

+

1969 

+

1970 b /\\n*+([)]>< 

+

1971 """, 

+

1972 } 

+

1973 

+

1974 makeFiles(d) 

+

1975 self.cog.callableMain(['argv0', '-z', '-r', '-s', r' /\n*+([)]><', 'test.cog']) 

+

1976 self.assertFilesSame('test.cog', 'test.out') 

+

1977 

+

1978 def testPrologue(self): 

+

1979 d = { 

+

1980 'test.cog': """\ 

+

1981 Some text. 

+

1982 //[[[cog cog.outl(str(math.sqrt(2))[:12])]]] 

+

1983 //[[[end]]] 

+

1984 epilogue. 

+

1985 """, 

+

1986 

+

1987 'test.out': """\ 

+

1988 Some text. 

+

1989 //[[[cog cog.outl(str(math.sqrt(2))[:12])]]] 

+

1990 1.4142135623 

+

1991 //[[[end]]] 

+

1992 epilogue. 

+

1993 """, 

+

1994 } 

+

1995 

+

1996 makeFiles(d) 

+

1997 self.cog.callableMain(['argv0', '-r', '-p', 'import math', 'test.cog']) 

+

1998 self.assertFilesSame('test.cog', 'test.out') 

+

1999 

+

2000 def testThreads(self): 

+

2001 # Test that the implictly imported cog module is actually different for 

+

2002 # different threads. 

+

2003 numthreads = 20 

+

2004 

+

2005 d = {} 

+

2006 for i in range(numthreads): 

+

2007 d['f{}.cog'.format(i)] = ( 

+

2008 "x\n" * i + 

+

2009 "[[[cog\n" + 

+

2010 "assert cog.firstLineNum == int(FIRST) == {}\n".format(i+1) + 

+

2011 "]]]\n" + 

+

2012 "[[[end]]]\n" 

+

2013 ) 

+

2014 makeFiles(d) 

+

2015 

+

2016 results = [] 

+

2017 

+

2018 def thread_main(num): 

+

2019 try: 

+

2020 ret = Cog().main( 

+

2021 ['cog.py', '-r', '-D', 'FIRST={}'.format(num+1), 'f{}.cog'.format(num)] 

+

2022 ) 

+

2023 assert ret == 0 

+

2024 except Exception as exc: 

+

2025 results.append(exc) 

+

2026 else: 

+

2027 results.append(None) 

+

2028 

+

2029 ts = [threading.Thread(target=thread_main, args=(i,)) for i in range(numthreads)] 

+

2030 for t in ts: 

+

2031 t.start() 

+

2032 for t in ts: 

+

2033 t.join() 

+

2034 assert results == [None] * numthreads 

+

2035 

+

2036 

+

2037class WritabilityTests(TestCaseWithTempDir): 

+

2038 

+

2039 d = { 

+

2040 'test.cog': """\ 

+

2041 //[[[cog 

+

2042 for fn in ['DoSomething', 'DoAnotherThing', 'DoLastThing']: 

+

2043 cog.outl("void %s();" % fn) 

+

2044 //]]] 

+

2045 //[[[end]]] 

+

2046 """, 

+

2047 

+

2048 'test.out': """\ 

+

2049 //[[[cog 

+

2050 for fn in ['DoSomething', 'DoAnotherThing', 'DoLastThing']: 

+

2051 cog.outl("void %s();" % fn) 

+

2052 //]]] 

+

2053 void DoSomething(); 

+

2054 void DoAnotherThing(); 

+

2055 void DoLastThing(); 

+

2056 //[[[end]]] 

+

2057 """, 

+

2058 } 

+

2059 

+

2060 if os.name == 'nt': #pragma: no cover 

+

2061 # for Windows 

+

2062 cmd_w_args = 'attrib -R %s' 

+

2063 cmd_w_asterisk = 'attrib -R *' 

+

2064 else: #pragma: no cover 

+

2065 # for unix-like 

+

2066 cmd_w_args = 'chmod +w %s' 

+

2067 cmd_w_asterisk = 'chmod +w *' 

+

2068 

+

2069 def setUp(self): 

+

2070 super(WritabilityTests, self).setUp() 

+

2071 makeFiles(self.d) 

+

2072 self.testcog = os.path.join(self.tempdir, 'test.cog') 

+

2073 os.chmod(self.testcog, stat.S_IREAD) # Make the file readonly. 

+

2074 assert not os.access(self.testcog, os.W_OK) 

+

2075 

+

2076 def tearDown(self): 

+

2077 os.chmod(self.testcog, stat.S_IWRITE) # Make the file writable again. 

+

2078 super(WritabilityTests, self).tearDown() 

+

2079 

+

2080 def testReadonlyNoCommand(self): 

+

2081 with self.assertRaisesRegex(CogError, "^Can't overwrite test.cog$"): 

+

2082 self.cog.callableMain(['argv0', '-r', 'test.cog']) 

+

2083 assert not os.access(self.testcog, os.W_OK) 

+

2084 

+

2085 def testReadonlyWithCommand(self): 

+

2086 self.cog.callableMain(['argv0', '-r', '-w', self.cmd_w_args, 'test.cog']) 

+

2087 self.assertFilesSame('test.cog', 'test.out') 

+

2088 assert os.access(self.testcog, os.W_OK) 

+

2089 

+

2090 def testReadonlyWithCommandWithNoSlot(self): 

+

2091 self.cog.callableMain(['argv0', '-r', '-w', self.cmd_w_asterisk, 'test.cog']) 

+

2092 self.assertFilesSame('test.cog', 'test.out') 

+

2093 assert os.access(self.testcog, os.W_OK) 

+

2094 

+

2095 def testReadonlyWithIneffectualCommand(self): 

+

2096 with self.assertRaisesRegex(CogError, "^Couldn't make test.cog writable$"): 

+

2097 self.cog.callableMain(['argv0', '-r', '-w', 'echo %s', 'test.cog']) 

+

2098 assert not os.access(self.testcog, os.W_OK) 

+

2099 

+

2100 

+

2101class ChecksumTests(TestCaseWithTempDir): 

+

2102 

+

2103 def testCreateChecksumOutput(self): 

+

2104 d = { 

+

2105 'cog1.txt': """\ 

+

2106 //[[[cog 

+

2107 cog.outl("This line was generated.") 

+

2108 //]]] 

+

2109 This line was generated. 

+

2110 //[[[end]]] 

+

2111 This line was not. 

+

2112 """, 

+

2113 

+

2114 'cog1.out': """\ 

+

2115 //[[[cog 

+

2116 cog.outl("This line was generated.") 

+

2117 //]]] 

+

2118 This line was generated. 

+

2119 //[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) 

+

2120 This line was not. 

+

2121 """, 

+

2122 } 

+

2123 

+

2124 makeFiles(d) 

+

2125 self.cog.callableMain(['argv0', '-r', '-c', 'cog1.txt']) 

+

2126 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

2127 

+

2128 def testCheckChecksumOutput(self): 

+

2129 d = { 

+

2130 'cog1.txt': """\ 

+

2131 //[[[cog 

+

2132 cog.outl("This line was newly") 

+

2133 cog.outl("generated by cog") 

+

2134 cog.outl("blah blah.") 

+

2135 //]]] 

+

2136 This line was generated. 

+

2137 //[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) 

+

2138 """, 

+

2139 

+

2140 'cog1.out': """\ 

+

2141 //[[[cog 

+

2142 cog.outl("This line was newly") 

+

2143 cog.outl("generated by cog") 

+

2144 cog.outl("blah blah.") 

+

2145 //]]] 

+

2146 This line was newly 

+

2147 generated by cog 

+

2148 blah blah. 

+

2149 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2150 """, 

+

2151 } 

+

2152 

+

2153 makeFiles(d) 

+

2154 self.cog.callableMain(['argv0', '-r', '-c', 'cog1.txt']) 

+

2155 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

2156 

+

2157 def testRemoveChecksumOutput(self): 

+

2158 d = { 

+

2159 'cog1.txt': """\ 

+

2160 //[[[cog 

+

2161 cog.outl("This line was newly") 

+

2162 cog.outl("generated by cog") 

+

2163 cog.outl("blah blah.") 

+

2164 //]]] 

+

2165 This line was generated. 

+

2166 //[[[end]]] (checksum: 8adb13fb59b996a1c7f0065ea9f3d893) fooey 

+

2167 """, 

+

2168 

+

2169 'cog1.out': """\ 

+

2170 //[[[cog 

+

2171 cog.outl("This line was newly") 

+

2172 cog.outl("generated by cog") 

+

2173 cog.outl("blah blah.") 

+

2174 //]]] 

+

2175 This line was newly 

+

2176 generated by cog 

+

2177 blah blah. 

+

2178 //[[[end]]] fooey 

+

2179 """, 

+

2180 } 

+

2181 

+

2182 makeFiles(d) 

+

2183 self.cog.callableMain(['argv0', '-r', 'cog1.txt']) 

+

2184 self.assertFilesSame('cog1.txt', 'cog1.out') 

+

2185 

+

2186 def testTamperedChecksumOutput(self): 

+

2187 d = { 

+

2188 'cog1.txt': """\ 

+

2189 //[[[cog 

+

2190 cog.outl("This line was newly") 

+

2191 cog.outl("generated by cog") 

+

2192 cog.outl("blah blah.") 

+

2193 //]]] 

+

2194 Xhis line was newly 

+

2195 generated by cog 

+

2196 blah blah. 

+

2197 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2198 """, 

+

2199 

+

2200 'cog2.txt': """\ 

+

2201 //[[[cog 

+

2202 cog.outl("This line was newly") 

+

2203 cog.outl("generated by cog") 

+

2204 cog.outl("blah blah.") 

+

2205 //]]] 

+

2206 This line was newly 

+

2207 generated by cog 

+

2208 blah blah! 

+

2209 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2210 """, 

+

2211 

+

2212 'cog3.txt': """\ 

+

2213 //[[[cog 

+

2214 cog.outl("This line was newly") 

+

2215 cog.outl("generated by cog") 

+

2216 cog.outl("blah blah.") 

+

2217 //]]] 

+

2218 

+

2219 This line was newly 

+

2220 generated by cog 

+

2221 blah blah. 

+

2222 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2223 """, 

+

2224 

+

2225 'cog4.txt': """\ 

+

2226 //[[[cog 

+

2227 cog.outl("This line was newly") 

+

2228 cog.outl("generated by cog") 

+

2229 cog.outl("blah blah.") 

+

2230 //]]] 

+

2231 This line was newly 

+

2232 generated by cog 

+

2233 blah blah.. 

+

2234 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2235 """, 

+

2236 

+

2237 'cog5.txt': """\ 

+

2238 //[[[cog 

+

2239 cog.outl("This line was newly") 

+

2240 cog.outl("generated by cog") 

+

2241 cog.outl("blah blah.") 

+

2242 //]]] 

+

2243 This line was newly 

+

2244 generated by cog 

+

2245 blah blah. 

+

2246 extra 

+

2247 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2248 """, 

+

2249 

+

2250 'cog6.txt': """\ 

+

2251 //[[[cog 

+

2252 cog.outl("This line was newly") 

+

2253 cog.outl("generated by cog") 

+

2254 cog.outl("blah blah.") 

+

2255 //]]] 

+

2256 //[[[end]]] (checksum: a8540982e5ad6b95c9e9a184b26f4346) 

+

2257 """, 

+

2258 } 

+

2259 

+

2260 makeFiles(d) 

+

2261 with self.assertRaisesRegex(CogError, 

+

2262 r"^cog1.txt\(9\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2263 self.cog.callableMain(['argv0', '-c', "cog1.txt"]) 

+

2264 with self.assertRaisesRegex(CogError, 

+

2265 r"^cog2.txt\(9\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2266 self.cog.callableMain(['argv0', '-c', "cog2.txt"]) 

+

2267 with self.assertRaisesRegex(CogError, 

+

2268 r"^cog3.txt\(10\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2269 self.cog.callableMain(['argv0', '-c', "cog3.txt"]) 

+

2270 with self.assertRaisesRegex(CogError, 

+

2271 r"^cog4.txt\(9\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2272 self.cog.callableMain(['argv0', '-c', "cog4.txt"]) 

+

2273 with self.assertRaisesRegex(CogError, 

+

2274 r"^cog5.txt\(10\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2275 self.cog.callableMain(['argv0', '-c', "cog5.txt"]) 

+

2276 with self.assertRaisesRegex(CogError, 

+

2277 r"^cog6.txt\(6\): Output has been edited! Delete old checksum to unprotect.$"): 

+

2278 self.cog.callableMain(['argv0', '-c', "cog6.txt"]) 

+

2279 

+

2280 def testArgvIsntModified(self): 

+

2281 argv = ['argv0', '-v'] 

+

2282 orig_argv = argv[:] 

+

2283 self.cog.callableMain(argv) 

+

2284 self.assertEqual(argv, orig_argv) 

+

2285 

+

2286 

+

2287class CustomMarkerTests(TestCaseWithTempDir): 

+

2288 

+

2289 def testCustomerMarkers(self): 

+

2290 d = { 

+

2291 'test.cog': """\ 

+

2292 //{{ 

+

2293 cog.outl("void %s();" % "MyFunction") 

+

2294 //}} 

+

2295 //{{end}} 

+

2296 """, 

+

2297 

+

2298 'test.out': """\ 

+

2299 //{{ 

+

2300 cog.outl("void %s();" % "MyFunction") 

+

2301 //}} 

+

2302 void MyFunction(); 

+

2303 //{{end}} 

+

2304 """, 

+

2305 } 

+

2306 

+

2307 makeFiles(d) 

+

2308 self.cog.callableMain([ 

+

2309 'argv0', '-r', 

+

2310 '--markers={{ }} {{end}}', 

+

2311 'test.cog' 

+

2312 ]) 

+

2313 self.assertFilesSame('test.cog', 'test.out') 

+

2314 

+

2315 def testTrulyWackyMarkers(self): 

+

2316 # Make sure the markers are properly re-escaped. 

+

2317 d = { 

+

2318 'test.cog': """\ 

+

2319 //**( 

+

2320 cog.outl("void %s();" % "MyFunction") 

+

2321 //**) 

+

2322 //**(end)** 

+

2323 """, 

+

2324 

+

2325 'test.out': """\ 

+

2326 //**( 

+

2327 cog.outl("void %s();" % "MyFunction") 

+

2328 //**) 

+

2329 void MyFunction(); 

+

2330 //**(end)** 

+

2331 """, 

+

2332 } 

+

2333 

+

2334 makeFiles(d) 

+

2335 self.cog.callableMain([ 

+

2336 'argv0', '-r', 

+

2337 '--markers=**( **) **(end)**', 

+

2338 'test.cog' 

+

2339 ]) 

+

2340 self.assertFilesSame('test.cog', 'test.out') 

+

2341 

+

2342 def testChangeJustOneMarker(self): 

+

2343 d = { 

+

2344 'test.cog': """\ 

+

2345 //**( 

+

2346 cog.outl("void %s();" % "MyFunction") 

+

2347 //]]] 

+

2348 //[[[end]]] 

+

2349 """, 

+

2350 

+

2351 'test.out': """\ 

+

2352 //**( 

+

2353 cog.outl("void %s();" % "MyFunction") 

+

2354 //]]] 

+

2355 void MyFunction(); 

+

2356 //[[[end]]] 

+

2357 """, 

+

2358 } 

+

2359 

+

2360 makeFiles(d) 

+

2361 self.cog.callableMain([ 

+

2362 'argv0', '-r', 

+

2363 '--markers=**( ]]] [[[end]]]', 

+

2364 'test.cog' 

+

2365 ]) 

+

2366 self.assertFilesSame('test.cog', 'test.out') 

+

2367 

+

2368 

+

2369class BlakeTests(TestCaseWithTempDir): 

+

2370 

+

2371 # Blake Winton's contributions. 

+

2372 def testDeleteCode(self): 

+

2373 # -o sets the output file. 

+

2374 d = { 

+

2375 'test.cog': """\ 

+

2376 // This is my C++ file. 

+

2377 //[[[cog 

+

2378 fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing'] 

+

2379 for fn in fnames: 

+

2380 cog.outl("void %s();" % fn) 

+

2381 //]]] 

+

2382 Some Sample Code Here 

+

2383 //[[[end]]]Data Data 

+

2384 And Some More 

+

2385 """, 

+

2386 

+

2387 'test.out': """\ 

+

2388 // This is my C++ file. 

+

2389 void DoSomething(); 

+

2390 void DoAnotherThing(); 

+

2391 void DoLastThing(); 

+

2392 And Some More 

+

2393 """, 

+

2394 } 

+

2395 

+

2396 makeFiles(d) 

+

2397 self.cog.callableMain(['argv0', '-d', '-o', 'test.cogged', 'test.cog']) 

+

2398 self.assertFilesSame('test.cogged', 'test.out') 

+

2399 

+

2400 def testDeleteCodeWithDashRFails(self): 

+

2401 d = { 

+

2402 'test.cog': """\ 

+

2403 // This is my C++ file. 

+

2404 """ 

+

2405 } 

+

2406 

+

2407 makeFiles(d) 

+

2408 with self.assertRaisesRegex(CogUsageError, r"^Can't use -d with -r \(or you would delete all your source!\)$"): 

+

2409 self.cog.callableMain(['argv0', '-r', '-d', 'test.cog']) 

+

2410 

+

2411 def testSettingGlobals(self): 

+

2412 # Blake Winton contributed a way to set the globals that will be used in 

+

2413 # processFile(). 

+

2414 d = { 

+

2415 'test.cog': """\ 

+

2416 // This is my C++ file. 

+

2417 //[[[cog 

+

2418 for fn in fnames: 

+

2419 cog.outl("void %s();" % fn) 

+

2420 //]]] 

+

2421 Some Sample Code Here 

+

2422 //[[[end]]]""", 

+

2423 

+

2424 'test.out': """\ 

+

2425 // This is my C++ file. 

+

2426 void DoBlake(); 

+

2427 void DoWinton(); 

+

2428 void DoContribution(); 

+

2429 """, 

+

2430 } 

+

2431 

+

2432 makeFiles(d) 

+

2433 globals = {} 

+

2434 globals['fnames'] = ['DoBlake', 'DoWinton', 'DoContribution'] 

+

2435 self.cog.options.bDeleteCode = True 

+

2436 self.cog.processFile('test.cog', 'test.cogged', globals=globals) 

+

2437 self.assertFilesSame('test.cogged', 'test.out') 

+

2438 

+

2439 

+

2440class ErrorCallTests(TestCaseWithTempDir): 

+

2441 

+

2442 def testErrorCallHasNoTraceback(self): 

+

2443 # Test that cog.error() doesn't show a traceback. 

+

2444 d = { 

+

2445 'error.cog': """\ 

+

2446 //[[[cog 

+

2447 cog.error("Something Bad!") 

+

2448 //]]] 

+

2449 //[[[end]]] 

+

2450 """, 

+

2451 } 

+

2452 

+

2453 makeFiles(d) 

+

2454 self.cog.main(['argv0', '-r', 'error.cog']) 

+

2455 output = self.output.getvalue() 

+

2456 self.assertEqual(output, "Cogging error.cog\nError: Something Bad!\n") 

+

2457 

+

2458 def testRealErrorHasTraceback(self): 

+

2459 # Test that a genuine error does show a traceback. 

+

2460 d = { 

+

2461 'error.cog': """\ 

+

2462 //[[[cog 

+

2463 raise RuntimeError("Hey!") 

+

2464 //]]] 

+

2465 //[[[end]]] 

+

2466 """, 

+

2467 } 

+

2468 

+

2469 makeFiles(d) 

+

2470 self.cog.main(['argv0', '-r', 'error.cog']) 

+

2471 output = self.output.getvalue() 

+

2472 msg = 'Actual output:\n' + output 

+

2473 self.assertTrue(output.startswith("Cogging error.cog\nTraceback (most recent"), msg) 

+

2474 self.assertIn("RuntimeError: Hey!", output) 

+

2475 

+

2476 

+

2477# Things not yet tested: 

+

2478# - A bad -w command (currently fails silently). 

- - diff --git a/doc/sample_html/cogapp_test_makefiles_py.html b/doc/sample_html/cogapp_test_makefiles_py.html index c9c123dd..9b0f0f35 100644 --- a/doc/sample_html/cogapp_test_makefiles_py.html +++ b/doc/sample_html/cogapp_test_makefiles_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/test_makefiles.py: 100.00% + Coverage for cogapp/test_makefiles.py: 23.38% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,212 +51,137 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

- -
-

""" Test the cogapp.makefiles modules 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

 

-

import unittest 

-

import shutil, os, random, tempfile 

-

 

-

from . import makefiles 

-

 

-

 

-

class SimpleTests(unittest.TestCase): 

-

 

-

def setUp(self): 

-

# Create a temporary directory. 

-

my_dir = 'testmakefiles_tempdir_' + str(random.random())[2:] 

-

self.tempdir = os.path.join(tempfile.gettempdir(), my_dir) 

-

os.mkdir(self.tempdir) 

-

 

-

def tearDown(self): 

-

# Get rid of the temporary directory. 

-

shutil.rmtree(self.tempdir) 

-

 

-

def exists(self, dname, fname): 

-

return os.path.exists(os.path.join(dname, fname)) 

-

 

-

def checkFilesExist(self, d, dname): 

-

for fname in d.keys(): 

-

assert(self.exists(dname, fname)) 

-

if type(d[fname]) == type({}): 

-

self.checkFilesExist(d[fname], os.path.join(dname, fname)) 

-

 

-

def checkFilesDontExist(self, d, dname): 

-

for fname in d.keys(): 

-

assert(not self.exists(dname, fname)) 

-

 

-

def testOneFile(self): 

-

fname = 'foo.txt' 

-

notfname = 'not_here.txt' 

-

d = { fname: "howdy" } 

-

assert(not self.exists(self.tempdir, fname)) 

-

assert(not self.exists(self.tempdir, notfname)) 

-

 

-

makefiles.makeFiles(d, self.tempdir) 

-

assert(self.exists(self.tempdir, fname)) 

-

assert(not self.exists(self.tempdir, notfname)) 

-

 

-

makefiles.removeFiles(d, self.tempdir) 

-

assert(not self.exists(self.tempdir, fname)) 

-

assert(not self.exists(self.tempdir, notfname)) 

-

 

-

def testManyFiles(self): 

-

d = { 

-

'top1.txt': "howdy", 

-

'top2.txt': "hello", 

-

'sub': { 

-

'sub1.txt': "inside", 

-

'sub2.txt': "inside2" 

-

}, 

-

} 

-

 

-

self.checkFilesDontExist(d, self.tempdir) 

-

makefiles.makeFiles(d, self.tempdir) 

-

self.checkFilesExist(d, self.tempdir) 

-

makefiles.removeFiles(d, self.tempdir) 

-

self.checkFilesDontExist(d, self.tempdir) 

-

 

-

def testContents(self): 

-

fname = 'bar.txt' 

-

cont0 = "I am bar.txt" 

-

d = { fname: cont0 } 

-

makefiles.makeFiles(d, self.tempdir) 

-

fcont1 = open(os.path.join(self.tempdir, fname)) 

-

assert(fcont1.read() == cont0) 

-

fcont1.close() 

-

 

-

def testDedent(self): 

-

fname = 'dedent.txt' 

-

d = { fname: """\ 

-

This is dedent.txt 

-

\tTabbed in. 

-

spaced in. 

-

OK. 

-

""" 

-

} 

-

makefiles.makeFiles(d, self.tempdir) 

-

fcont = open(os.path.join(self.tempdir, fname)) 

-

assert(fcont.read() == "This is dedent.txt\n\tTabbed in.\n spaced in.\nOK.\n") 

-

fcont.close() 

- -
+

1""" Test the cogapp.makefiles modules 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2019, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9import shutil 

+

10import os 

+

11import random 

+

12import tempfile 

+

13 

+

14from . import makefiles 

+

15from .backward import TestCase 

+

16 

+

17 

+

18class SimpleTests(TestCase): 

+

19 

+

20 def setUp(self): 

+

21 # Create a temporary directory. 

+

22 my_dir = 'testmakefiles_tempdir_' + str(random.random())[2:] 

+

23 self.tempdir = os.path.join(tempfile.gettempdir(), my_dir) 

+

24 os.mkdir(self.tempdir) 

+

25 

+

26 def tearDown(self): 

+

27 # Get rid of the temporary directory. 

+

28 shutil.rmtree(self.tempdir) 

+

29 

+

30 def exists(self, dname, fname): 

+

31 return os.path.exists(os.path.join(dname, fname)) 

+

32 

+

33 def checkFilesExist(self, d, dname): 

+

34 for fname in d.keys(): 

+

35 assert(self.exists(dname, fname)) 

+

36 if type(d[fname]) == type({}): 

+

37 self.checkFilesExist(d[fname], os.path.join(dname, fname)) 

+

38 

+

39 def checkFilesDontExist(self, d, dname): 

+

40 for fname in d.keys(): 

+

41 assert(not self.exists(dname, fname)) 

+

42 

+

43 def testOneFile(self): 

+

44 fname = 'foo.txt' 

+

45 notfname = 'not_here.txt' 

+

46 d = { fname: "howdy" } 

+

47 assert(not self.exists(self.tempdir, fname)) 

+

48 assert(not self.exists(self.tempdir, notfname)) 

+

49 

+

50 makefiles.makeFiles(d, self.tempdir) 

+

51 assert(self.exists(self.tempdir, fname)) 

+

52 assert(not self.exists(self.tempdir, notfname)) 

+

53 

+

54 makefiles.removeFiles(d, self.tempdir) 

+

55 assert(not self.exists(self.tempdir, fname)) 

+

56 assert(not self.exists(self.tempdir, notfname)) 

+

57 

+

58 def testManyFiles(self): 

+

59 d = { 

+

60 'top1.txt': "howdy", 

+

61 'top2.txt': "hello", 

+

62 'sub': { 

+

63 'sub1.txt': "inside", 

+

64 'sub2.txt': "inside2", 

+

65 }, 

+

66 } 

+

67 

+

68 self.checkFilesDontExist(d, self.tempdir) 

+

69 makefiles.makeFiles(d, self.tempdir) 

+

70 self.checkFilesExist(d, self.tempdir) 

+

71 makefiles.removeFiles(d, self.tempdir) 

+

72 self.checkFilesDontExist(d, self.tempdir) 

+

73 

+

74 def testOverlapping(self): 

+

75 d1 = { 

+

76 'top1.txt': "howdy", 

+

77 'sub': { 

+

78 'sub1.txt': "inside", 

+

79 }, 

+

80 } 

+

81 

+

82 d2 = { 

+

83 'top2.txt': "hello", 

+

84 'sub': { 

+

85 'sub2.txt': "inside2", 

+

86 }, 

+

87 } 

+

88 

+

89 self.checkFilesDontExist(d1, self.tempdir) 

+

90 self.checkFilesDontExist(d2, self.tempdir) 

+

91 makefiles.makeFiles(d1, self.tempdir) 

+

92 makefiles.makeFiles(d2, self.tempdir) 

+

93 self.checkFilesExist(d1, self.tempdir) 

+

94 self.checkFilesExist(d2, self.tempdir) 

+

95 makefiles.removeFiles(d1, self.tempdir) 

+

96 makefiles.removeFiles(d2, self.tempdir) 

+

97 self.checkFilesDontExist(d1, self.tempdir) 

+

98 self.checkFilesDontExist(d2, self.tempdir) 

+

99 

+

100 def testContents(self): 

+

101 fname = 'bar.txt' 

+

102 cont0 = "I am bar.txt" 

+

103 d = { fname: cont0 } 

+

104 makefiles.makeFiles(d, self.tempdir) 

+

105 fcont1 = open(os.path.join(self.tempdir, fname)) 

+

106 assert(fcont1.read() == cont0) 

+

107 fcont1.close() 

+

108 

+

109 def testDedent(self): 

+

110 fname = 'dedent.txt' 

+

111 d = { 

+

112 fname: """\ 

+

113 This is dedent.txt 

+

114 \tTabbed in. 

+

115 spaced in. 

+

116 OK. 

+

117 """, 

+

118 } 

+

119 makefiles.makeFiles(d, self.tempdir) 

+

120 fcont = open(os.path.join(self.tempdir, fname)) 

+

121 assert(fcont.read() == "This is dedent.txt\n\tTabbed in.\n spaced in.\nOK.\n") 

+

122 fcont.close() 

- - diff --git a/doc/sample_html/cogapp_test_whiteutils_py.html b/doc/sample_html/cogapp_test_whiteutils_py.html index 839d199c..a069a598 100644 --- a/doc/sample_html/cogapp_test_whiteutils_py.html +++ b/doc/sample_html/cogapp_test_whiteutils_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/test_whiteutils.py: 100.00% + Coverage for cogapp/test_whiteutils.py: 27.54% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,232 +51,116 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

- -
-

""" Test the cogapp.whiteutils module. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

 

-

import unittest 

-

 

-

from .whiteutils import * 

-

 

-

 

-

class WhitePrefixTests(unittest.TestCase): 

-

""" Test cases for cogapp.whiteutils. 

-

""" 

-

def testSingleLine(self): 

-

self.assertEqual(whitePrefix(['']), '') 

-

self.assertEqual(whitePrefix([' ']), '') 

-

self.assertEqual(whitePrefix(['x']), '') 

-

self.assertEqual(whitePrefix([' x']), ' ') 

-

self.assertEqual(whitePrefix(['\tx']), '\t') 

-

self.assertEqual(whitePrefix([' x']), ' ') 

-

self.assertEqual(whitePrefix([' \t \tx ']), ' \t \t') 

-

 

-

def testMultiLine(self): 

-

self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

-

self.assertEqual(whitePrefix([' y',' y',' y']), ' ') 

-

self.assertEqual(whitePrefix([' y',' y',' y']), ' ') 

-

 

-

def testBlankLinesAreIgnored(self): 

-

self.assertEqual(whitePrefix([' x',' x','',' x']), ' ') 

-

self.assertEqual(whitePrefix(['',' x',' x',' x']), ' ') 

-

self.assertEqual(whitePrefix([' x',' x',' x','']), ' ') 

-

self.assertEqual(whitePrefix([' x',' x',' ',' x']), ' ') 

-

 

-

def testTabCharacters(self): 

-

self.assertEqual(whitePrefix(['\timport sys', '', '\tprint sys.argv']), '\t') 

-

 

-

def testDecreasingLengths(self): 

-

self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

-

self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

-

 

-

 

-

class ReindentBlockTests(unittest.TestCase): 

-

""" Test cases for cogapp.reindentBlock. 

-

""" 

-

def testNonTermLine(self): 

-

self.assertEqual(reindentBlock(''), '') 

-

self.assertEqual(reindentBlock('x'), 'x') 

-

self.assertEqual(reindentBlock(' x'), 'x') 

-

self.assertEqual(reindentBlock(' x'), 'x') 

-

self.assertEqual(reindentBlock('\tx'), 'x') 

-

self.assertEqual(reindentBlock('x', ' '), ' x') 

-

self.assertEqual(reindentBlock('x', '\t'), '\tx') 

-

self.assertEqual(reindentBlock(' x', ' '), ' x') 

-

self.assertEqual(reindentBlock(' x', '\t'), '\tx') 

-

self.assertEqual(reindentBlock(' x', ' '), ' x') 

-

 

-

def testSingleLine(self): 

-

self.assertEqual(reindentBlock('\n'), '\n') 

-

self.assertEqual(reindentBlock('x\n'), 'x\n') 

-

self.assertEqual(reindentBlock(' x\n'), 'x\n') 

-

self.assertEqual(reindentBlock(' x\n'), 'x\n') 

-

self.assertEqual(reindentBlock('\tx\n'), 'x\n') 

-

self.assertEqual(reindentBlock('x\n', ' '), ' x\n') 

-

self.assertEqual(reindentBlock('x\n', '\t'), '\tx\n') 

-

self.assertEqual(reindentBlock(' x\n', ' '), ' x\n') 

-

self.assertEqual(reindentBlock(' x\n', '\t'), '\tx\n') 

-

self.assertEqual(reindentBlock(' x\n', ' '), ' x\n') 

-

 

-

def testRealBlock(self): 

-

self.assertEqual( 

-

reindentBlock('\timport sys\n\n\tprint sys.argv\n'), 

-

'import sys\n\nprint sys.argv\n' 

-

) 

-

 

-

 

-

class CommonPrefixTests(unittest.TestCase): 

-

""" Test cases for cogapp.commonPrefix. 

-

""" 

-

def testDegenerateCases(self): 

-

self.assertEqual(commonPrefix([]), '') 

-

self.assertEqual(commonPrefix(['']), '') 

-

self.assertEqual(commonPrefix(['','','','','']), '') 

-

self.assertEqual(commonPrefix(['cat in the hat']), 'cat in the hat') 

-

 

-

def testNoCommonPrefix(self): 

-

self.assertEqual(commonPrefix(['a','b']), '') 

-

self.assertEqual(commonPrefix(['a','b','c','d','e','f']), '') 

-

self.assertEqual(commonPrefix(['a','a','a','a','a','x']), '') 

-

 

-

def testUsualCases(self): 

-

self.assertEqual(commonPrefix(['ab', 'ac']), 'a') 

-

self.assertEqual(commonPrefix(['aab', 'aac']), 'aa') 

-

self.assertEqual(commonPrefix(['aab', 'aab', 'aab', 'aac']), 'aa') 

-

 

-

def testBlankLine(self): 

-

self.assertEqual(commonPrefix(['abc', 'abx', '', 'aby']), '') 

-

 

-

def testDecreasingLengths(self): 

-

self.assertEqual(commonPrefix(['abcd', 'abc', 'ab']), 'ab') 

- -
+

1""" Test the cogapp.whiteutils module. 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2019, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9from .backward import TestCase 

+

10from .whiteutils import * 

+

11 

+

12 

+

13class WhitePrefixTests(TestCase): 

+

14 """ Test cases for cogapp.whiteutils. 

+

15 """ 

+

16 def testSingleLine(self): 

+

17 self.assertEqual(whitePrefix(['']), '') 

+

18 self.assertEqual(whitePrefix([' ']), '') 

+

19 self.assertEqual(whitePrefix(['x']), '') 

+

20 self.assertEqual(whitePrefix([' x']), ' ') 

+

21 self.assertEqual(whitePrefix(['\tx']), '\t') 

+

22 self.assertEqual(whitePrefix([' x']), ' ') 

+

23 self.assertEqual(whitePrefix([' \t \tx ']), ' \t \t') 

+

24 

+

25 def testMultiLine(self): 

+

26 self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

+

27 self.assertEqual(whitePrefix([' y',' y',' y']), ' ') 

+

28 self.assertEqual(whitePrefix([' y',' y',' y']), ' ') 

+

29 

+

30 def testBlankLinesAreIgnored(self): 

+

31 self.assertEqual(whitePrefix([' x',' x','',' x']), ' ') 

+

32 self.assertEqual(whitePrefix(['',' x',' x',' x']), ' ') 

+

33 self.assertEqual(whitePrefix([' x',' x',' x','']), ' ') 

+

34 self.assertEqual(whitePrefix([' x',' x',' ',' x']), ' ') 

+

35 

+

36 def testTabCharacters(self): 

+

37 self.assertEqual(whitePrefix(['\timport sys', '', '\tprint sys.argv']), '\t') 

+

38 

+

39 def testDecreasingLengths(self): 

+

40 self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

+

41 self.assertEqual(whitePrefix([' x',' x',' x']), ' ') 

+

42 

+

43 

+

44class ReindentBlockTests(TestCase): 

+

45 """ Test cases for cogapp.reindentBlock. 

+

46 """ 

+

47 def testNonTermLine(self): 

+

48 self.assertEqual(reindentBlock(''), '') 

+

49 self.assertEqual(reindentBlock('x'), 'x') 

+

50 self.assertEqual(reindentBlock(' x'), 'x') 

+

51 self.assertEqual(reindentBlock(' x'), 'x') 

+

52 self.assertEqual(reindentBlock('\tx'), 'x') 

+

53 self.assertEqual(reindentBlock('x', ' '), ' x') 

+

54 self.assertEqual(reindentBlock('x', '\t'), '\tx') 

+

55 self.assertEqual(reindentBlock(' x', ' '), ' x') 

+

56 self.assertEqual(reindentBlock(' x', '\t'), '\tx') 

+

57 self.assertEqual(reindentBlock(' x', ' '), ' x') 

+

58 

+

59 def testSingleLine(self): 

+

60 self.assertEqual(reindentBlock('\n'), '\n') 

+

61 self.assertEqual(reindentBlock('x\n'), 'x\n') 

+

62 self.assertEqual(reindentBlock(' x\n'), 'x\n') 

+

63 self.assertEqual(reindentBlock(' x\n'), 'x\n') 

+

64 self.assertEqual(reindentBlock('\tx\n'), 'x\n') 

+

65 self.assertEqual(reindentBlock('x\n', ' '), ' x\n') 

+

66 self.assertEqual(reindentBlock('x\n', '\t'), '\tx\n') 

+

67 self.assertEqual(reindentBlock(' x\n', ' '), ' x\n') 

+

68 self.assertEqual(reindentBlock(' x\n', '\t'), '\tx\n') 

+

69 self.assertEqual(reindentBlock(' x\n', ' '), ' x\n') 

+

70 

+

71 def testRealBlock(self): 

+

72 self.assertEqual( 

+

73 reindentBlock('\timport sys\n\n\tprint sys.argv\n'), 

+

74 'import sys\n\nprint sys.argv\n' 

+

75 ) 

+

76 

+

77 

+

78class CommonPrefixTests(TestCase): 

+

79 """ Test cases for cogapp.commonPrefix. 

+

80 """ 

+

81 def testDegenerateCases(self): 

+

82 self.assertEqual(commonPrefix([]), '') 

+

83 self.assertEqual(commonPrefix(['']), '') 

+

84 self.assertEqual(commonPrefix(['','','','','']), '') 

+

85 self.assertEqual(commonPrefix(['cat in the hat']), 'cat in the hat') 

+

86 

+

87 def testNoCommonPrefix(self): 

+

88 self.assertEqual(commonPrefix(['a','b']), '') 

+

89 self.assertEqual(commonPrefix(['a','b','c','d','e','f']), '') 

+

90 self.assertEqual(commonPrefix(['a','a','a','a','a','x']), '') 

+

91 

+

92 def testUsualCases(self): 

+

93 self.assertEqual(commonPrefix(['ab', 'ac']), 'a') 

+

94 self.assertEqual(commonPrefix(['aab', 'aac']), 'aa') 

+

95 self.assertEqual(commonPrefix(['aab', 'aab', 'aab', 'aac']), 'aa') 

+

96 

+

97 def testBlankLine(self): 

+

98 self.assertEqual(commonPrefix(['abc', 'abx', '', 'aby']), '') 

+

99 

+

100 def testDecreasingLengths(self): 

+

101 self.assertEqual(commonPrefix(['abcd', 'abc', 'ab']), 'ab') 

- - diff --git a/doc/sample_html/cogapp_whiteutils_py.html b/doc/sample_html/cogapp_whiteutils_py.html index 7d714ca7..91546713 100644 --- a/doc/sample_html/cogapp_whiteutils_py.html +++ b/doc/sample_html/cogapp_whiteutils_py.html @@ -1,16 +1,10 @@ - - - - - - Coverage for cogapp/whiteutils.py: 98.70% + Coverage for cogapp/whiteutils.py: 88.61% - @@ -20,28 +14,21 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -64,170 +51,88 @@

-
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

- -
-

""" Indentation utilities for Cog. 

-

http://nedbatchelder.com/code/cog 

-

 

-

Copyright 2004-2015, Ned Batchelder. 

-

""" 

-

 

-

from __future__ import absolute_import 

-

import re 

-

from .backward import string_types, bytes_types, to_bytes, b 

-

 

-

def whitePrefix(strings): 

-

""" Determine the whitespace prefix common to all non-blank lines 

-

in the argument list. 

-

""" 

-

# Remove all blank lines from the list 

-

strings = [s for s in strings if s.strip() != ''] 

-

 

-

if not strings: return '' 

-

 

-

# Find initial whitespace chunk in the first line. 

-

# This is the best prefix we can hope for. 

-

pat = r'\s*' 

-

23 ↛ 25line 23 didn't jump to line 25, because the condition on line 23 was never false if isinstance(strings[0], bytes_types): 

-

pat = to_bytes(pat) 

-

prefix = re.match(pat, strings[0]).group(0) 

-

 

-

# Loop over the other strings, keeping only as much of 

-

# the prefix as matches each string. 

-

for s in strings: 

-

for i in range(len(prefix)): 

-

if prefix[i] != s[i]: 

-

prefix = prefix[:i] 

-

break 

-

return prefix 

-

 

-

def reindentBlock(lines, newIndent=''): 

-

""" Take a block of text as a string or list of lines. 

-

Remove any common whitespace indentation. 

-

Re-indent using newIndent, and return it as a single string. 

-

""" 

-

sep, nothing = '\n', '' 

-

if isinstance(lines, bytes_types): 

-

sep, nothing = b('\n'), b('') 

-

if isinstance(lines, string_types): 

-

lines = lines.split(sep) 

-

oldIndent = whitePrefix(lines) 

-

outLines = [] 

-

for l in lines: 

-

if oldIndent: 

-

l = l.replace(oldIndent, nothing, 1) 

-

if l and newIndent: 

-

l = newIndent + l 

-

outLines.append(l) 

-

return sep.join(outLines) 

-

 

-

def commonPrefix(strings): 

-

""" Find the longest string that is a prefix of all the strings. 

-

""" 

-

if not strings: 

-

return '' 

-

prefix = strings[0] 

-

for s in strings: 

-

if len(s) < len(prefix): 

-

prefix = prefix[:len(s)] 

-

if not prefix: 

-

return '' 

-

for i in range(len(prefix)): 

-

if prefix[i] != s[i]: 

-

prefix = prefix[:i] 

-

break 

-

return prefix 

- -
+

1""" Indentation utilities for Cog. 

+

2 http://nedbatchelder.com/code/cog 

+

3 

+

4 Copyright 2004-2019, Ned Batchelder. 

+

5""" 

+

6 

+

7from __future__ import absolute_import 

+

8 

+

9import re 

+

10 

+

11from .backward import string_types, bytes_types, to_bytes 

+

12 

+

13def whitePrefix(strings): 

+

14 """ Determine the whitespace prefix common to all non-blank lines 

+

15 in the argument list. 

+

16 """ 

+

17 # Remove all blank lines from the list 

+

18 strings = [s for s in strings if s.strip() != ''] 

+

19 

+

20 if not strings: return '' 

+

21 

+

22 # Find initial whitespace chunk in the first line. 

+

23 # This is the best prefix we can hope for. 

+

24 pat = r'\s*' 

+

25 if isinstance(strings[0], bytes_types): 25 ↛ 26line 25 didn't jump to line 26, because the condition on line 25 was never true

+

26 pat = to_bytes(pat) 

+

27 prefix = re.match(pat, strings[0]).group(0) 

+

28 

+

29 # Loop over the other strings, keeping only as much of 

+

30 # the prefix as matches each string. 

+

31 for s in strings: 

+

32 for i in range(len(prefix)): 

+

33 if prefix[i] != s[i]: 33 ↛ 34line 33 didn't jump to line 34, because the condition on line 33 was never true

+

34 prefix = prefix[:i] 

+

35 break 

+

36 return prefix 

+

37 

+

38def reindentBlock(lines, newIndent=''): 

+

39 """ Take a block of text as a string or list of lines. 

+

40 Remove any common whitespace indentation. 

+

41 Re-indent using newIndent, and return it as a single string. 

+

42 """ 

+

43 sep, nothing = '\n', '' 

+

44 if isinstance(lines, bytes_types): 44 ↛ 45line 44 didn't jump to line 45, because the condition on line 44 was never true

+

45 sep, nothing = b'\n', b'' 

+

46 if isinstance(lines, string_types): 

+

47 lines = lines.split(sep) 

+

48 oldIndent = whitePrefix(lines) 

+

49 outLines = [] 

+

50 for l in lines: 

+

51 if oldIndent: 

+

52 l = l.replace(oldIndent, nothing, 1) 

+

53 if l and newIndent: 

+

54 l = newIndent + l 

+

55 outLines.append(l) 

+

56 return sep.join(outLines) 

+

57 

+

58def commonPrefix(strings): 

+

59 """ Find the longest string that is a prefix of all the strings. 

+

60 """ 

+

61 if not strings: 61 ↛ 62line 61 didn't jump to line 62, because the condition on line 61 was never true

+

62 return '' 

+

63 prefix = strings[0] 

+

64 for s in strings: 

+

65 if len(s) < len(prefix): 

+

66 prefix = prefix[:len(s)] 

+

67 if not prefix: 

+

68 return '' 

+

69 for i in range(len(prefix)): 

+

70 if prefix[i] != s[i]: 

+

71 prefix = prefix[:i] 

+

72 break 

+

73 return prefix 

- - diff --git a/doc/sample_html/coverage_html.js b/doc/sample_html/coverage_html.js index 84b5a7e0..22152333 100644 --- a/doc/sample_html/coverage_html.js +++ b/doc/sample_html/coverage_html.js @@ -169,22 +169,13 @@ coverage.wire_up_filter = function () { // Loaded on index.html coverage.index_ready = function ($) { - // Look for a cookie containing previous sort settings: + // Look for a localStorage item containing previous sort settings: var sort_list = []; - var cookie_name = "COVERAGE_INDEX_SORT"; - var i; + var storage_name = "COVERAGE_INDEX_SORT"; + var stored_list = localStorage.getItem(storage_name); - // This almost makes it worth installing the jQuery cookie plugin: - if (document.cookie.indexOf(cookie_name) > -1) { - var cookies = document.cookie.split(";"); - for (i = 0; i < cookies.length; i++) { - var parts = cookies[i].split("="); - - if ($.trim(parts[0]) === cookie_name && parts[1]) { - sort_list = eval("[[" + parts[1] + "]]"); - break; - } - } + if (stored_list) { + sort_list = JSON.parse('[[' + stored_list + ']]'); } // Create a new widget which exists only to save and restore @@ -231,7 +222,7 @@ coverage.index_ready = function ($) { // Watch for page unload events so we can save the final sort settings: $(window).unload(function () { - document.cookie = cookie_name + "=" + sort_list.toString() + "; path=/"; + localStorage.setItem(storage_name, sort_list.toString()) }); }; @@ -240,7 +231,7 @@ coverage.index_ready = function ($) { coverage.pyfile_ready = function ($) { // If we're directed to a particular line number, highlight the line. var frag = location.hash; - if (frag.length > 2 && frag[1] === 'n') { + if (frag.length > 2 && frag[1] === 't') { $(frag).addClass('highlight'); coverage.set_sel(parseInt(frag.substr(2), 10)); } @@ -265,21 +256,22 @@ coverage.pyfile_ready = function ($) { coverage.init_scroll_markers(); - // Rebuild scroll markers after window high changing - $(window).resize(coverage.resize_scroll_markers); + // Rebuild scroll markers when the window height changes. + $(window).resize(coverage.build_scroll_markers); }; coverage.toggle_lines = function (btn, cls) { btn = $(btn); - var hide = "hide_"+cls; - if (btn.hasClass(hide)) { - $("#source ."+cls).removeClass(hide); - btn.removeClass(hide); + var show = "show_"+cls; + if (btn.hasClass(show)) { + $("#source ." + cls).removeClass(show); + btn.removeClass(show); } else { - $("#source ."+cls).addClass(hide); - btn.addClass(hide); + $("#source ." + cls).addClass(show); + btn.addClass(show); } + coverage.build_scroll_markers(); }; // Return the nth line div. @@ -292,11 +284,6 @@ coverage.num_elt = function (n) { return $("#n" + n); }; -// Return the container of all the code. -coverage.code_container = function () { - return $(".linenos"); -}; - // Set the selection. b and e are line numbers. coverage.set_sel = function (b, e) { // The first line selected. @@ -315,9 +302,17 @@ coverage.to_first_chunk = function () { coverage.to_next_chunk(); }; -coverage.is_transparent = function (color) { - // Different browsers return different colors for "none". - return color === "transparent" || color === "rgba(0, 0, 0, 0)"; +// Return a string indicating what kind of chunk this line belongs to, +// or null if not a chunk. +coverage.chunk_indicator = function (line_elt) { + var klass = line_elt.attr('class'); + if (klass) { + var m = klass.match(/\bshow_\w+\b/); + if (m) { + return m[0]; + } + } + return null; }; coverage.to_next_chunk = function () { @@ -325,14 +320,14 @@ coverage.to_next_chunk = function () { // Find the start of the next colored chunk. var probe = c.sel_end; - var color, probe_line; + var chunk_indicator, probe_line; while (true) { probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } - color = probe_line.css("background-color"); - if (!c.is_transparent(color)) { + chunk_indicator = c.chunk_indicator(probe_line); + if (chunk_indicator) { break; } probe++; @@ -342,11 +337,11 @@ coverage.to_next_chunk = function () { var begin = probe; // Find the end of this chunk. - var next_color = color; - while (next_color === color) { + var next_indicator = chunk_indicator; + while (next_indicator === chunk_indicator) { probe++; probe_line = c.line_elt(probe); - next_color = probe_line.css("background-color"); + next_indicator = c.chunk_indicator(probe_line); } c.set_sel(begin, probe); c.show_selection(); @@ -361,25 +356,25 @@ coverage.to_prev_chunk = function () { if (probe_line.length === 0) { return; } - var color = probe_line.css("background-color"); - while (probe > 0 && c.is_transparent(color)) { + var chunk_indicator = c.chunk_indicator(probe_line); + while (probe > 0 && !chunk_indicator) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { return; } - color = probe_line.css("background-color"); + chunk_indicator = c.chunk_indicator(probe_line); } // There's a prev chunk, `probe` points to its last line. var end = probe+1; // Find the beginning of this chunk. - var prev_color = color; - while (prev_color === color) { + var prev_indicator = chunk_indicator; + while (prev_indicator === chunk_indicator) { probe--; probe_line = c.line_elt(probe); - prev_color = probe_line.css("background-color"); + prev_indicator = c.chunk_indicator(probe_line); } c.set_sel(probe+1, end); c.show_selection(); @@ -451,29 +446,29 @@ coverage.select_line_or_chunk = function (lineno) { if (probe_line.length === 0) { return; } - var the_color = probe_line.css("background-color"); - if (!c.is_transparent(the_color)) { + var the_indicator = c.chunk_indicator(probe_line); + if (the_indicator) { // The line is in a highlighted chunk. // Search backward for the first line. var probe = lineno; - var color = the_color; - while (probe > 0 && color === the_color) { + var indicator = the_indicator; + while (probe > 0 && indicator === the_indicator) { probe--; probe_line = c.line_elt(probe); if (probe_line.length === 0) { break; } - color = probe_line.css("background-color"); + indicator = c.chunk_indicator(probe_line); } var begin = probe + 1; // Search forward for the last line. probe = lineno; - color = the_color; - while (color === the_color) { + indicator = the_indicator; + while (indicator === the_indicator) { probe++; probe_line = c.line_elt(probe); - color = probe_line.css("background-color"); + indicator = c.chunk_indicator(probe_line); } coverage.set_sel(begin, probe); @@ -487,7 +482,7 @@ coverage.show_selection = function () { var c = coverage; // Highlight the lines in the chunk - c.code_container().find(".highlight").removeClass("highlight"); + $(".linenos .highlight").removeClass("highlight"); for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { c.num_elt(probe).addClass("highlight"); } @@ -517,21 +512,21 @@ coverage.finish_scrolling = function () { coverage.init_scroll_markers = function () { var c = coverage; // Init some variables - c.lines_len = $('td.text p').length; + c.lines_len = $('#source p').length; c.body_h = $('body').height(); c.header_h = $('div#header').height(); - c.missed_lines = $('td.text p.mis, td.text p.par'); // Build html - c.resize_scroll_markers(); + c.build_scroll_markers(); }; -coverage.resize_scroll_markers = function () { +coverage.build_scroll_markers = function () { var c = coverage, min_line_height = 3, max_line_height = 10, visible_window_h = $(window).height(); + c.lines_to_mark = $('#source').find('p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par'); $('#scroll_marker').remove(); // Don't build markers if the window has no scroll bar. if (c.body_h <= visible_window_h) { @@ -555,11 +550,16 @@ coverage.resize_scroll_markers = function () { var previous_line = -99, last_mark, - last_top; + last_top, + offsets = {}; - c.missed_lines.each(function () { - var line_top = Math.round($(this).offset().top * marker_scale), - id_name = $(this).attr('id'), + // Calculate line offsets outside loop to prevent relayouts + c.lines_to_mark.each(function() { + offsets[this.id] = $(this).offset().top; + }); + c.lines_to_mark.each(function () { + var id_name = $(this).attr('id'), + line_top = Math.round(offsets[id_name] * marker_scale), line_number = parseInt(id_name.substring(1, id_name.length)); if (line_number === previous_line + 1) { diff --git a/doc/sample_html/index.html b/doc/sample_html/index.html index 777e73e8..9d483d3a 100644 --- a/doc/sample_html/index.html +++ b/doc/sample_html/index.html @@ -1,13 +1,9 @@ - - - Coverage report - @@ -18,21 +14,17 @@ - -
Hide keyboard shortcuts

Hot-keys on this page

@@ -42,171 +34,131 @@ s m x - b p - c   change column sorting

-
- - - - - - - - - - - - + + + + + + - - - - - - - - - + + - + - - - + - - - - - - - - - + + + + + + - - + + - - - - - + + - - - + + - - - - - + + + - - + + - - - - + - + - - - - + - + - - - - - - + + + -
Module statements missing excludedbranches partialcoverage
Total135214132361098.49%151490172783439.90%
cogapp/__init__.py 2 0 00 0100.00%
cogapp/__main__.py 3 3 00 00.00%
cogapp/backward.py198226 04 2157.14%69.23%
cogapp/cogapp.py42734176498.84%48521512002849.34%
cogapp/makefiles.py282720 0314392.86%017.07%
cogapp/test_cogapp.py7040790549 66199.86%20030.00%
cogapp/test_makefiles.py557153 006 0100.00%23.38%
cogapp/test_whiteutils.py 6950 000 0100.00%27.54%
cogapp/whiteutils.py 455 0032198.70%34488.61%
-

No items found using the specified filter.

- - diff --git a/doc/sample_html/status.json b/doc/sample_html/status.json index 6fd39e55..3b9717bf 100644 --- a/doc/sample_html/status.json +++ b/doc/sample_html/status.json @@ -1 +1 @@ -{"files":{"cogapp_test_whiteutils_py":{"index":{"relative_filename":"cogapp/test_whiteutils.py","html_filename":"cogapp_test_whiteutils_py.html","nums":[1,69,0,0,0,0,0]},"hash":"e00fa13d9d6f419ca35e732ea83c17fb"},"cogapp_test_makefiles_py":{"index":{"relative_filename":"cogapp/test_makefiles.py","html_filename":"cogapp_test_makefiles_py.html","nums":[1,55,0,0,6,0,0]},"hash":"db9f8cbf81e744216a3602f494704e64"},"cogapp_cogapp_py":{"index":{"relative_filename":"cogapp/cogapp.py","html_filename":"cogapp_cogapp_py.html","nums":[1,427,4,3,176,4,4]},"hash":"4755e7ad9cc02487511c151e968808d8"},"cogapp___init___py":{"index":{"relative_filename":"cogapp/__init__.py","html_filename":"cogapp___init___py.html","nums":[1,2,0,0,0,0,0]},"hash":"589b4cc38603d62593ba92f20950eb8a"},"cogapp_backward_py":{"index":{"relative_filename":"cogapp/backward.py","html_filename":"cogapp_backward_py.html","nums":[1,19,0,8,2,1,1]},"hash":"5b76f23e07605fde0795af44bf5eeedf"},"cogapp_test_cogapp_py":{"index":{"relative_filename":"cogapp/test_cogapp.py","html_filename":"cogapp_test_cogapp_py.html","nums":[1,704,6,0,6,1,1]},"hash":"f8c759a0caca2f8e76270d8f1720e637"},"cogapp_makefiles_py":{"index":{"relative_filename":"cogapp/makefiles.py","html_filename":"cogapp_makefiles_py.html","nums":[1,28,3,0,14,3,3]},"hash":"1703ddbb839a9738578dc9bc8deab9b5"},"cogapp_whiteutils_py":{"index":{"relative_filename":"cogapp/whiteutils.py","html_filename":"cogapp_whiteutils_py.html","nums":[1,45,0,0,32,1,1]},"hash":"f0acf5699b528da74f67913134e4e21d"},"cogapp___main___py":{"index":{"relative_filename":"cogapp/__main__.py","html_filename":"cogapp___main___py.html","nums":[1,3,0,3,0,0,0]},"hash":"c846304fff9f9b5f7510a86b60c3c3c6"}},"version":"4.5","settings":"2bc9291143291213aaed835381c1a3fc","format":1} \ No newline at end of file +{"format":2,"version":"5.0","globals":"e1846004c42776ae010bf8e34a91519e","files":{"cogapp___init___py":{"hash":"394223dfdd89e833f305580aa57a8249","index":{"nums":[1,2,0,0,0,0,0],"html_filename":"cogapp___init___py.html","relative_filename":"cogapp/__init__.py"}},"cogapp___main___py":{"hash":"2cec3551dfd9a5818a6550318658ccd4","index":{"nums":[1,3,0,3,0,0,0],"html_filename":"cogapp___main___py.html","relative_filename":"cogapp/__main__.py"}},"cogapp_backward_py":{"hash":"a9fac271913998141885e738e94e4366","index":{"nums":[1,22,0,6,4,2,2],"html_filename":"cogapp_backward_py.html","relative_filename":"cogapp/backward.py"}},"cogapp_cogapp_py":{"hash":"fe4ad7ebb464cbf9343ce967237d49af","index":{"nums":[1,485,1,215,200,28,132],"html_filename":"cogapp_cogapp_py.html","relative_filename":"cogapp/cogapp.py"}},"cogapp_makefiles_py":{"hash":"551431f9308a0836e0a365e64ff7c333","index":{"nums":[1,27,0,20,14,0,14],"html_filename":"cogapp_makefiles_py.html","relative_filename":"cogapp/makefiles.py"}},"cogapp_test_cogapp_py":{"hash":"cb0eb6015bcf540023c227a30835c5d6","index":{"nums":[1,790,6,549,20,0,18],"html_filename":"cogapp_test_cogapp_py.html","relative_filename":"cogapp/test_cogapp.py"}},"cogapp_test_makefiles_py":{"hash":"0447c2f176e1ea621505e8452b9d5038","index":{"nums":[1,71,0,53,6,0,6],"html_filename":"cogapp_test_makefiles_py.html","relative_filename":"cogapp/test_makefiles.py"}},"cogapp_test_whiteutils_py":{"hash":"5af4aaae2ad4317a361eb40dd79d4ea0","index":{"nums":[1,69,0,50,0,0,0],"html_filename":"cogapp_test_whiteutils_py.html","relative_filename":"cogapp/test_whiteutils.py"}},"cogapp_whiteutils_py":{"hash":"4068aefb16d502186c6baa27cc775d4a","index":{"nums":[1,45,0,5,34,4,4],"html_filename":"cogapp_whiteutils_py.html","relative_filename":"cogapp/whiteutils.py"}}}} \ No newline at end of file diff --git a/doc/sample_html/style.css b/doc/sample_html/style.css index d6b29524..e8ff5765 100644 --- a/doc/sample_html/style.css +++ b/doc/sample_html/style.css @@ -1,375 +1,124 @@ +@charset "UTF-8"; /* Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 */ /* For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt */ +/* Don't edit this .css file. Edit the .scss file instead! */ +html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } -/* CSS styles for coverage.py. */ +body { font-family: georgia, serif; font-size: 1em; } -/* Page-wide styles */ -html, body, h1, h2, h3, p, table, td, th { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; - } +html > body { font-size: 16px; } -/* Set baseline grid to 16 pt. */ -body { - font-family: georgia, serif; - font-size: 1em; - } - -html>body { - font-size: 16px; - } - -/* Set base font size to 12/16 */ -p { - font-size: .75em; /* 12/16 */ - line-height: 1.33333333em; /* 16/12 */ - } - -table { - border-collapse: collapse; - } -td { - vertical-align: top; -} -table tr.hidden { - display: none !important; - } - -p#no_rows { - display: none; - font-size: 1.2em; - } - -a.nav { - text-decoration: none; - color: inherit; - } -a.nav:hover { - text-decoration: underline; - color: inherit; - } - -/* Page structure */ -#header { - background: #f8f8f8; - width: 100%; - border-bottom: 1px solid #eee; - } - -#source { - padding: 1em; - font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; - } - -.indexfile #footer { - margin: 1em 3em; - } - -.pyfile #footer { - margin: 1em 1em; - } - -#footer .content { - padding: 0; - font-size: 85%; - font-family: verdana, sans-serif; - color: #666666; - font-style: italic; - } - -#index { - margin: 1em 0 0 3em; - } - -/* Header styles */ -#header .content { - padding: 1em 3em; - } - -h1 { - font-size: 1.25em; - display: inline-block; -} - -#filter_container { - display: inline-block; - float: right; - margin: 0 2em 0 0; -} -#filter_container input { - width: 10em; -} - -h2.stats { - margin-top: .5em; - font-size: 1em; -} -.stats span { - border: 1px solid; - padding: .1em .25em; - margin: 0 .1em; - cursor: pointer; - border-color: #999 #ccc #ccc #999; -} -.stats span.hide_run, .stats span.hide_exc, -.stats span.hide_mis, .stats span.hide_par, -.stats span.par.hide_run.hide_par { - border-color: #ccc #999 #999 #ccc; -} -.stats span.par.hide_run { - border-color: #999 #ccc #ccc #999; -} - -.stats span.run { - background: #ddffdd; -} -.stats span.exc { - background: #eeeeee; -} -.stats span.mis { - background: #ffdddd; -} -.stats span.hide_run { - background: #eeffee; -} -.stats span.hide_exc { - background: #f5f5f5; -} -.stats span.hide_mis { - background: #ffeeee; -} -.stats span.par { - background: #ffffaa; -} -.stats span.hide_par { - background: #ffffcc; -} - -/* Help panel */ -#keyboard_icon { - float: right; - margin: 5px; - cursor: pointer; -} - -.help_panel { - position: absolute; - background: #ffffcc; - padding: .5em; - border: 1px solid #883; - display: none; -} - -.indexfile .help_panel { - width: 20em; height: 4em; -} - -.pyfile .help_panel { - width: 16em; height: 8em; -} - -.help_panel .legend { - font-style: italic; - margin-bottom: 1em; -} - -#panel_icon { - float: right; - cursor: pointer; -} - -.keyhelp { - margin: .75em; -} - -.keyhelp .key { - border: 1px solid black; - border-color: #888 #333 #333 #888; - padding: .1em .35em; - font-family: monospace; - font-weight: bold; - background: #eee; -} - -/* Source file styles */ -.linenos p { - text-align: right; - margin: 0; - padding: 0 .5em; - color: #999999; - font-family: verdana, sans-serif; - font-size: .625em; /* 10/16 */ - line-height: 1.6em; /* 16/10 */ - } -.linenos p.highlight { - background: #ffdd00; - } -.linenos p a { - text-decoration: none; - color: #999999; - } -.linenos p a:hover { - text-decoration: underline; - color: #999999; - } - -td.text { - width: 100%; - } -.text p { - margin: 0; - padding: 0 0 0 .5em; - border-left: 2px solid #ffffff; - white-space: pre; - position: relative; - } - -.text p.mis { - background: #ffdddd; - border-left: 2px solid #ff0000; - } -.text p.run, .text p.run.hide_par { - background: #ddffdd; - border-left: 2px solid #00ff00; - } -.text p.exc { - background: #eeeeee; - border-left: 2px solid #808080; - } -.text p.par, .text p.par.hide_run { - background: #ffffaa; - border-left: 2px solid #eeee99; - } -.text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, -.text p.hide_run.hide_par { - background: inherit; - } - -.text span.annotate { - font-family: georgia; - color: #666; - float: right; - padding-right: .5em; - } -.text p.hide_par span.annotate { - display: none; - } -.text span.annotate.long { - display: none; - } -.text p:hover span.annotate.long { - display: block; - max-width: 50%; - white-space: normal; - float: right; - position: absolute; - top: 1.75em; - right: 1em; - width: 30em; - height: auto; - color: #333; - background: #ffffcc; - border: 1px solid #888; - padding: .25em .5em; - z-index: 999; - border-radius: .2em; - box-shadow: #cccccc .2em .2em .2em; - } - -/* Syntax coloring */ -.text .com { - color: green; - font-style: italic; - line-height: 1px; - } -.text .key { - font-weight: bold; - line-height: 1px; - } -.text .str { - color: #000080; - } - -/* index styles */ -#index td, #index th { - text-align: right; - width: 5em; - padding: .25em .5em; - border-bottom: 1px solid #eee; - } -#index th { - font-style: italic; - color: #333; - border-bottom: 1px solid #ccc; - cursor: pointer; - } -#index th:hover { - background: #eee; - border-bottom: 1px solid #999; - } -#index td.left, #index th.left { - padding-left: 0; - } -#index td.right, #index th.right { - padding-right: 0; - } -#index th.headerSortDown, #index th.headerSortUp { - border-bottom: 1px solid #000; - white-space: nowrap; - background: #eee; - } -#index th.headerSortDown:after { - content: " ↓"; -} -#index th.headerSortUp:after { - content: " ↑"; -} -#index td.name, #index th.name { - text-align: left; - width: auto; - } -#index td.name a { - text-decoration: none; - color: #000; - } -#index tr.total, -#index tr.total_dynamic { - } -#index tr.total td, -#index tr.total_dynamic td { - font-weight: bold; - border-top: 1px solid #ccc; - border-bottom: none; - } -#index tr.file:hover { - background: #eeeeee; - } -#index tr.file:hover td.name { - text-decoration: underline; - color: #000; - } - -/* scroll marker styles */ -#scroll_marker { - position: fixed; - right: 0; - top: 0; - width: 16px; - height: 100%; - background: white; - border-left: 1px solid #eee; - } - -#scroll_marker .marker { - background: #eedddd; - position: absolute; - min-height: 3px; - width: 100%; - } +p { font-size: .75em; line-height: 1.33333333em; } + +table { border-collapse: collapse; } + +td { vertical-align: top; } + +table tr.hidden { display: none !important; } + +p#no_rows { display: none; font-size: 1.2em; } + +a.nav { text-decoration: none; color: inherit; } +a.nav:hover { text-decoration: underline; color: inherit; } + +#header { background: #f8f8f8; width: 100%; border-bottom: 1px solid #eee; } + +.indexfile #footer { margin: 1em 3em; } + +.pyfile #footer { margin: 1em 1em; } + +#footer .content { padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; font-style: italic; } + +#index { margin: 1em 0 0 3em; } + +#header .content { padding: 1em 3rem; } + +h1 { font-size: 1.25em; display: inline-block; } + +#filter_container { display: inline-block; float: right; margin: 0 2em 0 0; } +#filter_container input { width: 10em; } + +h2.stats { margin-top: .5em; font-size: 1em; } + +.stats span { border: 1px solid; border-radius: .1em; padding: .1em .5em; margin: 0 .1em; cursor: pointer; border-color: #ccc #999 #999 #ccc; } +.stats span.run { background: #eeffee; } +.stats span.run.show_run { border-color: #999 #ccc #ccc #999; background: #ddffdd; } +.stats span.mis { background: #ffeeee; } +.stats span.mis.show_mis { border-color: #999 #ccc #ccc #999; background: #ffdddd; } +.stats span.exc { background: #f7f7f7; } +.stats span.exc.show_exc { border-color: #999 #ccc #ccc #999; background: #eeeeee; } +.stats span.par { background: #ffffd5; } +.stats span.par.show_par { border-color: #999 #ccc #ccc #999; background: #ffffaa; } + +#source p .annotate.long, .help_panel { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; box-shadow: #cccccc .2em .2em .2em; color: #333; padding: .25em .5em; } + +#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; } + +#keyboard_icon { float: right; margin: 5px; cursor: pointer; } + +.help_panel { padding: .5em; border: 1px solid #883; } +.help_panel .legend { font-style: italic; margin-bottom: 1em; } +.indexfile .help_panel { width: 20em; height: 4em; } +.pyfile .help_panel { width: 16em; height: 8em; } + +#panel_icon { float: right; cursor: pointer; } + +.keyhelp { margin: .75em; } +.keyhelp .key { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: monospace; font-weight: bold; background: #eee; } + +#source { padding: 1em 0 1em 3rem; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; } +#source p { position: relative; white-space: pre; } +#source p * { box-sizing: border-box; } +#source p .n { float: left; text-align: right; width: 3rem; box-sizing: border-box; margin-left: -3rem; padding-right: 1em; color: #999999; font-family: verdana, sans-serif; } +#source p .n a { text-decoration: none; color: #999999; font-size: .8333em; line-height: 1em; } +#source p .n a:hover { text-decoration: underline; color: #999999; } +#source p.highlight .n { background: #ffdd00; } +#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid white; } +#source p .t:hover { background: #f2f2f2; } +#source p .t:hover ~ .r .annotate.long { display: block; } +#source p .t .com { color: green; font-style: italic; line-height: 1px; } +#source p .t .key { font-weight: bold; line-height: 1px; } +#source p .t .str { color: #000080; } +#source p.mis .t { border-left: 0.2em solid #ff0000; } +#source p.mis.show_mis .t { background: #ffdddd; } +#source p.mis.show_mis .t:hover { background: #f2d2d2; } +#source p.run .t { border-left: 0.2em solid #00ff00; } +#source p.run.show_run .t { background: #ddffdd; } +#source p.run.show_run .t:hover { background: #d2f2d2; } +#source p.exc .t { border-left: 0.2em solid #808080; } +#source p.exc.show_exc .t { background: #eeeeee; } +#source p.exc.show_exc .t:hover { background: #e2e2e2; } +#source p.par .t { border-left: 0.2em solid #eeee99; } +#source p.par.show_par .t { background: #ffffaa; } +#source p.par.show_par .t:hover { background: #f2f2a2; } +#source p .r { position: absolute; top: 0; right: 2.5em; font-family: verdana, sans-serif; } +#source p .annotate { font-family: georgia; color: #666; padding-right: .5em; } +#source p .annotate.short:hover ~ .long { display: block; } +#source p .annotate.long { width: 30em; right: 2.5em; } +#source p input { display: none; } +#source p input ~ .r label.ctx { cursor: pointer; border-radius: .25em; } +#source p input ~ .r label.ctx::before { content: "▶ "; } +#source p input ~ .r label.ctx:hover { background: #d5f7ff; color: #666; } +#source p input:checked ~ .r label.ctx { background: #aaeeff; color: #666; border-radius: .75em .75em 0 0; padding: 0 .5em; margin: -.25em 0; } +#source p input:checked ~ .r label.ctx::before { content: "▼ "; } +#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; } +#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; } +#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: verdana, sans-serif; white-space: nowrap; background: #aaeeff; border-radius: .25em; margin-right: 1.75em; } +#source p .ctxs span { display: block; text-align: right; } + +#index td, #index th { text-align: right; width: 5em; padding: .25em .5em; border-bottom: 1px solid #eee; } +#index td.left, #index th.left { padding-left: 0; } +#index td.right, #index th.right { padding-right: 0; } +#index td.name, #index th.name { text-align: left; width: auto; } +#index th { font-style: italic; color: #333; border-bottom: 1px solid #ccc; cursor: pointer; } +#index th:hover { background: #eee; border-bottom: 1px solid #999; } +#index th.headerSortDown, #index th.headerSortUp { border-bottom: 1px solid #000; white-space: nowrap; background: #eee; } +#index th.headerSortDown:after { content: " ↓"; } +#index th.headerSortUp:after { content: " ↑"; } +#index td.name a { text-decoration: none; color: #000; } +#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } +#index tr.file:hover { background: #eeeeee; } +#index tr.file:hover td.name { text-decoration: underline; color: #000; } + +#scroll_marker { position: fixed; right: 0; top: 0; width: 16px; height: 100%; background: white; border-left: 1px solid #eee; will-change: transform; } +#scroll_marker .marker { background: #ddd; position: absolute; min-height: 3px; width: 100%; } -- cgit v1.2.1