From a201ff9a72ed8cccedf27ef712bae00e4532b48c Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 4 Oct 2009 21:34:54 -0400 Subject: Updated sample html report. --- doc/sample_html/_ned_py_path.html | 1508 ++++++++++++ doc/sample_html/cogapp_cogapp.html | 1418 +++++------ doc/sample_html/cogapp_makefiles.html | 128 +- doc/sample_html/cogapp_test_cogapp.html | 3920 +++++++++++++++---------------- doc/sample_html/cogapp_whiteutils.html | 126 +- doc/sample_html/index.html | 18 +- doc/sample_html/style.css | 21 +- 7 files changed, 4337 insertions(+), 2802 deletions(-) create mode 100644 doc/sample_html/_ned_py_path.html (limited to 'doc/sample_html') diff --git a/doc/sample_html/_ned_py_path.html b/doc/sample_html/_ned_py_path.html new file mode 100644 index 0000000..78637ee --- /dev/null +++ b/doc/sample_html/_ned_py_path.html @@ -0,0 +1,1508 @@ + + + +Coverage for c:\ned\py\path + + + + + + + +
+ + + + + +
+

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

+ +
+

""" path.py - An object representing a path to a file or directory. 

+

 

+

Example: 

+

 

+

from path import path 

+

d = path('/home/guido/bin') 

+

for f in d.files('*.py'): 

+

    f.chmod(0755) 

+

 

+

This module requires Python 2.2 or later. 

+

 

+

 

+

URL:     http://www.jorendorff.com/articles/python/path 

+

Author:  Jason Orendorff <jason@jorendorff.com> (and others - see the url!) 

+

Date:    29 Feb 2004 

+

""" 

+

 

+

 

+

# TODO 

+

#   - Bug in write_text().  It doesn't support Universal newline mode. 

+

#   - Better error message in listdir() when self isn't a 

+

#     directory. (On Windows, the error message really sucks.) 

+

#   - Make sure everything has a good docstring. 

+

#   - Add methods for regex find and replace. 

+

#   - guess_content_type() method? 

+

#   - Perhaps support arguments to touch(). 

+

#   - Could add split() and join() methods that generate warnings. 

+

#   - Note:  __add__() technically has a bug, I think, where 

+

#     it doesn't play nice with other types that implement 

+

#     __radd__().  Test this. 

+

 

+

from __future__ import generators 

+

 

+

import sys, os, fnmatch, glob, shutil, codecs 

+

 

+

__version__ = '2.0.2' 

+

__all__ = ['path'] 

+

 

+

# Pre-2.3 support.  Are unicode filenames supported? 

+

_base = str 

+

try: 

+

    if os.path.supports_unicode_filenames: 

+

        _base = unicode 

+

except AttributeError: 

+

    pass 

+

 

+

# Pre-2.3 workaround for basestring. 

+

try: 

+

    basestring 

+

except NameError: 

+

    basestring = (str, unicode) 

+

 

+

# Universal newline support 

+

_textmode = 'r' 

+

if hasattr(file, 'newlines'): 

+

    _textmode = 'U' 

+

 

+

 

+

class path(_base): 

+

    """ Represents a filesystem path. 

+

 

+

    For documentation on individual methods, consult their 

+

    counterparts in os.path. 

+

    """ 

+

 

+

    # --- Special Python methods. 

+

 

+

    def __repr__(self): 

+

        return 'path(%s)' % _base.__repr__(self) 

+

 

+

    # Adding a path and a string yields a path. 

+

    def __add__(self, more): 

+

        return path(_base(self) + more) 

+

 

+

    def __radd__(self, other): 

+

        return path(other + _base(self)) 

+

 

+

    # The / operator joins paths. 

+

    def __div__(self, rel): 

+

        """ fp.__div__(rel) == fp / rel == fp.joinpath(rel) 

+

 

+

        Join two path components, adding a separator character if 

+

        needed. 

+

        """ 

+

        return path(os.path.join(self, rel)) 

+

 

+

    # Make the / operator work even when true division is enabled. 

+

    __truediv__ = __div__ 

+

 

+

    def getcwd(): 

+

        """ Return the current working directory as a path object. """ 

+

        return path(os.getcwd()) 

+

    getcwd = staticmethod(getcwd) 

+

 

+

 

+

    # --- Operations on path strings. 

+

 

+

    def abspath(self):       return path(os.path.abspath(self)) 

+

    def normcase(self):      return path(os.path.normcase(self)) 

+

    def normpath(self):      return path(os.path.normpath(self)) 

+

    def realpath(self):      return path(os.path.realpath(self)) 

+

    def expanduser(self):    return path(os.path.expanduser(self)) 

+

    def expandvars(self):    return path(os.path.expandvars(self)) 

+

    def dirname(self):       return path(os.path.dirname(self)) 

+

    basename = os.path.basename 

+

 

+

    def expand(self): 

+

        """ Clean up a filename by calling expandvars(), 

+

        expanduser(), and normpath() on it. 

+

 

+

        This is commonly everything needed to clean up a filename 

+

        read from a configuration file, for example. 

+

        """ 

+

        return self.expandvars().expanduser().normpath() 

+

 

+

    def _get_namebase(self): 

+

        base, ext = os.path.splitext(self.name) 

+

        return base 

+

 

+

    def _get_ext(self): 

+

        f, ext = os.path.splitext(_base(self)) 

+

        return ext 

+

 

+

    def _get_drive(self): 

+

        drive, r = os.path.splitdrive(self) 

+

        return path(drive) 

+

 

+

    parent = property( 

+

        dirname, None, None, 

+

        """ This path's parent directory, as a new path object. 

+

 

+

        For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib') 

+

        """) 

+

 

+

    name = property( 

+

        basename, None, None, 

+

        """ The name of this file or directory without the full path. 

+

 

+

        For example, path('/usr/local/lib/libpython.so').name == 'libpython.so' 

+

        """) 

+

 

+

    namebase = property( 

+

        _get_namebase, None, None, 

+

        """ The same as path.name, but with one file extension stripped off. 

+

 

+

        For example, path('/home/guido/python.tar.gz').name     == 'python.tar.gz', 

+

        but          path('/home/guido/python.tar.gz').namebase == 'python.tar' 

+

        """) 

+

 

+

    ext = property( 

+

        _get_ext, None, None, 

+

        """ The file extension, for example '.py'. """) 

+

 

+

    drive = property( 

+

        _get_drive, None, None, 

+

        """ The drive specifier, for example 'C:'. 

+

        This is always empty on systems that don't use drive specifiers. 

+

        """) 

+

 

+

    def splitpath(self): 

+

        """ p.splitpath() -> Return (p.parent, p.name). """ 

+

        parent, child = os.path.split(self) 

+

        return path(parent), child 

+

 

+

    def splitdrive(self): 

+

        """ p.splitdrive() -> Return (p.drive, <the rest of p>). 

+

 

+

        Split the drive specifier from this path.  If there is 

+

        no drive specifier, p.drive is empty, so the return value 

+

        is simply (path(''), p).  This is always the case on Unix. 

+

        """ 

+

        drive, rel = os.path.splitdrive(self) 

+

        return path(drive), rel 

+

 

+

    def splitext(self): 

+

        """ p.splitext() -> Return (p.stripext(), p.ext). 

+

 

+

        Split the filename extension from this path and return 

+

        the two parts.  Either part may be empty. 

+

 

+

        The extension is everything from '.' to the end of the 

+

        last path segment.  This has the property that if 

+

        (a, b) == p.splitext(), then a + b == p. 

+

        """ 

+

        # Cast to plain string using _base because Python 2.2 

+

        # implementations of os.path.splitext use "for c in path:..." 

+

        # which means something different when applied to a path 

+

        # object. 

+

        filename, ext = os.path.splitext(_base(self)) 

+

        return path(filename), ext 

+

 

+

    def stripext(self): 

+

        """ p.stripext() -> Remove one file extension from the path. 

+

 

+

        For example, path('/home/guido/python.tar.gz').stripext() 

+

        returns path('/home/guido/python.tar'). 

+

        """ 

+

        return self.splitext()[0] 

+

 

+

    if hasattr(os.path, 'splitunc'): 

+

        def splitunc(self): 

+

            unc, rest = os.path.splitunc(self) 

+

            return path(unc), rest 

+

 

+

        def _get_uncshare(self): 

+

            unc, r = os.path.splitunc(self) 

+

            return path(unc) 

+

 

+

        uncshare = property( 

+

            _get_uncshare, None, None, 

+

            """ The UNC mount point for this path. 

+

            This is empty for paths on local drives. """) 

+

 

+

    def joinpath(self, *args): 

+

        """ Join two or more path components, adding a separator 

+

        character (os.sep) if needed.  Returns a new path 

+

        object. 

+

        """ 

+

        return path(os.path.join(self, *args)) 

+

 

+

    def splitall(self): 

+

        """ Return a list of the path components in this path. 

+

 

+

        The first item in the list will be a path.  Its value will be 

+

        either os.curdir, os.pardir, empty, or the root directory of 

+

        this path (for example, '/' or 'C:\\').  The other items in 

+

        the list will be strings. 

+

 

+

        path.path.joinpath(*result) will yield the original path. 

+

        """ 

+

        parts = [] 

+

        loc = self 

+

        while loc != os.curdir and loc != os.pardir: 

+

            prev = loc 

+

            loc, child = prev.splitpath() 

+

            if loc == prev: 

+

                break 

+

            parts.append(child) 

+

        parts.append(loc) 

+

        parts.reverse() 

+

        return parts 

+

 

+

    def relpath(self): 

+

        """ Return this path as a relative path, 

+

        based from the current working directory. 

+

        """ 

+

        cwd = path(os.getcwd()) 

+

        return cwd.relpathto(self) 

+

 

+

    def relpathto(self, dest): 

+

        """ Return a relative path from self to dest. 

+

 

+

        If there is no relative path from self to dest, for example if 

+

        they reside on different drives in Windows, then this returns 

+

        dest.abspath(). 

+

        """ 

+

        origin = self.abspath() 

+

        dest = path(dest).abspath() 

+

 

+

        orig_list = origin.normcase().splitall() 

+

        # Don't normcase dest!  We want to preserve the case. 

+

        dest_list = dest.splitall() 

+

 

+

        if orig_list[0] != os.path.normcase(dest_list[0]): 

+

            # Can't get here from there. 

+

            return dest 

+

 

+

        # Find the location where the two paths start to differ. 

+

        i = 0 

+

        for start_seg, dest_seg in zip(orig_list, dest_list): 

+

            if start_seg != os.path.normcase(dest_seg): 

+

                break 

+

            i += 1 

+

 

+

        # Now i is the point where the two paths diverge. 

+

        # Need a certain number of "os.pardir"s to work up 

+

        # from the origin to the point of divergence. 

+

        segments = [os.pardir] * (len(orig_list) - i) 

+

        # Need to add the diverging part of dest_list. 

+

        segments += dest_list[i:] 

+

        if len(segments) == 0: 

+

            # If they happen to be identical, use os.curdir. 

+

            return path(os.curdir) 

+

        else: 

+

            return path(os.path.join(*segments)) 

+

 

+

 

+

    # --- Listing, searching, walking, and matching 

+

 

+

    def listdir(self, pattern=None): 

+

        """ D.listdir() -> List of items in this directory. 

+

 

+

        Use D.files() or D.dirs() instead if you want a listing 

+

        of just files or just subdirectories. 

+

 

+

        The elements of the list are path objects. 

+

 

+

        With the optional 'pattern' argument, this only lists 

+

        items whose names match the given pattern. 

+

        """ 

+

        names = os.listdir(self) 

+

        if pattern is not None: 

+

            names = fnmatch.filter(names, pattern) 

+

        return [self / child for child in names] 

+

 

+

    def dirs(self, pattern=None): 

+

        """ D.dirs() -> List of this directory's subdirectories. 

+

 

+

        The elements of the list are path objects. 

+

        This does not walk recursively into subdirectories 

+

        (but see path.walkdirs). 

+

 

+

        With the optional 'pattern' argument, this only lists 

+

        directories whose names match the given pattern.  For 

+

        example, d.dirs('build-*'). 

+

        """ 

+

        return [p for p in self.listdir(pattern) if p.isdir()] 

+

 

+

    def files(self, pattern=None): 

+

        """ D.files() -> List of the files in this directory. 

+

 

+

        The elements of the list are path objects. 

+

        This does not walk into subdirectories (see path.walkfiles). 

+

 

+

        With the optional 'pattern' argument, this only lists files 

+

        whose names match the given pattern.  For example, 

+

        d.files('*.pyc'). 

+

        """ 

+

 

+

        return [p for p in self.listdir(pattern) if p.isfile()] 

+

 

+

    def walk(self, pattern=None): 

+

        """ D.walk() -> iterator over files and subdirs, recursively. 

+

 

+

        The iterator yields path objects naming each child item of 

+

        this directory and its descendants.  This requires that 

+

        D.isdir(). 

+

 

+

        This performs a depth-first traversal of the directory tree. 

+

        Each directory is returned just before all its children. 

+

        """ 

+

        for child in self.listdir(): 

+

            if pattern is None or child.fnmatch(pattern): 

+

                yield child 

+

            if child.isdir(): 

+

                for item in child.walk(pattern): 

+

                    yield item 

+

 

+

    def walkdirs(self, pattern=None): 

+

        """ D.walkdirs() -> iterator over subdirs, recursively. 

+

 

+

        With the optional 'pattern' argument, this yields only 

+

        directories whose names match the given pattern.  For 

+

        example, mydir.walkdirs('*test') yields only directories 

+

        with names ending in 'test'. 

+

        """ 

+

        for child in self.dirs(): 

+

            if pattern is None or child.fnmatch(pattern): 

+

                yield child 

+

            for subsubdir in child.walkdirs(pattern): 

+

                yield subsubdir 

+

 

+

    def walkfiles(self, pattern=None): 

+

        """ D.walkfiles() -> iterator over files in D, recursively. 

+

 

+

        The optional argument, pattern, limits the results to files 

+

        with names that match the pattern.  For example, 

+

        mydir.walkfiles('*.tmp') yields only files with the .tmp 

+

        extension. 

+

        """ 

+

        for child in self.listdir(): 

+

            if child.isfile(): 

+

                if pattern is None or child.fnmatch(pattern): 

+

                    yield child 

+

            elif child.isdir(): 

+

                for f in child.walkfiles(pattern): 

+

                    yield f 

+

 

+

    def fnmatch(self, pattern): 

+

        """ Return True if self.name matches the given pattern. 

+

 

+

        pattern - A filename pattern with wildcards, 

+

            for example '*.py'. 

+

        """ 

+

        return fnmatch.fnmatch(self.name, pattern) 

+

 

+

    def glob(self, pattern): 

+

        """ Return a list of path objects that match the pattern. 

+

 

+

        pattern - a path relative to this directory, with wildcards. 

+

 

+

        For example, path('/users').glob('*/bin/*') returns a list 

+

        of all the files users have in their bin directories. 

+

        """ 

+

        return map(path, glob.glob(_base(self / pattern))) 

+

 

+

 

+

    # --- Reading or writing an entire file at once. 

+

 

+

    def open(self, mode='r'): 

+

        """ Open this file.  Return a file object. """ 

+

        return file(self, mode) 

+

 

+

    def bytes(self): 

+

        """ Open this file, read all bytes, return them as a string. """ 

+

        f = self.open('rb') 

+

        try: 

+

            return f.read() 

+

        finally: 

+

            f.close() 

+

 

+

    def write_bytes(self, bytes, append=False): 

+

        """ Open this file and write the given bytes to it. 

+

 

+

        Default behavior is to overwrite any existing file. 

+

        Call this with write_bytes(bytes, append=True) to append instead. 

+

        """ 

+

        if append: 

+

            mode = 'ab' 

+

        else: 

+

            mode = 'wb' 

+

        f = self.open(mode) 

+

        try: 

+

            f.write(bytes) 

+

        finally: 

+

            f.close() 

+

 

+

    def text(self, encoding=None, errors='strict'): 

+

        """ Open this file, read it in, return the content as a string. 

+

 

+

        This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r' 

+

        are automatically translated to '\n'. 

+

 

+

        Optional arguments: 

+

 

+

        encoding - The Unicode encoding (or character set) of 

+

            the file.  If present, the content of the file is 

+

            decoded and returned as a unicode object; otherwise 

+

            it is returned as an 8-bit str. 

+

        errors - How to handle Unicode errors; see help(str.decode) 

+

            for the options.  Default is 'strict'. 

+

        """ 

+

        if encoding is None: 

+

            # 8-bit 

+

            f = self.open(_textmode) 

+

            try: 

+

                return f.read() 

+

            finally: 

+

                f.close() 

+

        else: 

+

            # Unicode 

+

            f = codecs.open(self, 'r', encoding, errors) 

+

            # (Note - Can't use 'U' mode here, since codecs.open 

+

            # doesn't support 'U' mode, even in Python 2.3.) 

+

            try: 

+

                t = f.read() 

+

            finally: 

+

                f.close() 

+

            return t.replace(u'\r\n', u'\n').replace(u'\r', u'\n') 

+

 

+

    def write_text(self, text, encoding=None, errors='strict', append=False): 

+

        """ Write the given text to this file. 

+

 

+

        The default behavior is to overwrite any existing file; 

+

        to append instead, use the 'append=True' keyword argument. 

+

 

+

        There are two differences between path.write_text() and 

+

        path.write_bytes(): Unicode handling and newline handling. 

+

 

+

        --- Unicode 

+

 

+

        If 'text' isn't Unicode, this essentially just does 

+

        open(self, 'w').write(text).  The 'encoding' and 'errors' 

+

        arguments are ignored. 

+

 

+

        If 'text' is Unicode, it is first converted to bytes using the 

+

        specified 'encoding' (or the default encoding if 'encoding' 

+

        isn't specified).  The 'errors' argument applies only to this 

+

        conversion. 

+

 

+

        --- Newlines 

+

 

+

        write_text() converts from programmer-friendly newlines 

+

        (always '\n') to platform-specific newlines (see os.linesep; 

+

        on Windows, for example, the end-of-line marker is '\r\n'). 

+

        This applies to Unicode text the same as to 8-bit text. 

+

 

+

        Because of this conversion, the text should only contain plain 

+

        newlines ('\n'), just like the return value of path.text(). 

+

        If the text contains the characters '\r\n', it may be written 

+

        as '\r\r\n' or '\r\r' depending on your platform.  (This is 

+

        exactly the same as when you open a file for writing with 

+

        fopen(filename, "w") in C or file(filename, 'w') in Python.) 

+

        """ 

+

        if isinstance(text, unicode): 

+

            text = text.replace(u'\n', os.linesep) 

+

            if encoding is None: 

+

                encoding = sys.getdefaultencoding() 

+

            bytes = text.encode(encoding, errors) 

+

            self.write_bytes(bytes, append) 

+

        else: 

+

            if append: 

+

                mode = 'a' 

+

            else: 

+

                mode = 'w' 

+

            f = self.open(mode) 

+

            try: 

+

                f.write(text) 

+

            finally: 

+

                f.close() 

+

 

+

    def lines(self, encoding=None, errors='strict', retain=True): 

+

        """ Open this file, read all lines, return them in a list. 

+

 

+

        Optional arguments: 

+

            encoding - The Unicode encoding (or character set) of 

+

                the file.  The default is None, meaning the content 

+

                of the file is read as 8-bit characters and returned 

+

                as a list of (non-Unicode) str objects. 

+

            errors - How to handle Unicode errors; see help(str.decode) 

+

                for the options.  Default is 'strict' 

+

            retain - If true, retain newline characters; but all newline 

+

                character combinations ('\r', '\n', '\r\n') are 

+

                translated to '\n'.  If false, newline characters are 

+

                stripped off.  Default is True. 

+

 

+

        This uses 'U' mode in Python 2.3 and later. 

+

        """ 

+

        if encoding is None and retain: 

+

            f = self.open(_textmode) 

+

            try: 

+

                return f.readlines() 

+

            finally: 

+

                f.close() 

+

        else: 

+

            return self.text(encoding, errors).splitlines(retain) 

+

 

+

    def write_lines(self, lines, encoding=None, errors='strict', 

+

                    linesep=os.linesep): 

+

        """ Overwrite this file with the given lines of text. 

+

 

+

        lines - A list of strings. 

+

        encoding - A Unicode encoding to use.  This applies only if 

+

            'lines' contains any Unicode strings. 

+

        errors - How to handle errors in Unicode encoding.  This 

+

            also applies only to Unicode strings. 

+

        linesep - A character sequence that will be added at the 

+

            end of every line that doesn't already have it. 

+

        """ 

+

        f = self.open('wb') 

+

        try: 

+

            for line in lines: 

+

                if not line.endswith(linesep): 

+

                    line += linesep 

+

                if isinstance(line, unicode): 

+

                    if encoding is None: 

+

                        encoding = sys.getdefaultencoding() 

+

                    line = line.encode(encoding, errors=errors) 

+

                f.write(line) 

+

        finally: 

+

            f.close() 

+

 

+

 

+

    # --- Methods for querying the filesystem. 

+

 

+

    exists = os.path.exists 

+

    isabs = os.path.isabs 

+

    isdir = os.path.isdir 

+

    isfile = os.path.isfile 

+

    islink = os.path.islink 

+

    ismount = os.path.ismount 

+

 

+

    if hasattr(os.path, 'samefile'): 

+

        samefile = os.path.samefile 

+

 

+

    getatime = os.path.getatime 

+

    atime = property( 

+

        getatime, None, None, 

+

        """ Last access time of the file. """) 

+

 

+

    getmtime = os.path.getmtime 

+

    mtime = property( 

+

        getmtime, None, None, 

+

        """ Last-modified time of the file. """) 

+

 

+

    if hasattr(os.path, 'getctime'): 

+

        getctime = os.path.getctime 

+

        ctime = property( 

+

            getctime, None, None, 

+

            """ Creation time of the file. """) 

+

 

+

    getsize = os.path.getsize 

+

    size = property( 

+

        getsize, None, None, 

+

        """ Size of the file, in bytes. """) 

+

 

+

    if hasattr(os, 'access'): 

+

        def access(self, mode): 

+

            """ Return true if current user has access to this path. 

+

 

+

            mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK 

+

            """ 

+

            return os.access(self, mode) 

+

 

+

    def stat(self): 

+

        """ Perform a stat() system call on this path. """ 

+

        return os.stat(self) 

+

 

+

    def lstat(self): 

+

        """ Like path.stat(), but do not follow symbolic links. """ 

+

        return os.lstat(self) 

+

 

+

    if hasattr(os, 'statvfs'): 

+

        def statvfs(self): 

+

            """ Perform a statvfs() system call on this path. """ 

+

            return os.statvfs(self) 

+

 

+

    if hasattr(os, 'pathconf'): 

+

        def pathconf(self, name): 

+

            return os.pathconf(self, name) 

+

 

+

 

+

    # --- Modifying operations on files and directories 

+

 

+

    def utime(self, times): 

+

        """ Set the access and modified times of this file. """ 

+

        os.utime(self, times) 

+

 

+

    def chmod(self, mode): 

+

        os.chmod(self, mode) 

+

 

+

    if hasattr(os, 'chown'): 

+

        def chown(self, uid, gid): 

+

            os.chown(self, uid, gid) 

+

 

+

    def rename(self, new): 

+

        os.rename(self, new) 

+

 

+

    def renames(self, new): 

+

        os.renames(self, new) 

+

 

+

 

+

    # --- Create/delete operations on directories 

+

 

+

    def mkdir(self, mode=0777): 

+

        os.mkdir(self, mode) 

+

 

+

    def makedirs(self, mode=0777): 

+

        os.makedirs(self, mode) 

+

 

+

    def rmdir(self): 

+

        os.rmdir(self) 

+

 

+

    def removedirs(self): 

+

        os.removedirs(self) 

+

 

+

 

+

    # --- Modifying operations on files 

+

 

+

    def touch(self): 

+

        """ Set the access/modified times of this file to the current time. 

+

        Create the file if it does not exist. 

+

        """ 

+

        fd = os.open(self, os.O_WRONLY | os.O_CREAT, 0666) 

+

        os.close(fd) 

+

        os.utime(self, None) 

+

 

+

    def remove(self): 

+

        os.remove(self) 

+

 

+

    def unlink(self): 

+

        os.unlink(self) 

+

 

+

 

+

    # --- Links 

+

 

+

    if hasattr(os, 'link'): 

+

        def link(self, newpath): 

+

            """ Create a hard link at 'newpath', pointing to this file. """ 

+

            os.link(self, newpath) 

+

 

+

    if hasattr(os, 'symlink'): 

+

        def symlink(self, newlink): 

+

            """ Create a symbolic link at 'newlink', pointing here. """ 

+

            os.symlink(self, newlink) 

+

 

+

    if hasattr(os, 'readlink'): 

+

        def readlink(self): 

+

            """ Return the path to which this symbolic link points. 

+

 

+

            The result may be an absolute or a relative path. 

+

            """ 

+

            return path(os.readlink(self)) 

+

 

+

        def readlinkabs(self): 

+

            """ Return the path to which this symbolic link points. 

+

 

+

            The result is always an absolute path. 

+

            """ 

+

            p = self.readlink() 

+

            if p.isabs(): 

+

                return p 

+

            else: 

+

                return (self.parent / p).abspath() 

+

 

+

 

+

    # --- High-level functions from shutil 

+

 

+

    copyfile = shutil.copyfile 

+

    copymode = shutil.copymode 

+

    copystat = shutil.copystat 

+

    copy = shutil.copy 

+

    copy2 = shutil.copy2 

+

    copytree = shutil.copytree 

+

    if hasattr(shutil, 'move'): 

+

        move = shutil.move 

+

    rmtree = shutil.rmtree 

+

 

+

 

+

    # --- Special stuff from os 

+

 

+

    if hasattr(os, 'chroot'): 

+

        def chroot(self): 

+

            os.chroot(self) 

+

 

+

    if hasattr(os, 'startfile'): 

+

        def startfile(self): 

+

            os.startfile(self) 

+

 

+ +
+
+ + + diff --git a/doc/sample_html/cogapp_cogapp.html b/doc/sample_html/cogapp_cogapp.html index 6930fb5..555756f 100644 --- a/doc/sample_html/cogapp_cogapp.html +++ b/doc/sample_html/cogapp_cogapp.html @@ -749,715 +749,715 @@ function toggle_lines(btn, cls) { -

""" Cog code generation tool.

-

    http://nedbatchelder.com/code/cog

-

 

-

    Copyright 2004-2009, Ned Batchelder.

-

"""

-

 

-

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

-

from cStringIO import StringIO

-

 

-

# The recommended way to compute md5's changed in Python 2.5

-

try:

-

    import hashlib

-

    hash_factory = hashlib.md5

-

except ImportError:

-

    import md5

-

    hash_factory = md5.new

-

 

-

__all__ = ['Cog', 'CogUsageError']

-

 

-

__version__ = '2.2'       # 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.

-

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.

-

    -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]]] marker can be omitted, and is assumed at eof.

-

    -v          Print the version of cog and exit.

-

    -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

-

 

-

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):

-

        print >>self.stdout, "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]

-

            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

-

 

-

    def __cmp__(self, other):

-

        """ Comparison operator for tests to use.

-

        """

-

        return self.__dict__.__cmp__(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:o:rs:Uvw:xz')

-

        except getopt.error, 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 == '-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

-

            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 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.sBeginSpec = '[[[cog'

-

        self.sEndSpec = ']]]'

-

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

-

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

-

        self.sEndFormat = '[[[end]]] (checksum: %s)'

-

 

-

        self.options = CogOptions()

-

        self.sOutputMode = 'w'

-

 

-

        self.installCogModule()

-

 

-

    def showWarning(self, msg):

-

        print >>self.stdout, "Warning:", msg

-

 

-

    def isBeginSpecLine(self, s):

-

        return string.find(s, self.sBeginSpec) >= 0

-

 

-

    def isEndSpecLine(self, s):

-

        return string.find(s, self.sEndSpec) >= 0 and \

-

            not self.isEndOutputLine(s)

-

 

-

    def isEndOutputLine(self, s):

-

        return string.find(s, self.sEndOutput) >= 0

-

 

-

    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 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, basestring):

-

            # Open the input file.

-

            sFileIn = fIn

-

            fIn = fInToClose = open(fIn, 'r')

-

        if isinstance(fOut, basestring):

-

            # Open the output file.

-

            sFileOut = fOut

-

            fOut = fOutToClose = open(fOut, self.sOutputMode)

-

 

-

        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.sEndSpec,

-

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

-

                    if self.isEndOutputLine(l):

-

                        raise CogError("Unexpected '%s'" % self.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 = string.find(l, self.sBeginSpec)

-

                    end = string.find(l, self.sEndSpec)

-

                    if beg > end:

-

                        raise CogError("Cog code markers inverted",

-

                            file=sFileIn, line=firstLineNum)

-

                    else:

-

                        sCode = l[beg+len(self.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.sBeginSpec,

-

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

-

                        if self.isEndOutputLine(l):

-

                            raise CogError("Unexpected '%s'" % self.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.

-

                hasher = hash_factory()

-

                while l and not self.isEndOutputLine(l):

-

                    if self.isBeginSpecLine(l):

-

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

-

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

-

                    if self.isEndSpecLine(l):

-

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

-

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

-

                    hasher.update(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.sEndOutput,

-

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

-

 

-

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

-

                # supposed to generate code.

-

                hasher = hash_factory()

-

                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(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.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 = open(sOldPath, self.sOutputMode)

-

        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()

-

 

-

        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)])

-

 

-

            # Set the file output mode based on whether we want \n or native

-

            # line endings.

-

            self.sOutputMode = 'w'

-

            if self.options.bNewlines:

-

                self.sOutputMode = 'wb'

-

 

-

            # 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.

-

                print >>self.stdout, "Cogging %s" % sFile,

-

                bNeedNewline = True

-

 

-

                try:

-

                    fOldFile = open(sFile)

-

                    sOldText = fOldFile.read()

-

                    fOldFile.close()

-

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

-

                    if sOldText != sNewText:

-

                        print >>self.stdout, "  (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:

-

                        print >>self.stdout

-

            else:

-

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

-

        finally:

-

            self.restoreIncludePath()

-

 

-

    def processFileList(self, sFileList):

-

        """ Process the files in a file list.

-

        """

-

        flist = open(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.

-

        """

-

        argv0 = argv.pop(0)

-

 

-

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

-

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

-

            print >>self.stderr, usage,

-

            return

-

 

-

        self.options.parseArgs(argv)

-

        self.options.validate()

-

 

-

        if self.options.bShowVersion:

-

            print >>self.stdout, "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, err:

-

            print >>self.stderr, err

-

            print >>self.stderr, "(for help use -?)"

-

            return 2

-

        except CogGeneratedError, err:

-

            print >>self.stderr, "Error: %s" % err

-

            return 3

-

        except CogError, err:

-

            print >>self.stderr, 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.

+

""" Cog code generation tool. 

+

    http://nedbatchelder.com/code/cog 

+

     

+

    Copyright 2004-2009, Ned Batchelder. 

+

""" 

+

 

+

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

+

from cStringIO import StringIO 

+

 

+

# The recommended way to compute md5's changed in Python 2.5 

+

try: 

+

    import hashlib 

+

    hash_factory = hashlib.md5 

+

except ImportError: 

+

    import md5 

+

    hash_factory = md5.new 

+

 

+

__all__ = ['Cog', 'CogUsageError'] 

+

 

+

__version__ = '2.2'       # 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. 

+

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. 

+

    -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]]] marker can be omitted, and is assumed at eof. 

+

    -v          Print the version of cog and exit. 

+

    -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 

+

 

+

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): 

+

        print >>self.stdout, "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] 

+

            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 

+

 

+

    def __cmp__(self, other): 

+

        """ Comparison operator for tests to use. 

+

        """ 

+

        return self.__dict__.__cmp__(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:o:rs:Uvw:xz') 

+

        except getopt.error, 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 == '-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 

+

            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 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.sBeginSpec = '[[[cog' 

+

        self.sEndSpec = ']]]' 

+

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

+

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

+

        self.sEndFormat = '[[[end]]] (checksum: %s)' 

+

 

+

        self.options = CogOptions() 

+

        self.sOutputMode = 'w' 

+

 

+

        self.installCogModule() 

+

 

+

    def showWarning(self, msg): 

+

        print >>self.stdout, "Warning:", msg 

+

 

+

    def isBeginSpecLine(self, s): 

+

        return string.find(s, self.sBeginSpec) >= 0 

+

 

+

    def isEndSpecLine(self, s): 

+

        return string.find(s, self.sEndSpec) >= 0 and \ 

+

            not self.isEndOutputLine(s) 

+

 

+

    def isEndOutputLine(self, s): 

+

        return string.find(s, self.sEndOutput) >= 0 

+

 

+

    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 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, basestring): 

+

            # Open the input file. 

+

            sFileIn = fIn 

+

            fIn = fInToClose = open(fIn, 'r') 

+

        if isinstance(fOut, basestring): 

+

            # Open the output file. 

+

            sFileOut = fOut 

+

            fOut = fOutToClose = open(fOut, self.sOutputMode) 

+

 

+

        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.sEndSpec, 

+

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

+

                    if self.isEndOutputLine(l): 

+

                        raise CogError("Unexpected '%s'" % self.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 = string.find(l, self.sBeginSpec) 

+

                    end = string.find(l, self.sEndSpec) 

+

                    if beg > end: 

+

                        raise CogError("Cog code markers inverted", 

+

                            file=sFileIn, line=firstLineNum) 

+

                    else: 

+

                        sCode = l[beg+len(self.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.sBeginSpec, 

+

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

+

                        if self.isEndOutputLine(l): 

+

                            raise CogError("Unexpected '%s'" % self.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. 

+

                hasher = hash_factory() 

+

                while l and not self.isEndOutputLine(l): 

+

                    if self.isBeginSpecLine(l): 

+

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

+

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

+

                    if self.isEndSpecLine(l): 

+

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

+

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

+

                    hasher.update(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.sEndOutput, 

+

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

+

 

+

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

+

                # supposed to generate code. 

+

                hasher = hash_factory() 

+

                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(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.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 = open(sOldPath, self.sOutputMode) 

+

        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() 

+

 

+

        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)]) 

+

 

+

            # Set the file output mode based on whether we want \n or native 

+

            # line endings. 

+

            self.sOutputMode = 'w' 

+

            if self.options.bNewlines: 

+

                self.sOutputMode = 'wb' 

+

 

+

            # 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. 

+

                print >>self.stdout, "Cogging %s" % sFile, 

+

                bNeedNewline = True 

+

 

+

                try: 

+

                    fOldFile = open(sFile) 

+

                    sOldText = fOldFile.read() 

+

                    fOldFile.close() 

+

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

+

                    if sOldText != sNewText: 

+

                        print >>self.stdout, "  (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: 

+

                        print >>self.stdout 

+

            else: 

+

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

+

        finally: 

+

            self.restoreIncludePath() 

+

 

+

    def processFileList(self, sFileList): 

+

        """ Process the files in a file list. 

+

        """ 

+

        flist = open(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. 

+

        """ 

+

        argv0 = argv.pop(0) 

+

 

+

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

+

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

+

            print >>self.stderr, usage, 

+

            return 

+

 

+

        self.options.parseArgs(argv) 

+

        self.options.validate() 

+

 

+

        if self.options.bShowVersion: 

+

            print >>self.stdout, "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, err: 

+

            print >>self.stderr, err 

+

            print >>self.stderr, "(for help use -?)" 

+

            return 2 

+

        except CogGeneratedError, err: 

+

            print >>self.stderr, "Error: %s" % err 

+

            return 3 

+

        except CogError, err: 

+

            print >>self.stderr, 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. 

diff --git a/doc/sample_html/cogapp_makefiles.html b/doc/sample_html/cogapp_makefiles.html index d1c7e56..4d50521 100644 --- a/doc/sample_html/cogapp_makefiles.html +++ b/doc/sample_html/cogapp_makefiles.html @@ -104,70 +104,70 @@ function toggle_lines(btn, cls) { -

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

-

    http://nedbatchelder.com/code/cog

-

 

-

    Copyright 2004-2009, Ned Batchelder.

-

"""

-

 

-

import path     # Non-standard, from http://www.jorendorff.com/articles/python/path

-

from whiteutils import reindentBlock

-

 

-

__version__ = '1.0.20040126'

-

__all__ = ['makeFiles', 'removeFiles']

-

 

-

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

-

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

-

    """

-

    dirpath = path.path(basedir)

-

    for name, contents in d.items():

-

        child = dirpath / name

-

        if isinstance(contents, basestring):

-

            mode = 'w'

-

            if raw:

-

                mode = 'wb'

-

            f = open(child, mode)

-

            if not raw:

-

                contents = reindentBlock(contents)

-

            f.write(contents)

-

            f.close()

-

        else:

-

            if not child.exists():

-

                child.mkdir()

-

            makeFiles(contents, child, raw=raw)

-

 

-

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

-

    """ Remove the files created by makeFiles.

-

        Directories are removed if they are empty.

-

    """

-

    dirpath = path.path(basedir)

-

    for name, contents in d.items():

-

        child = dirpath / name

-

        if isinstance(contents, basestring):

-

            child.remove()

-

        else:

-

            removeFiles(contents, child)

-

            if not child.files() and not child.dirs():

-

                child.rmdir()

-

 

-

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)

+

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

+

    http://nedbatchelder.com/code/cog 

+

     

+

    Copyright 2004-2009, Ned Batchelder. 

+

""" 

+

 

+

import path     # Non-standard, from http://www.jorendorff.com/articles/python/path 

+

from whiteutils import reindentBlock 

+

 

+

__version__ = '1.0.20040126' 

+

__all__ = ['makeFiles', 'removeFiles'] 

+

 

+

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

+

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

+

    """ 

+

    dirpath = path.path(basedir) 

+

    for name, contents in d.items(): 

+

        child = dirpath / name 

+

        if isinstance(contents, basestring): 

+

            mode = 'w' 

+

            if raw: 

+

                mode = 'wb' 

+

            f = open(child, mode) 

+

            if not raw: 

+

                contents = reindentBlock(contents) 

+

            f.write(contents) 

+

            f.close() 

+

        else: 

+

            if not child.exists(): 

+

                child.mkdir() 

+

            makeFiles(contents, child, raw=raw) 

+

 

+

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

+

    """ Remove the files created by makeFiles. 

+

        Directories are removed if they are empty. 

+

    """ 

+

    dirpath = path.path(basedir) 

+

    for name, contents in d.items(): 

+

        child = dirpath / name 

+

        if isinstance(contents, basestring): 

+

            child.remove() 

+

        else: 

+

            removeFiles(contents, child) 

+

            if not child.files() and not child.dirs(): 

+

                child.rmdir() 

+

 

+

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) 

diff --git a/doc/sample_html/cogapp_test_cogapp.html b/doc/sample_html/cogapp_test_cogapp.html index 2f19e05..23355ae 100644 --- a/doc/sample_html/cogapp_test_cogapp.html +++ b/doc/sample_html/cogapp_test_cogapp.html @@ -2000,1966 +2000,1966 @@ function toggle_lines(btn, cls) { -

""" Test cogapp.

-

    http://nedbatchelder.com/code/cog

-

 

-

    Copyright 2004-2009, Ned Batchelder.

-

"""

-

 

-

import unittest

-

import os, random, re, StringIO, stat, sys, tempfile

-

import path     # Non-standard, from http://www.jorendorff.com/articles/python/path

-

from cogapp import Cog, CogOptions, CogGenerator

-

from cogapp import CogError, CogUsageError, CogGeneratedError

-

from cogapp import usage, __version__

-

from whiteutils import reindentBlock

-

from makefiles import *

-

 

-

class TestCase(unittest.TestCase):

-

    """ Base class for all Cog test cases.  Adds utility methods I like.

-

    """

-

    def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs):

-

        """ Just like unittest.TestCase.assertRaises,

-

            but checks that the message is right too.

-

        """

-

        try:

-

            callableObj(*args, **kwargs)

-

        except excClass, exc:

-

            excMsg = str(exc)

-

            if not msg:

-

                # No message provided: it passes.

-

                return  #pragma: no cover

-

            elif excMsg == msg:

-

                # Message provided, and we got the right message: it passes.

-

                return

-

            else:   #pragma: no cover

-

                # Message provided, and it didn't match: fail!

-

                raise self.failureException("Right exception, wrong message: got '%s' expected '%s'" % (excMsg, msg))

-

        else:   #pragma: no cover

-

            if hasattr(excClass,'__name__'):

-

                excName = excClass.__name__

-

            else:

-

                excName = str(excClass)

-

            raise self.failureException("Expected to raise %s, didn't get an exception at all" % excName)

-

 

-

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

-

            """

-

        self.assertRaisesMsg(CogError,

-

             "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))

-

 

-

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)

-

 

-

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)

-

        self.assertRaisesMsg(CogError,

-

            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)

-

        self.assertRaisesMsg(CogGeneratedError,

-

            "This ain't right!",

-

            Cog().processString, (infile))

-

 

-

    def testErrorNoMsg(self):

-

        infile = """\

-

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

-

            [[[end]]]

-

            """

-

 

-

        infile = reindentBlock(infile)

-

        self.assertRaisesMsg(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.StringIO()

-

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

-

 

-

    def setUp(self):

-

        # Create a temporary directory.

-

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

-

        self.tempdir.mkdir()

-

        self.olddir = os.getcwd()

-

        os.chdir(self.tempdir)

-

        self.newCog()

-

 

-

    def tearDown(self):

-

        os.chdir(self.olddir)

-

        # Get rid of the temporary directory.

-

        self.tempdir.rmtree()

-

 

-

    def assertFilesSame(self, sFName1, sFName2):

-

        self.assertEqual((self.tempdir / sFName1).text(), (self.tempdir / sFName2).text())

-

 

-

    def assertFileContent(self, sFName, sContent):

-

        sAbsName = self.tempdir / sFName

-

        f = open(sAbsName, 'rb')

-

        try:

-

            sFileContent = f.read()

-

        finally:

-

            f.close()

-

        self.assertEqual(sFileContent, sContent)

-

 

-

 

-

class ArgumentHandlingTests(TestCaseWithTempDir):

-

 

-

    def testArgumentFailure(self):

-

        # Return value 2 means usage problem.

-

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

-

        output = self.output.getvalue()

-

        assert(output.find("option -j not recognized") >= 0)

-

        self.assertRaises(CogUsageError, self.cog.callableMain, (['argv0']))

-

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

-

 

-

    def testNoDashOAndAtFile(self):

-

        d = {

-

            'cogfiles.txt': """\

-

                # Please run cog

-

                """

-

            }

-

 

-

        makeFiles(d)

-

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

-

 

-

    def testDashV(self):

-

        assert(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()

-

        assert(self.cog.main(argv) == 0)

-

        self.assertEquals(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)

-

        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)

-

        self.assertRaisesMsg(

-

            CogError, "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):

-

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

-

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

-

 

-

 

-

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()

-

        assert(output.find("(changed)") >= 0)

-

 

-

    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', 'test.cogged', 'test.cog'])

-

        self.assertFilesSame('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()

-

        assert(output.find("(changed)") >= 0)

-

 

-

    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()

-

        assert(output.find("(changed)") >= 0)

-

 

-

    def testAtFileWithArgs(self):

-

        d = {

-

            'both.cog': """\

-

                //[[[cog

-

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

-

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

-

                //]]]

-

                //[[[end]]]

-

                """,

-

 

-

            'one.out': """\

-

                //[[[cog

-

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

-

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

-

                //]]]

-

                one: True // ONE

-

                two: False // ONE

-

                //[[[end]]]

-

                """,

-

 

-

            'two.out': """\

-

                //[[[cog

-

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

-

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

-

                //]]]

-

                one: False // TWO

-

                two: True // TWO

-

                //[[[end]]]

-

                """,

-

 

-

            'cogfiles.txt': """\

-

                # Please run cog

-

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

-

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

-

                """

-

            }

-

 

-

        makeFiles(d)

-

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

-

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

-

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

-

 

-

    def testAtFileWithBadArgCombo(self):

-

        d = {

-

            'both.cog': """\

-

                //[[[cog

-

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

-

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

-

                //]]]

-

                //[[[end]]]

-

                """,

-

 

-

            'cogfiles.txt': """\

-

                # Please run cog

-

                both.cog

-

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

-

                """

-

            }

-

 

-

        makeFiles(d)

-

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

-

 

-

    def testAtFileWithTrickyFilenames(self):

-

        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': """\

-

                # 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')

-

 

-

 

-

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 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)

-

        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()

-

        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()

-

        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()

-

        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()

-

        assert(output.find("Warning") < 0)

-

        self.newCog()

-

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

-

        output = self.output.getvalue()

-

        assert(output.find("Warning: no cog code found in without.cog") >= 0)

-

        self.newCog()

-

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

-

        output = self.output.getvalue()

-

        assert(output.find("Warning") < 0)

-

 

-

    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()

-

        assert(output.find("(changed)") >= 0)

-

 

-

    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.StringIO()

-

        self.cog.setOutput(stderr=stderr)

-

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

-

        output = self.output.getvalue()

-

        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.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 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)

-

 

-

                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 = self.tempdir / 'test.cog'

-

        self.testcog.chmod(stat.S_IREAD)   # Make the file readonly.

-

        assert not os.access(self.testcog, os.W_OK)

-

 

-

    def tearDown(self):

-

        self.testcog.chmod(stat.S_IWRITE)   # Make the file writable again.

-

        TestCaseWithTempDir.tearDown(self)

-

 

-

    def testReadonlyNoCommand(self):

-

        self.assertRaisesMsg(

-

            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):

-

        self.assertRaisesMsg(

-

            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)

-

        self.assertRaisesMsg(CogError,

-

            "cog1.txt(9): Output has been edited! Delete old checksum to unprotect.",

-

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

-

        self.assertRaisesMsg(CogError,

-

            "cog2.txt(9): Output has been edited! Delete old checksum to unprotect.",

-

            self.cog.callableMain, (['argv0', '-c', "cog2.txt"]))

-

        self.assertRaisesMsg(CogError,

-

            "cog3.txt(10): Output has been edited! Delete old checksum to unprotect.",

-

            self.cog.callableMain, (['argv0', '-c', "cog3.txt"]))

-

        self.assertRaisesMsg(CogError,

-

            "cog4.txt(9): Output has been edited! Delete old checksum to unprotect.",

-

            self.cog.callableMain, (['argv0', '-c', "cog4.txt"]))

-

        self.assertRaisesMsg(CogError,

-

            "cog5.txt(10): Output has been edited! Delete old checksum to unprotect.",

-

            self.cog.callableMain, (['argv0', '-c', "cog5.txt"]))

-

        self.assertRaisesMsg(CogError,

-

            "cog6.txt(6): Output has been edited! Delete old checksum to unprotect.",

-

            self.cog.callableMain, (['argv0', '-c', "cog6.txt"]))

-

 

-

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)

-

        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.assert_(output.find("RuntimeError: Hey!") > 0, msg)

-

 

-

 

-

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

-

    unittest.main()

-

 

-

# Things not yet tested:

-

# - A bad -w command (currently fails silently).

+

""" Test cogapp. 

+

    http://nedbatchelder.com/code/cog 

+

     

+

    Copyright 2004-2009, Ned Batchelder. 

+

""" 

+

 

+

import unittest 

+

import os, random, re, StringIO, stat, sys, tempfile 

+

import path     # Non-standard, from http://www.jorendorff.com/articles/python/path 

+

from cogapp import Cog, CogOptions, CogGenerator 

+

from cogapp import CogError, CogUsageError, CogGeneratedError 

+

from cogapp import usage, __version__ 

+

from whiteutils import reindentBlock 

+

from makefiles import * 

+

 

+

class TestCase(unittest.TestCase): 

+

    """ Base class for all Cog test cases.  Adds utility methods I like. 

+

    """ 

+

    def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs): 

+

        """ Just like unittest.TestCase.assertRaises, 

+

            but checks that the message is right too. 

+

        """ 

+

        try: 

+

            callableObj(*args, **kwargs) 

+

        except excClass, exc: 

+

            excMsg = str(exc) 

+

            if not msg: 

+

                # No message provided: it passes. 

+

                return  #pragma: no cover 

+

            elif excMsg == msg: 

+

                # Message provided, and we got the right message: it passes. 

+

                return 

+

            else:   #pragma: no cover 

+

                # Message provided, and it didn't match: fail! 

+

                raise self.failureException("Right exception, wrong message: got '%s' expected '%s'" % (excMsg, msg)) 

+

        else:   #pragma: no cover 

+

            if hasattr(excClass,'__name__'): 

+

                excName = excClass.__name__ 

+

            else: 

+

                excName = str(excClass) 

+

            raise self.failureException("Expected to raise %s, didn't get an exception at all" % excName) 

+

 

+

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 

+

            """ 

+

        self.assertRaisesMsg(CogError, 

+

             "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)) 

+

 

+

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) 

+

 

+

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) 

+

        self.assertRaisesMsg(CogError, 

+

            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) 

+

        self.assertRaisesMsg(CogGeneratedError, 

+

            "This ain't right!", 

+

            Cog().processString, (infile)) 

+

 

+

    def testErrorNoMsg(self): 

+

        infile = """\ 

+

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

+

            [[[end]]] 

+

            """ 

+

 

+

        infile = reindentBlock(infile) 

+

        self.assertRaisesMsg(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.StringIO() 

+

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

+

 

+

    def setUp(self): 

+

        # Create a temporary directory. 

+

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

+

        self.tempdir.mkdir() 

+

        self.olddir = os.getcwd() 

+

        os.chdir(self.tempdir) 

+

        self.newCog() 

+

 

+

    def tearDown(self): 

+

        os.chdir(self.olddir) 

+

        # Get rid of the temporary directory. 

+

        self.tempdir.rmtree() 

+

 

+

    def assertFilesSame(self, sFName1, sFName2): 

+

        self.assertEqual((self.tempdir / sFName1).text(), (self.tempdir / sFName2).text()) 

+

 

+

    def assertFileContent(self, sFName, sContent): 

+

        sAbsName = self.tempdir / sFName 

+

        f = open(sAbsName, 'rb') 

+

        try: 

+

            sFileContent = f.read() 

+

        finally: 

+

            f.close() 

+

        self.assertEqual(sFileContent, sContent) 

+

 

+

 

+

class ArgumentHandlingTests(TestCaseWithTempDir): 

+

 

+

    def testArgumentFailure(self): 

+

        # Return value 2 means usage problem. 

+

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

+

        output = self.output.getvalue() 

+

        assert(output.find("option -j not recognized") >= 0) 

+

        self.assertRaises(CogUsageError, self.cog.callableMain, (['argv0'])) 

+

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

+

 

+

    def testNoDashOAndAtFile(self): 

+

        d = { 

+

            'cogfiles.txt': """\ 

+

                # Please run cog 

+

                """ 

+

            } 

+

 

+

        makeFiles(d) 

+

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

+

 

+

    def testDashV(self): 

+

        assert(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() 

+

        assert(self.cog.main(argv) == 0) 

+

        self.assertEquals(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) 

+

        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) 

+

        self.assertRaisesMsg( 

+

            CogError, "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): 

+

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

+

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

+

 

+

 

+

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() 

+

        assert(output.find("(changed)") >= 0) 

+

 

+

    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', 'test.cogged', 'test.cog']) 

+

        self.assertFilesSame('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() 

+

        assert(output.find("(changed)") >= 0) 

+

 

+

    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() 

+

        assert(output.find("(changed)") >= 0) 

+

 

+

    def testAtFileWithArgs(self): 

+

        d = { 

+

            'both.cog': """\ 

+

                //[[[cog 

+

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

+

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

+

                //]]] 

+

                //[[[end]]] 

+

                """, 

+

 

+

            'one.out': """\ 

+

                //[[[cog 

+

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

+

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

+

                //]]] 

+

                one: True // ONE 

+

                two: False // ONE 

+

                //[[[end]]] 

+

                """, 

+

 

+

            'two.out': """\ 

+

                //[[[cog 

+

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

+

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

+

                //]]] 

+

                one: False // TWO 

+

                two: True // TWO 

+

                //[[[end]]] 

+

                """, 

+

 

+

            'cogfiles.txt': """\ 

+

                # Please run cog 

+

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

+

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

+

                """ 

+

            } 

+

 

+

        makeFiles(d) 

+

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

+

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

+

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

+

 

+

    def testAtFileWithBadArgCombo(self): 

+

        d = { 

+

            'both.cog': """\ 

+

                //[[[cog 

+

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

+

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

+

                //]]] 

+

                //[[[end]]] 

+

                """, 

+

 

+

            'cogfiles.txt': """\ 

+

                # Please run cog 

+

                both.cog  

+

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

+

                """ 

+

            } 

+

 

+

        makeFiles(d) 

+

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

+

 

+

    def testAtFileWithTrickyFilenames(self): 

+

        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': """\ 

+

                # 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') 

+

 

+

 

+

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 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) 

+

        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() 

+

        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() 

+

        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() 

+

        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() 

+

        assert(output.find("Warning") < 0) 

+

        self.newCog() 

+

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

+

        output = self.output.getvalue() 

+

        assert(output.find("Warning: no cog code found in without.cog") >= 0) 

+

        self.newCog() 

+

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

+

        output = self.output.getvalue() 

+

        assert(output.find("Warning") < 0) 

+

 

+

    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() 

+

        assert(output.find("(changed)") >= 0) 

+

 

+

    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.StringIO() 

+

        self.cog.setOutput(stderr=stderr) 

+

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

+

        output = self.output.getvalue() 

+

        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.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 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) 

+

                    

+

                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 = self.tempdir / 'test.cog' 

+

        self.testcog.chmod(stat.S_IREAD)   # Make the file readonly. 

+

        assert not os.access(self.testcog, os.W_OK) 

+

 

+

    def tearDown(self): 

+

        self.testcog.chmod(stat.S_IWRITE)   # Make the file writable again. 

+

        TestCaseWithTempDir.tearDown(self) 

+

 

+

    def testReadonlyNoCommand(self): 

+

        self.assertRaisesMsg( 

+

            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): 

+

        self.assertRaisesMsg( 

+

            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) 

+

        self.assertRaisesMsg(CogError, 

+

            "cog1.txt(9): Output has been edited! Delete old checksum to unprotect.", 

+

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

+

        self.assertRaisesMsg(CogError, 

+

            "cog2.txt(9): Output has been edited! Delete old checksum to unprotect.", 

+

            self.cog.callableMain, (['argv0', '-c', "cog2.txt"])) 

+

        self.assertRaisesMsg(CogError, 

+

            "cog3.txt(10): Output has been edited! Delete old checksum to unprotect.", 

+

            self.cog.callableMain, (['argv0', '-c', "cog3.txt"])) 

+

        self.assertRaisesMsg(CogError, 

+

            "cog4.txt(9): Output has been edited! Delete old checksum to unprotect.", 

+

            self.cog.callableMain, (['argv0', '-c', "cog4.txt"])) 

+

        self.assertRaisesMsg(CogError, 

+

            "cog5.txt(10): Output has been edited! Delete old checksum to unprotect.", 

+

            self.cog.callableMain, (['argv0', '-c', "cog5.txt"])) 

+

        self.assertRaisesMsg(CogError, 

+

            "cog6.txt(6): Output has been edited! Delete old checksum to unprotect.", 

+

            self.cog.callableMain, (['argv0', '-c', "cog6.txt"])) 

+

 

+

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) 

+

        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.assert_(output.find("RuntimeError: Hey!") > 0, msg) 

+

 

+

 

+

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

+

    unittest.main() 

+

 

+

# Things not yet tested: 

+

# - A bad -w command (currently fails silently). 

diff --git a/doc/sample_html/cogapp_whiteutils.html b/doc/sample_html/cogapp_whiteutils.html index e5f8435..b2aaf86 100644 --- a/doc/sample_html/cogapp_whiteutils.html +++ b/doc/sample_html/cogapp_whiteutils.html @@ -103,69 +103,69 @@ function toggle_lines(btn, cls) { -

""" Indentation utilities for Cog.

-

    http://nedbatchelder.com/code/cog

-

 

-

    Copyright 2004-2009, Ned Batchelder.

-

"""

-

 

-

import re

-

 

-

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.

-

    prefix = re.match(r'\s*', 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.

-

    """

-

    if isinstance(lines, basestring):

-

        lines = lines.split('\n')

-

    oldIndent = whitePrefix(lines)

-

    outLines = []

-

    for l in lines:

-

        if oldIndent:

-

            l = l.replace(oldIndent, '', 1)

-

        if l and newIndent:

-

            l = newIndent + l

-

        outLines.append(l)

-

    return '\n'.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

+

""" Indentation utilities for Cog. 

+

    http://nedbatchelder.com/code/cog 

+

     

+

    Copyright 2004-2009, Ned Batchelder. 

+

""" 

+

 

+

import re 

+

 

+

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. 

+

    prefix = re.match(r'\s*', 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. 

+

    """ 

+

    if isinstance(lines, basestring): 

+

        lines = lines.split('\n') 

+

    oldIndent = whitePrefix(lines) 

+

    outLines = [] 

+

    for l in lines: 

+

        if oldIndent: 

+

            l = l.replace(oldIndent, '', 1) 

+

        if l and newIndent: 

+

            l = newIndent + l 

+

        outLines.append(l) 

+

    return '\n'.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 

diff --git a/doc/sample_html/index.html b/doc/sample_html/index.html index 478229a..c44d355 100644 --- a/doc/sample_html/index.html +++ b/doc/sample_html/index.html @@ -9,7 +9,7 @@ @@ -24,6 +24,14 @@ coverage + + c:\ned\py\path + 286 + 114 + 0 + 40% + + cogapp\cogapp 387 @@ -58,10 +66,10 @@ Total -1040 -454 +1326 +568 23 -44% +43% @@ -69,7 +77,7 @@ diff --git a/doc/sample_html/style.css b/doc/sample_html/style.css index d9d324c..34ab10e 100644 --- a/doc/sample_html/style.css +++ b/doc/sample_html/style.css @@ -54,6 +54,11 @@ a.nav:hover { } #footer { + margin: 1em 3em; + } + +#footer .content { + padding: 0; font-size: 85%; font-family: verdana, sans-serif; color: #666666; @@ -65,7 +70,7 @@ a.nav:hover { } /* Header styles */ -.content { +#header .content { padding: 1em 3em; } @@ -124,6 +129,20 @@ td.text { background: inherit; } +/* 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; -- cgit v1.2.1