##// END OF EJS Templates
tests: conditionalize test-hightlight.t on pygments version...
Gregory Szorc -
r44578:5b38c2ab default
parent child Browse files
Show More
@@ -1,1025 +1,1041 b''
1 1 from __future__ import absolute_import, print_function
2 2
3 3 import distutils.version
4 4 import os
5 5 import re
6 6 import socket
7 7 import stat
8 8 import subprocess
9 9 import sys
10 10 import tempfile
11 11
12 12 tempprefix = 'hg-hghave-'
13 13
14 14 checks = {
15 15 "true": (lambda: True, "yak shaving"),
16 16 "false": (lambda: False, "nail clipper"),
17 17 }
18 18
19 19 try:
20 20 import msvcrt
21 21
22 22 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
23 23 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
24 24 except ImportError:
25 25 pass
26 26
27 27 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
28 28 stderr = getattr(sys.stderr, 'buffer', sys.stderr)
29 29
30 30 if sys.version_info[0] >= 3:
31 31
32 32 def _bytespath(p):
33 33 if p is None:
34 34 return p
35 35 return p.encode('utf-8')
36 36
37 37 def _strpath(p):
38 38 if p is None:
39 39 return p
40 40 return p.decode('utf-8')
41 41
42 42
43 43 else:
44 44
45 45 def _bytespath(p):
46 46 return p
47 47
48 48 _strpath = _bytespath
49 49
50 50
51 51 def check(name, desc):
52 52 """Registers a check function for a feature."""
53 53
54 54 def decorator(func):
55 55 checks[name] = (func, desc)
56 56 return func
57 57
58 58 return decorator
59 59
60 60
61 61 def checkvers(name, desc, vers):
62 62 """Registers a check function for each of a series of versions.
63 63
64 64 vers can be a list or an iterator.
65 65
66 66 Produces a series of feature checks that have the form <name><vers> without
67 67 any punctuation (even if there's punctuation in 'vers'; i.e. this produces
68 68 'py38', not 'py3.8' or 'py-38')."""
69 69
70 70 def decorator(func):
71 71 def funcv(v):
72 72 def f():
73 73 return func(v)
74 74
75 75 return f
76 76
77 77 for v in vers:
78 78 v = str(v)
79 79 f = funcv(v)
80 80 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
81 81 return func
82 82
83 83 return decorator
84 84
85 85
86 86 def checkfeatures(features):
87 87 result = {
88 88 'error': [],
89 89 'missing': [],
90 90 'skipped': [],
91 91 }
92 92
93 93 for feature in features:
94 94 negate = feature.startswith('no-')
95 95 if negate:
96 96 feature = feature[3:]
97 97
98 98 if feature not in checks:
99 99 result['missing'].append(feature)
100 100 continue
101 101
102 102 check, desc = checks[feature]
103 103 try:
104 104 available = check()
105 105 except Exception:
106 106 result['error'].append('hghave check failed: %s' % feature)
107 107 continue
108 108
109 109 if not negate and not available:
110 110 result['skipped'].append('missing feature: %s' % desc)
111 111 elif negate and available:
112 112 result['skipped'].append('system supports %s' % desc)
113 113
114 114 return result
115 115
116 116
117 117 def require(features):
118 118 """Require that features are available, exiting if not."""
119 119 result = checkfeatures(features)
120 120
121 121 for missing in result['missing']:
122 122 stderr.write(
123 123 ('skipped: unknown feature: %s\n' % missing).encode('utf-8')
124 124 )
125 125 for msg in result['skipped']:
126 126 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
127 127 for msg in result['error']:
128 128 stderr.write(('%s\n' % msg).encode('utf-8'))
129 129
130 130 if result['missing']:
131 131 sys.exit(2)
132 132
133 133 if result['skipped'] or result['error']:
134 134 sys.exit(1)
135 135
136 136
137 137 def matchoutput(cmd, regexp, ignorestatus=False):
138 138 """Return the match object if cmd executes successfully and its output
139 139 is matched by the supplied regular expression.
140 140 """
141 141 r = re.compile(regexp)
142 142 p = subprocess.Popen(
143 143 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
144 144 )
145 145 s = p.communicate()[0]
146 146 ret = p.returncode
147 147 return (ignorestatus or not ret) and r.search(s)
148 148
149 149
150 150 @check("baz", "GNU Arch baz client")
151 151 def has_baz():
152 152 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
153 153
154 154
155 155 @check("bzr", "Canonical's Bazaar client")
156 156 def has_bzr():
157 157 try:
158 158 import bzrlib
159 159 import bzrlib.bzrdir
160 160 import bzrlib.errors
161 161 import bzrlib.revision
162 162 import bzrlib.revisionspec
163 163
164 164 bzrlib.revisionspec.RevisionSpec
165 165 return bzrlib.__doc__ is not None
166 166 except (AttributeError, ImportError):
167 167 return False
168 168
169 169
170 170 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
171 171 def has_bzr_range(v):
172 172 major, minor = v.split('rc')[0].split('.')[0:2]
173 173 try:
174 174 import bzrlib
175 175
176 176 return bzrlib.__doc__ is not None and bzrlib.version_info[:2] >= (
177 177 int(major),
178 178 int(minor),
179 179 )
180 180 except ImportError:
181 181 return False
182 182
183 183
184 184 @check("chg", "running with chg")
185 185 def has_chg():
186 186 return 'CHGHG' in os.environ
187 187
188 188
189 189 @check("cvs", "cvs client/server")
190 190 def has_cvs():
191 191 re = br'Concurrent Versions System.*?server'
192 192 return matchoutput('cvs --version 2>&1', re) and not has_msys()
193 193
194 194
195 195 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
196 196 def has_cvs112():
197 197 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
198 198 return matchoutput('cvs --version 2>&1', re) and not has_msys()
199 199
200 200
201 201 @check("cvsnt", "cvsnt client/server")
202 202 def has_cvsnt():
203 203 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
204 204 return matchoutput('cvsnt --version 2>&1', re)
205 205
206 206
207 207 @check("darcs", "darcs client")
208 208 def has_darcs():
209 209 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
210 210
211 211
212 212 @check("mtn", "monotone client (>= 1.0)")
213 213 def has_mtn():
214 214 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
215 215 'mtn --version', br'monotone 0\.', True
216 216 )
217 217
218 218
219 219 @check("eol-in-paths", "end-of-lines in paths")
220 220 def has_eol_in_paths():
221 221 try:
222 222 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
223 223 os.close(fd)
224 224 os.remove(path)
225 225 return True
226 226 except (IOError, OSError):
227 227 return False
228 228
229 229
230 230 @check("execbit", "executable bit")
231 231 def has_executablebit():
232 232 try:
233 233 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
234 234 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
235 235 try:
236 236 os.close(fh)
237 237 m = os.stat(fn).st_mode & 0o777
238 238 new_file_has_exec = m & EXECFLAGS
239 239 os.chmod(fn, m ^ EXECFLAGS)
240 240 exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
241 241 finally:
242 242 os.unlink(fn)
243 243 except (IOError, OSError):
244 244 # we don't care, the user probably won't be able to commit anyway
245 245 return False
246 246 return not (new_file_has_exec or exec_flags_cannot_flip)
247 247
248 248
249 249 @check("icasefs", "case insensitive file system")
250 250 def has_icasefs():
251 251 # Stolen from mercurial.util
252 252 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
253 253 os.close(fd)
254 254 try:
255 255 s1 = os.stat(path)
256 256 d, b = os.path.split(path)
257 257 p2 = os.path.join(d, b.upper())
258 258 if path == p2:
259 259 p2 = os.path.join(d, b.lower())
260 260 try:
261 261 s2 = os.stat(p2)
262 262 return s2 == s1
263 263 except OSError:
264 264 return False
265 265 finally:
266 266 os.remove(path)
267 267
268 268
269 269 @check("fifo", "named pipes")
270 270 def has_fifo():
271 271 if getattr(os, "mkfifo", None) is None:
272 272 return False
273 273 name = tempfile.mktemp(dir='.', prefix=tempprefix)
274 274 try:
275 275 os.mkfifo(name)
276 276 os.unlink(name)
277 277 return True
278 278 except OSError:
279 279 return False
280 280
281 281
282 282 @check("killdaemons", 'killdaemons.py support')
283 283 def has_killdaemons():
284 284 return True
285 285
286 286
287 287 @check("cacheable", "cacheable filesystem")
288 288 def has_cacheable_fs():
289 289 from mercurial import util
290 290
291 291 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
292 292 os.close(fd)
293 293 try:
294 294 return util.cachestat(path).cacheable()
295 295 finally:
296 296 os.remove(path)
297 297
298 298
299 299 @check("lsprof", "python lsprof module")
300 300 def has_lsprof():
301 301 try:
302 302 import _lsprof
303 303
304 304 _lsprof.Profiler # silence unused import warning
305 305 return True
306 306 except ImportError:
307 307 return False
308 308
309 309
310 310 def gethgversion():
311 311 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
312 312 if not m:
313 313 return (0, 0)
314 314 return (int(m.group(1)), int(m.group(2)))
315 315
316 316
317 317 @checkvers(
318 318 "hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)])
319 319 )
320 320 def has_hg_range(v):
321 321 major, minor = v.split('.')[0:2]
322 322 return gethgversion() >= (int(major), int(minor))
323 323
324 324
325 325 @check("hg08", "Mercurial >= 0.8")
326 326 def has_hg08():
327 327 if checks["hg09"][0]():
328 328 return True
329 329 return matchoutput('hg help annotate 2>&1', '--date')
330 330
331 331
332 332 @check("hg07", "Mercurial >= 0.7")
333 333 def has_hg07():
334 334 if checks["hg08"][0]():
335 335 return True
336 336 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
337 337
338 338
339 339 @check("hg06", "Mercurial >= 0.6")
340 340 def has_hg06():
341 341 if checks["hg07"][0]():
342 342 return True
343 343 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
344 344
345 345
346 346 @check("gettext", "GNU Gettext (msgfmt)")
347 347 def has_gettext():
348 348 return matchoutput('msgfmt --version', br'GNU gettext-tools')
349 349
350 350
351 351 @check("git", "git command line client")
352 352 def has_git():
353 353 return matchoutput('git --version 2>&1', br'^git version')
354 354
355 355
356 356 def getgitversion():
357 357 m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
358 358 if not m:
359 359 return (0, 0)
360 360 return (int(m.group(1)), int(m.group(2)))
361 361
362 362
363 363 # https://github.com/git-lfs/lfs-test-server
364 364 @check("lfs-test-server", "git-lfs test server")
365 365 def has_lfsserver():
366 366 exe = 'lfs-test-server'
367 367 if has_windows():
368 368 exe = 'lfs-test-server.exe'
369 369 return any(
370 370 os.access(os.path.join(path, exe), os.X_OK)
371 371 for path in os.environ["PATH"].split(os.pathsep)
372 372 )
373 373
374 374
375 375 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
376 376 def has_git_range(v):
377 377 major, minor = v.split('.')[0:2]
378 378 return getgitversion() >= (int(major), int(minor))
379 379
380 380
381 381 @check("docutils", "Docutils text processing library")
382 382 def has_docutils():
383 383 try:
384 384 import docutils.core
385 385
386 386 docutils.core.publish_cmdline # silence unused import
387 387 return True
388 388 except ImportError:
389 389 return False
390 390
391 391
392 392 def getsvnversion():
393 393 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
394 394 if not m:
395 395 return (0, 0)
396 396 return (int(m.group(1)), int(m.group(2)))
397 397
398 398
399 399 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
400 400 def has_svn_range(v):
401 401 major, minor = v.split('.')[0:2]
402 402 return getsvnversion() >= (int(major), int(minor))
403 403
404 404
405 405 @check("svn", "subversion client and admin tools")
406 406 def has_svn():
407 407 return matchoutput('svn --version 2>&1', br'^svn, version') and matchoutput(
408 408 'svnadmin --version 2>&1', br'^svnadmin, version'
409 409 )
410 410
411 411
412 412 @check("svn-bindings", "subversion python bindings")
413 413 def has_svn_bindings():
414 414 try:
415 415 import svn.core
416 416
417 417 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
418 418 if version < (1, 4):
419 419 return False
420 420 return True
421 421 except ImportError:
422 422 return False
423 423
424 424
425 425 @check("p4", "Perforce server and client")
426 426 def has_p4():
427 427 return matchoutput('p4 -V', br'Rev\. P4/') and matchoutput(
428 428 'p4d -V', br'Rev\. P4D/'
429 429 )
430 430
431 431
432 432 @check("symlink", "symbolic links")
433 433 def has_symlink():
434 434 # mercurial.windows.checklink() is a hard 'no' at the moment
435 435 if os.name == 'nt' or getattr(os, "symlink", None) is None:
436 436 return False
437 437 name = tempfile.mktemp(dir='.', prefix=tempprefix)
438 438 try:
439 439 os.symlink(".", name)
440 440 os.unlink(name)
441 441 return True
442 442 except (OSError, AttributeError):
443 443 return False
444 444
445 445
446 446 @check("hardlink", "hardlinks")
447 447 def has_hardlink():
448 448 from mercurial import util
449 449
450 450 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
451 451 os.close(fh)
452 452 name = tempfile.mktemp(dir='.', prefix=tempprefix)
453 453 try:
454 454 util.oslink(_bytespath(fn), _bytespath(name))
455 455 os.unlink(name)
456 456 return True
457 457 except OSError:
458 458 return False
459 459 finally:
460 460 os.unlink(fn)
461 461
462 462
463 463 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
464 464 def has_hardlink_whitelisted():
465 465 from mercurial import util
466 466
467 467 try:
468 468 fstype = util.getfstype(b'.')
469 469 except OSError:
470 470 return False
471 471 return fstype in util._hardlinkfswhitelist
472 472
473 473
474 474 @check("rmcwd", "can remove current working directory")
475 475 def has_rmcwd():
476 476 ocwd = os.getcwd()
477 477 temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
478 478 try:
479 479 os.chdir(temp)
480 480 # On Linux, 'rmdir .' isn't allowed, but the other names are okay.
481 481 # On Solaris and Windows, the cwd can't be removed by any names.
482 482 os.rmdir(os.getcwd())
483 483 return True
484 484 except OSError:
485 485 return False
486 486 finally:
487 487 os.chdir(ocwd)
488 488 # clean up temp dir on platforms where cwd can't be removed
489 489 try:
490 490 os.rmdir(temp)
491 491 except OSError:
492 492 pass
493 493
494 494
495 495 @check("tla", "GNU Arch tla client")
496 496 def has_tla():
497 497 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
498 498
499 499
500 500 @check("gpg", "gpg client")
501 501 def has_gpg():
502 502 return matchoutput('gpg --version 2>&1', br'GnuPG')
503 503
504 504
505 505 @check("gpg2", "gpg client v2")
506 506 def has_gpg2():
507 507 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
508 508
509 509
510 510 @check("gpg21", "gpg client v2.1+")
511 511 def has_gpg21():
512 512 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
513 513
514 514
515 515 @check("unix-permissions", "unix-style permissions")
516 516 def has_unix_permissions():
517 517 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
518 518 try:
519 519 fname = os.path.join(d, 'foo')
520 520 for umask in (0o77, 0o07, 0o22):
521 521 os.umask(umask)
522 522 f = open(fname, 'w')
523 523 f.close()
524 524 mode = os.stat(fname).st_mode
525 525 os.unlink(fname)
526 526 if mode & 0o777 != ~umask & 0o666:
527 527 return False
528 528 return True
529 529 finally:
530 530 os.rmdir(d)
531 531
532 532
533 533 @check("unix-socket", "AF_UNIX socket family")
534 534 def has_unix_socket():
535 535 return getattr(socket, 'AF_UNIX', None) is not None
536 536
537 537
538 538 @check("root", "root permissions")
539 539 def has_root():
540 540 return getattr(os, 'geteuid', None) and os.geteuid() == 0
541 541
542 542
543 543 @check("pyflakes", "Pyflakes python linter")
544 544 def has_pyflakes():
545 545 return matchoutput(
546 546 "sh -c \"echo 'import re' 2>&1 | pyflakes\"",
547 547 br"<stdin>:1: 're' imported but unused",
548 548 True,
549 549 )
550 550
551 551
552 552 @check("pylint", "Pylint python linter")
553 553 def has_pylint():
554 554 return matchoutput("pylint --help", br"Usage: pylint", True)
555 555
556 556
557 557 @check("clang-format", "clang-format C code formatter")
558 558 def has_clang_format():
559 559 m = matchoutput('clang-format --version', br'clang-format version (\d)')
560 560 # style changed somewhere between 4.x and 6.x
561 561 return m and int(m.group(1)) >= 6
562 562
563 563
564 564 @check("jshint", "JSHint static code analysis tool")
565 565 def has_jshint():
566 566 return matchoutput("jshint --version 2>&1", br"jshint v")
567 567
568 568
569 569 @check("pygments", "Pygments source highlighting library")
570 570 def has_pygments():
571 571 try:
572 572 import pygments
573 573
574 574 pygments.highlight # silence unused import warning
575 575 return True
576 576 except ImportError:
577 577 return False
578 578
579 579
580 @check("pygments25", "Pygments version >= 2.5")
581 def pygments25():
582 try:
583 import pygments
584
585 v = pygments.__version__
586 except ImportError:
587 return False
588
589 parts = v.split(".")
590 major = int(parts[0])
591 minor = int(parts[1])
592
593 return (major, minor) >= (2, 5)
594
595
580 596 @check("outer-repo", "outer repo")
581 597 def has_outer_repo():
582 598 # failing for other reasons than 'no repo' imply that there is a repo
583 599 return not matchoutput('hg root 2>&1', br'abort: no repository found', True)
584 600
585 601
586 602 @check("ssl", "ssl module available")
587 603 def has_ssl():
588 604 try:
589 605 import ssl
590 606
591 607 ssl.CERT_NONE
592 608 return True
593 609 except ImportError:
594 610 return False
595 611
596 612
597 613 @check("sslcontext", "python >= 2.7.9 ssl")
598 614 def has_sslcontext():
599 615 try:
600 616 import ssl
601 617
602 618 ssl.SSLContext
603 619 return True
604 620 except (ImportError, AttributeError):
605 621 return False
606 622
607 623
608 624 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
609 625 def has_defaultcacerts():
610 626 from mercurial import sslutil, ui as uimod
611 627
612 628 ui = uimod.ui.load()
613 629 return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts
614 630
615 631
616 632 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
617 633 def has_defaultcacertsloaded():
618 634 import ssl
619 635 from mercurial import sslutil, ui as uimod
620 636
621 637 if not has_defaultcacerts():
622 638 return False
623 639 if not has_sslcontext():
624 640 return False
625 641
626 642 ui = uimod.ui.load()
627 643 cafile = sslutil._defaultcacerts(ui)
628 644 ctx = ssl.create_default_context()
629 645 if cafile:
630 646 ctx.load_verify_locations(cafile=cafile)
631 647 else:
632 648 ctx.load_default_certs()
633 649
634 650 return len(ctx.get_ca_certs()) > 0
635 651
636 652
637 653 @check("tls1.2", "TLS 1.2 protocol support")
638 654 def has_tls1_2():
639 655 from mercurial import sslutil
640 656
641 657 return b'tls1.2' in sslutil.supportedprotocols
642 658
643 659
644 660 @check("windows", "Windows")
645 661 def has_windows():
646 662 return os.name == 'nt'
647 663
648 664
649 665 @check("system-sh", "system() uses sh")
650 666 def has_system_sh():
651 667 return os.name != 'nt'
652 668
653 669
654 670 @check("serve", "platform and python can manage 'hg serve -d'")
655 671 def has_serve():
656 672 return True
657 673
658 674
659 675 @check("test-repo", "running tests from repository")
660 676 def has_test_repo():
661 677 t = os.environ["TESTDIR"]
662 678 return os.path.isdir(os.path.join(t, "..", ".hg"))
663 679
664 680
665 681 @check("tic", "terminfo compiler and curses module")
666 682 def has_tic():
667 683 try:
668 684 import curses
669 685
670 686 curses.COLOR_BLUE
671 687 return matchoutput('test -x "`which tic`"', br'')
672 688 except ImportError:
673 689 return False
674 690
675 691
676 692 @check("xz", "xz compression utility")
677 693 def has_xz():
678 694 # When Windows invokes a subprocess in shell mode, it uses `cmd.exe`, which
679 695 # only knows `where`, not `which`. So invoke MSYS shell explicitly.
680 696 return matchoutput("sh -c 'test -x \"`which xz`\"'", b'')
681 697
682 698
683 699 @check("msys", "Windows with MSYS")
684 700 def has_msys():
685 701 return os.getenv('MSYSTEM')
686 702
687 703
688 704 @check("aix", "AIX")
689 705 def has_aix():
690 706 return sys.platform.startswith("aix")
691 707
692 708
693 709 @check("osx", "OS X")
694 710 def has_osx():
695 711 return sys.platform == 'darwin'
696 712
697 713
698 714 @check("osxpackaging", "OS X packaging tools")
699 715 def has_osxpackaging():
700 716 try:
701 717 return (
702 718 matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
703 719 and matchoutput(
704 720 'productbuild', br'Usage: productbuild ', ignorestatus=1
705 721 )
706 722 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
707 723 and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
708 724 )
709 725 except ImportError:
710 726 return False
711 727
712 728
713 729 @check('linuxormacos', 'Linux or MacOS')
714 730 def has_linuxormacos():
715 731 # This isn't a perfect test for MacOS. But it is sufficient for our needs.
716 732 return sys.platform.startswith(('linux', 'darwin'))
717 733
718 734
719 735 @check("docker", "docker support")
720 736 def has_docker():
721 737 pat = br'A self-sufficient runtime for'
722 738 if matchoutput('docker --help', pat):
723 739 if 'linux' not in sys.platform:
724 740 # TODO: in theory we should be able to test docker-based
725 741 # package creation on non-linux using boot2docker, but in
726 742 # practice that requires extra coordination to make sure
727 743 # $TESTTEMP is going to be visible at the same path to the
728 744 # boot2docker VM. If we figure out how to verify that, we
729 745 # can use the following instead of just saying False:
730 746 # return 'DOCKER_HOST' in os.environ
731 747 return False
732 748
733 749 return True
734 750 return False
735 751
736 752
737 753 @check("debhelper", "debian packaging tools")
738 754 def has_debhelper():
739 755 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
740 756 # quote), so just accept anything in that spot.
741 757 dpkg = matchoutput(
742 758 'dpkg --version', br"Debian .dpkg' package management program"
743 759 )
744 760 dh = matchoutput(
745 761 'dh --help', br'dh is a part of debhelper.', ignorestatus=True
746 762 )
747 763 dh_py2 = matchoutput(
748 764 'dh_python2 --help', br'other supported Python versions'
749 765 )
750 766 # debuild comes from the 'devscripts' package, though you might want
751 767 # the 'build-debs' package instead, which has a dependency on devscripts.
752 768 debuild = matchoutput(
753 769 'debuild --help', br'to run debian/rules with given parameter'
754 770 )
755 771 return dpkg and dh and dh_py2 and debuild
756 772
757 773
758 774 @check(
759 775 "debdeps", "debian build dependencies (run dpkg-checkbuilddeps in contrib/)"
760 776 )
761 777 def has_debdeps():
762 778 # just check exit status (ignoring output)
763 779 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
764 780 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
765 781
766 782
767 783 @check("demandimport", "demandimport enabled")
768 784 def has_demandimport():
769 785 # chg disables demandimport intentionally for performance wins.
770 786 return (not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable'
771 787
772 788
773 789 # Add "py27", "py35", ... as possible feature checks. Note that there's no
774 790 # punctuation here.
775 791 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
776 792 def has_python_range(v):
777 793 major, minor = v.split('.')[0:2]
778 794 py_major, py_minor = sys.version_info.major, sys.version_info.minor
779 795
780 796 return (py_major, py_minor) >= (int(major), int(minor))
781 797
782 798
783 799 @check("py3", "running with Python 3.x")
784 800 def has_py3():
785 801 return 3 == sys.version_info[0]
786 802
787 803
788 804 @check("py3exe", "a Python 3.x interpreter is available")
789 805 def has_python3exe():
790 806 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
791 807
792 808
793 809 @check("pure", "running with pure Python code")
794 810 def has_pure():
795 811 return any(
796 812 [
797 813 os.environ.get("HGMODULEPOLICY") == "py",
798 814 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
799 815 ]
800 816 )
801 817
802 818
803 819 @check("slow", "allow slow tests (use --allow-slow-tests)")
804 820 def has_slow():
805 821 return os.environ.get('HGTEST_SLOW') == 'slow'
806 822
807 823
808 824 @check("hypothesis", "Hypothesis automated test generation")
809 825 def has_hypothesis():
810 826 try:
811 827 import hypothesis
812 828
813 829 hypothesis.given
814 830 return True
815 831 except ImportError:
816 832 return False
817 833
818 834
819 835 @check("unziplinks", "unzip(1) understands and extracts symlinks")
820 836 def unzip_understands_symlinks():
821 837 return matchoutput('unzip --help', br'Info-ZIP')
822 838
823 839
824 840 @check("zstd", "zstd Python module available")
825 841 def has_zstd():
826 842 try:
827 843 import mercurial.zstd
828 844
829 845 mercurial.zstd.__version__
830 846 return True
831 847 except ImportError:
832 848 return False
833 849
834 850
835 851 @check("devfull", "/dev/full special file")
836 852 def has_dev_full():
837 853 return os.path.exists('/dev/full')
838 854
839 855
840 856 @check("ensurepip", "ensurepip module")
841 857 def has_ensurepip():
842 858 try:
843 859 import ensurepip
844 860
845 861 ensurepip.bootstrap
846 862 return True
847 863 except ImportError:
848 864 return False
849 865
850 866
851 867 @check("virtualenv", "Python virtualenv support")
852 868 def has_virtualenv():
853 869 try:
854 870 import virtualenv
855 871
856 872 virtualenv.ACTIVATE_SH
857 873 return True
858 874 except ImportError:
859 875 return False
860 876
861 877
862 878 @check("fsmonitor", "running tests with fsmonitor")
863 879 def has_fsmonitor():
864 880 return 'HGFSMONITOR_TESTS' in os.environ
865 881
866 882
867 883 @check("fuzzywuzzy", "Fuzzy string matching library")
868 884 def has_fuzzywuzzy():
869 885 try:
870 886 import fuzzywuzzy
871 887
872 888 fuzzywuzzy.__version__
873 889 return True
874 890 except ImportError:
875 891 return False
876 892
877 893
878 894 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
879 895 def has_clang_libfuzzer():
880 896 mat = matchoutput('clang --version', br'clang version (\d)')
881 897 if mat:
882 898 # libfuzzer is new in clang 6
883 899 return int(mat.group(1)) > 5
884 900 return False
885 901
886 902
887 903 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
888 904 def has_clang60():
889 905 return matchoutput('clang-6.0 --version', br'clang version 6\.')
890 906
891 907
892 908 @check("xdiff", "xdiff algorithm")
893 909 def has_xdiff():
894 910 try:
895 911 from mercurial import policy
896 912
897 913 bdiff = policy.importmod('bdiff')
898 914 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
899 915 except (ImportError, AttributeError):
900 916 return False
901 917
902 918
903 919 @check('extraextensions', 'whether tests are running with extra extensions')
904 920 def has_extraextensions():
905 921 return 'HGTESTEXTRAEXTENSIONS' in os.environ
906 922
907 923
908 924 def getrepofeatures():
909 925 """Obtain set of repository features in use.
910 926
911 927 HGREPOFEATURES can be used to define or remove features. It contains
912 928 a space-delimited list of feature strings. Strings beginning with ``-``
913 929 mean to remove.
914 930 """
915 931 # Default list provided by core.
916 932 features = {
917 933 'bundlerepo',
918 934 'revlogstore',
919 935 'fncache',
920 936 }
921 937
922 938 # Features that imply other features.
923 939 implies = {
924 940 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
925 941 }
926 942
927 943 for override in os.environ.get('HGREPOFEATURES', '').split(' '):
928 944 if not override:
929 945 continue
930 946
931 947 if override.startswith('-'):
932 948 if override[1:] in features:
933 949 features.remove(override[1:])
934 950 else:
935 951 features.add(override)
936 952
937 953 for imply in implies.get(override, []):
938 954 if imply.startswith('-'):
939 955 if imply[1:] in features:
940 956 features.remove(imply[1:])
941 957 else:
942 958 features.add(imply)
943 959
944 960 return features
945 961
946 962
947 963 @check('reporevlogstore', 'repository using the default revlog store')
948 964 def has_reporevlogstore():
949 965 return 'revlogstore' in getrepofeatures()
950 966
951 967
952 968 @check('reposimplestore', 'repository using simple storage extension')
953 969 def has_reposimplestore():
954 970 return 'simplestore' in getrepofeatures()
955 971
956 972
957 973 @check('repobundlerepo', 'whether we can open bundle files as repos')
958 974 def has_repobundlerepo():
959 975 return 'bundlerepo' in getrepofeatures()
960 976
961 977
962 978 @check('repofncache', 'repository has an fncache')
963 979 def has_repofncache():
964 980 return 'fncache' in getrepofeatures()
965 981
966 982
967 983 @check('sqlite', 'sqlite3 module is available')
968 984 def has_sqlite():
969 985 try:
970 986 import sqlite3
971 987
972 988 version = sqlite3.sqlite_version_info
973 989 except ImportError:
974 990 return False
975 991
976 992 if version < (3, 8, 3):
977 993 # WITH clause not supported
978 994 return False
979 995
980 996 return matchoutput('sqlite3 -version', br'^3\.\d+')
981 997
982 998
983 999 @check('vcr', 'vcr http mocking library')
984 1000 def has_vcr():
985 1001 try:
986 1002 import vcr
987 1003
988 1004 vcr.VCR
989 1005 return True
990 1006 except (ImportError, AttributeError):
991 1007 pass
992 1008 return False
993 1009
994 1010
995 1011 @check('emacs', 'GNU Emacs')
996 1012 def has_emacs():
997 1013 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
998 1014 # 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
999 1015 # 24 release)
1000 1016 return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
1001 1017
1002 1018
1003 1019 @check('black', 'the black formatter for python')
1004 1020 def has_black():
1005 1021 blackcmd = 'black --version'
1006 1022 version_regex = b'black, version ([0-9a-b.]+)'
1007 1023 version = matchoutput(blackcmd, version_regex)
1008 1024 sv = distutils.version.StrictVersion
1009 1025 return version and sv(_strpath(version.group(1))) >= sv('19.10b0')
1010 1026
1011 1027
1012 1028 @check('pytype', 'the pytype type checker')
1013 1029 def has_pytype():
1014 1030 pytypecmd = 'pytype --version'
1015 1031 version = matchoutput(pytypecmd, b'[0-9a-b.]+')
1016 1032 sv = distutils.version.StrictVersion
1017 1033 return version and sv(_strpath(version.group(0))) >= sv('2019.10.17')
1018 1034
1019 1035
1020 1036 @check("rustfmt", "rustfmt tool")
1021 1037 def has_rustfmt():
1022 1038 # We use Nightly's rustfmt due to current unstable config options.
1023 1039 return matchoutput(
1024 1040 '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt'
1025 1041 )
@@ -1,1038 +1,1040 b''
1 1 #require pygments serve
2 2
3 3 $ cat <<EOF >> $HGRCPATH
4 4 > [extensions]
5 5 > highlight =
6 6 > [web]
7 7 > pygments_style = friendly
8 8 > highlightfiles = **.py and size('<100KB')
9 9 > EOF
10 10 $ hg init test
11 11 $ cd test
12 12
13 13 $ filterhtml () {
14 14 > sed -e "s/class=\"k\"/class=\"kn\"/g" \
15 15 > -e "s/class=\"mf\"/class=\"mi\"/g" \
16 16 > -e "s/class=\"vm\"/class=\"n\"/g" \
17 17 > -e "s/class=\"\([cs]\)[h12]\"/class=\"\1\"/g"
18 18 > }
19 19
20 20 create random Python file to exercise Pygments
21 21
22 22 $ cat <<NO_CHECK_EOF > primes.py
23 23 > """Fun with generators. Corresponding Haskell implementation:
24 24 >
25 25 > primes = 2 : sieve [3, 5..]
26 26 > where sieve (p:ns) = p : sieve [n | n <- ns, mod n p /= 0]
27 27 > """
28 28 >
29 29 > import itertools
30 30 >
31 31 > def primes():
32 32 > """Generate all primes."""
33 33 > def sieve(ns):
34 34 > p = ns.next()
35 35 > # It is important to yield *here* in order to stop the
36 36 > # infinite recursion.
37 37 > yield p
38 38 > ns = itertools.ifilter(lambda n: n % p != 0, ns)
39 39 > for n in sieve(ns):
40 40 > yield n
41 41 >
42 42 > odds = itertools.ifilter(lambda i: i % 2 == 1, itertools.count())
43 43 > dropwhile = itertools.dropwhile
44 44 > return itertools.chain([2], sieve(dropwhile(lambda n: n < 3, odds)))
45 45 >
46 46 > if __name__ == "__main__":
47 47 > import sys
48 48 > try:
49 49 > n = int(sys.argv[1])
50 50 > except (ValueError, IndexError):
51 51 > n = 10
52 52 > p = primes()
53 53 > print("The first %d primes: %s" % (n, list(itertools.islice(p, n))))
54 54 > NO_CHECK_EOF
55 55 $ echo >> primes.py # to test html markup with an empty line just before EOF
56 56 $ hg ci -Ama
57 57 adding primes.py
58 58
59 59 hg serve
60 60
61 61 $ hg serve -p $HGPORT -d -n test --pid-file=hg.pid -A access.log -E errors.log
62 62 $ cat hg.pid >> $DAEMON_PIDS
63 63
64 64 hgweb filerevision, html
65 65
66 66 $ (get-with-headers.py localhost:$HGPORT 'file/tip/primes.py') | filterhtml
67 67 200 Script output follows
68 68
69 69 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
70 70 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
71 71 <head>
72 72 <link rel="icon" href="/static/hgicon.png" type="image/png" />
73 73 <meta name="robots" content="index, nofollow" />
74 74 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
75 75 <script type="text/javascript" src="/static/mercurial.js"></script>
76 76
77 77 <link rel="stylesheet" href="/highlightcss" type="text/css" />
78 78 <title>test: 687f2d169546 primes.py</title>
79 79 </head>
80 80 <body>
81 81
82 82 <div class="container">
83 83 <div class="menu">
84 84 <div class="logo">
85 85 <a href="https://mercurial-scm.org/">
86 86 <img src="/static/hglogo.png" alt="mercurial" /></a>
87 87 </div>
88 88 <ul>
89 89 <li><a href="/shortlog/tip">log</a></li>
90 90 <li><a href="/graph/tip">graph</a></li>
91 91 <li><a href="/tags">tags</a></li>
92 92 <li><a href="/bookmarks">bookmarks</a></li>
93 93 <li><a href="/branches">branches</a></li>
94 94 </ul>
95 95 <ul>
96 96 <li><a href="/rev/tip">changeset</a></li>
97 97 <li><a href="/file/tip/">browse</a></li>
98 98 </ul>
99 99 <ul>
100 100 <li class="active">file</li>
101 101 <li><a href="/file/tip/primes.py">latest</a></li>
102 102 <li><a href="/diff/tip/primes.py">diff</a></li>
103 103 <li><a href="/comparison/tip/primes.py">comparison</a></li>
104 104 <li><a href="/annotate/tip/primes.py">annotate</a></li>
105 105 <li><a href="/log/tip/primes.py">file log</a></li>
106 106 <li><a href="/raw-file/tip/primes.py">raw</a></li>
107 107 </ul>
108 108 <ul>
109 109 <li><a href="/help">help</a></li>
110 110 </ul>
111 111 </div>
112 112
113 113 <div class="main">
114 114 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
115 115 <h3>
116 116 view primes.py @ 0:<a href="/rev/687f2d169546">687f2d169546</a>
117 117 <span class="phase">draft</span> <span class="branchhead">default</span> <span class="tag">tip</span>
118 118 </h3>
119 119
120 120
121 121 <form class="search" action="/log">
122 122
123 123 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
124 124 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
125 125 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
126 126 </form>
127 127
128 128 <div class="description">a</div>
129 129
130 130 <table id="changesetEntry">
131 131 <tr>
132 132 <th class="author">author</th>
133 133 <td class="author">&#116;&#101;&#115;&#116;</td>
134 134 </tr>
135 135 <tr>
136 136 <th class="date">date</th>
137 137 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
138 138 </tr>
139 139 <tr>
140 140 <th class="author">parents</th>
141 141 <td class="author"></td>
142 142 </tr>
143 143 <tr>
144 144 <th class="author">children</th>
145 145 <td class="author"></td>
146 146 </tr>
147 147 </table>
148 148
149 149 <div class="overflow">
150 150 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="#">on</a></div>
151 151 <div class="sourcefirst"> line source</div>
152 152 <pre class="sourcelines stripes4 wrap bottomline"
153 153 data-logurl="/log/tip/primes.py"
154 154 data-selectabletag="SPAN"
155 155 data-ishead="1">
156 156
157 157 <span id="l1"><span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></span><a href="#l1"></a>
158 158 <span id="l2"></span><a href="#l2"></a>
159 159 <span id="l3"><span class="sd">primes = 2 : sieve [3, 5..]</span></span><a href="#l3"></a>
160 160 <span id="l4"><span class="sd"> where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></span><a href="#l4"></a>
161 161 <span id="l5"><span class="sd">&quot;&quot;&quot;</span></span><a href="#l5"></a>
162 162 <span id="l6"></span><a href="#l6"></a>
163 163 <span id="l7"><span class="kn">import</span> <span class="nn">itertools</span></span><a href="#l7"></a>
164 164 <span id="l8"></span><a href="#l8"></a>
165 165 <span id="l9"><span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></span><a href="#l9"></a>
166 166 <span id="l10"> <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></span><a href="#l10"></a>
167 167 <span id="l11"> <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></span><a href="#l11"></a>
168 168 <span id="l12"> <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></span><a href="#l12"></a>
169 169 <span id="l13"> <span class="c"># It is important to yield *here* in order to stop the</span></span><a href="#l13"></a>
170 170 <span id="l14"> <span class="c"># infinite recursion.</span></span><a href="#l14"></a>
171 171 <span id="l15"> <span class="kn">yield</span> <span class="n">p</span></span><a href="#l15"></a>
172 172 <span id="l16"> <span class="n">ns</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></span><a href="#l16"></a>
173 173 <span id="l17"> <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></span><a href="#l17"></a>
174 174 <span id="l18"> <span class="kn">yield</span> <span class="n">n</span></span><a href="#l18"></a>
175 175 <span id="l19"></span><a href="#l19"></a>
176 176 <span id="l20"> <span class="n">odds</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">itertools</span><span class="o">.</span><span class="n">count</span><span class="p">())</span></span><a href="#l20"></a>
177 177 <span id="l21"> <span class="n">dropwhile</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">dropwhile</span></span><a href="#l21"></a>
178 178 <span id="l22"> <span class="kn">return</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></span><a href="#l22"></a>
179 179 <span id="l23"></span><a href="#l23"></a>
180 180 <span id="l24"><span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></span><a href="#l24"></a>
181 181 <span id="l25"> <span class="kn">import</span> <span class="nn">sys</span></span><a href="#l25"></a>
182 182 <span id="l26"> <span class="kn">try</span><span class="p">:</span></span><a href="#l26"></a>
183 183 <span id="l27"> <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></span><a href="#l27"></a>
184 184 <span id="l28"> <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></span><a href="#l28"></a>
185 185 <span id="l29"> <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></span><a href="#l29"></a>
186 186 <span id="l30"> <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></span><a href="#l30"></a>
187 <span id="l31"> <span class="kn">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></span><a href="#l31"></a>
187 <span id="l31"> <span class="nb">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></span><a href="#l31"></a> (pygments25 !)
188 <span id="l31"> <span class="kn">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></span><a href="#l31"></a> (no-pygments25 !)
188 189 <span id="l32"></span><a href="#l32"></a>
189 190 </pre>
190 191 </div>
191 192
192 193 <script type="text/javascript" src="/static/followlines.js"></script>
193 194
194 195 </div>
195 196 </div>
196 197
197 198
198 199
199 200 </body>
200 201 </html>
201 202
202 203
203 204 hgweb fileannotate, html
204 205
205 206 $ (get-with-headers.py localhost:$HGPORT 'annotate/tip/primes.py') | filterhtml
206 207 200 Script output follows
207 208
208 209 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
209 210 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
210 211 <head>
211 212 <link rel="icon" href="/static/hgicon.png" type="image/png" />
212 213 <meta name="robots" content="index, nofollow" />
213 214 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
214 215 <script type="text/javascript" src="/static/mercurial.js"></script>
215 216
216 217 <link rel="stylesheet" href="/highlightcss" type="text/css" />
217 218 <title>test: primes.py annotate</title>
218 219 </head>
219 220 <body>
220 221
221 222 <div class="container">
222 223 <div class="menu">
223 224 <div class="logo">
224 225 <a href="https://mercurial-scm.org/">
225 226 <img src="/static/hglogo.png" alt="mercurial" /></a>
226 227 </div>
227 228 <ul>
228 229 <li><a href="/shortlog/tip">log</a></li>
229 230 <li><a href="/graph/tip">graph</a></li>
230 231 <li><a href="/tags">tags</a></li>
231 232 <li><a href="/bookmarks">bookmarks</a></li>
232 233 <li><a href="/branches">branches</a></li>
233 234 </ul>
234 235
235 236 <ul>
236 237 <li><a href="/rev/tip">changeset</a></li>
237 238 <li><a href="/file/tip/">browse</a></li>
238 239 </ul>
239 240 <ul>
240 241 <li><a href="/file/tip/primes.py">file</a></li>
241 242 <li><a href="/file/tip/primes.py">latest</a></li>
242 243 <li><a href="/diff/tip/primes.py">diff</a></li>
243 244 <li><a href="/comparison/tip/primes.py">comparison</a></li>
244 245 <li class="active">annotate</li>
245 246 <li><a href="/log/tip/primes.py">file log</a></li>
246 247 <li><a href="/raw-file/tip/primes.py">raw</a></li>
247 248 </ul>
248 249 <ul>
249 250 <li><a href="/help">help</a></li>
250 251 </ul>
251 252 </div>
252 253
253 254 <div class="main">
254 255 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
255 256 <h3>
256 257 annotate primes.py @ 0:<a href="/rev/687f2d169546">687f2d169546</a>
257 258 <span class="phase">draft</span> <span class="branchhead">default</span> <span class="tag">tip</span>
258 259 </h3>
259 260
260 261
261 262 <form class="search" action="/log">
262 263
263 264 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
264 265 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
265 266 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
266 267 </form>
267 268
268 269 <div class="description">a</div>
269 270
270 271 <table id="changesetEntry">
271 272 <tr>
272 273 <th class="author">author</th>
273 274 <td class="author">&#116;&#101;&#115;&#116;</td>
274 275 </tr>
275 276 <tr>
276 277 <th class="date">date</th>
277 278 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
278 279 </tr>
279 280 <tr>
280 281 <th class="author">parents</th>
281 282 <td class="author"></td>
282 283 </tr>
283 284 <tr>
284 285 <th class="author">children</th>
285 286 <td class="author"></td>
286 287 </tr>
287 288 </table>
288 289
289 290
290 291 <form id="diffopts-form"
291 292 data-ignorews="0"
292 293 data-ignorewsamount="0"
293 294 data-ignorewseol="0"
294 295 data-ignoreblanklines="0">
295 296 <span>Ignore whitespace changes - </span>
296 297 <span>Everywhere:</span>
297 298 <input id="ignorews-checkbox" type="checkbox" />
298 299 <span>Within whitespace:</span>
299 300 <input id="ignorewsamount-checkbox" type="checkbox" />
300 301 <span>At end of lines:</span>
301 302 <input id="ignorewseol-checkbox" type="checkbox" />
302 303 </form>
303 304
304 305 <script type="text/javascript">
305 306 renderDiffOptsForm();
306 307 </script>
307 308
308 309 <div class="overflow">
309 310 <table class="bigtable">
310 311 <thead>
311 312 <tr>
312 313 <th class="annotate">rev</th>
313 314 <th class="line">&nbsp;&nbsp;line source</th>
314 315 </tr>
315 316 </thead>
316 317 <tbody class="stripes2 sourcelines"
317 318 data-logurl="/log/tip/primes.py"
318 319 data-selectabletag="TR"
319 320 data-ishead="1">
320 321
321 322 <tr id="l1" class="thisrev">
322 323 <td class="annotate parity0">
323 324 <a href="/annotate/687f2d169546/primes.py#l1">
324 325 0
325 326 </a>
326 327 <div class="annotate-info">
327 328 <div>
328 329 <a href="/annotate/687f2d169546/primes.py#l1">
329 330 687f2d169546</a>
330 331 a
331 332 </div>
332 333 <div><em>&#116;&#101;&#115;&#116;</em></div>
333 334 <div>parents: </div>
334 335 <a href="/diff/687f2d169546/primes.py">diff</a>
335 336 <a href="/rev/687f2d169546">changeset</a>
336 337 </div>
337 338 </td>
338 339 <td class="source followlines-btn-parent"><a href="#l1"> 1</a> <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></td>
339 340 </tr>
340 341 <tr id="l2" class="thisrev">
341 342 <td class="annotate parity0">
342 343
343 344 <div class="annotate-info">
344 345 <div>
345 346 <a href="/annotate/687f2d169546/primes.py#l2">
346 347 687f2d169546</a>
347 348 a
348 349 </div>
349 350 <div><em>&#116;&#101;&#115;&#116;</em></div>
350 351 <div>parents: </div>
351 352 <a href="/diff/687f2d169546/primes.py">diff</a>
352 353 <a href="/rev/687f2d169546">changeset</a>
353 354 </div>
354 355 </td>
355 356 <td class="source followlines-btn-parent"><a href="#l2"> 2</a> </td>
356 357 </tr>
357 358 <tr id="l3" class="thisrev">
358 359 <td class="annotate parity0">
359 360
360 361 <div class="annotate-info">
361 362 <div>
362 363 <a href="/annotate/687f2d169546/primes.py#l3">
363 364 687f2d169546</a>
364 365 a
365 366 </div>
366 367 <div><em>&#116;&#101;&#115;&#116;</em></div>
367 368 <div>parents: </div>
368 369 <a href="/diff/687f2d169546/primes.py">diff</a>
369 370 <a href="/rev/687f2d169546">changeset</a>
370 371 </div>
371 372 </td>
372 373 <td class="source followlines-btn-parent"><a href="#l3"> 3</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></td>
373 374 </tr>
374 375 <tr id="l4" class="thisrev">
375 376 <td class="annotate parity0">
376 377
377 378 <div class="annotate-info">
378 379 <div>
379 380 <a href="/annotate/687f2d169546/primes.py#l4">
380 381 687f2d169546</a>
381 382 a
382 383 </div>
383 384 <div><em>&#116;&#101;&#115;&#116;</em></div>
384 385 <div>parents: </div>
385 386 <a href="/diff/687f2d169546/primes.py">diff</a>
386 387 <a href="/rev/687f2d169546">changeset</a>
387 388 </div>
388 389 </td>
389 390 <td class="source followlines-btn-parent"><a href="#l4"> 4</a> <span class="sd"> where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></td>
390 391 </tr>
391 392 <tr id="l5" class="thisrev">
392 393 <td class="annotate parity0">
393 394
394 395 <div class="annotate-info">
395 396 <div>
396 397 <a href="/annotate/687f2d169546/primes.py#l5">
397 398 687f2d169546</a>
398 399 a
399 400 </div>
400 401 <div><em>&#116;&#101;&#115;&#116;</em></div>
401 402 <div>parents: </div>
402 403 <a href="/diff/687f2d169546/primes.py">diff</a>
403 404 <a href="/rev/687f2d169546">changeset</a>
404 405 </div>
405 406 </td>
406 407 <td class="source followlines-btn-parent"><a href="#l5"> 5</a> <span class="sd">&quot;&quot;&quot;</span></td>
407 408 </tr>
408 409 <tr id="l6" class="thisrev">
409 410 <td class="annotate parity0">
410 411
411 412 <div class="annotate-info">
412 413 <div>
413 414 <a href="/annotate/687f2d169546/primes.py#l6">
414 415 687f2d169546</a>
415 416 a
416 417 </div>
417 418 <div><em>&#116;&#101;&#115;&#116;</em></div>
418 419 <div>parents: </div>
419 420 <a href="/diff/687f2d169546/primes.py">diff</a>
420 421 <a href="/rev/687f2d169546">changeset</a>
421 422 </div>
422 423 </td>
423 424 <td class="source followlines-btn-parent"><a href="#l6"> 6</a> </td>
424 425 </tr>
425 426 <tr id="l7" class="thisrev">
426 427 <td class="annotate parity0">
427 428
428 429 <div class="annotate-info">
429 430 <div>
430 431 <a href="/annotate/687f2d169546/primes.py#l7">
431 432 687f2d169546</a>
432 433 a
433 434 </div>
434 435 <div><em>&#116;&#101;&#115;&#116;</em></div>
435 436 <div>parents: </div>
436 437 <a href="/diff/687f2d169546/primes.py">diff</a>
437 438 <a href="/rev/687f2d169546">changeset</a>
438 439 </div>
439 440 </td>
440 441 <td class="source followlines-btn-parent"><a href="#l7"> 7</a> <span class="kn">import</span> <span class="nn">itertools</span></td>
441 442 </tr>
442 443 <tr id="l8" class="thisrev">
443 444 <td class="annotate parity0">
444 445
445 446 <div class="annotate-info">
446 447 <div>
447 448 <a href="/annotate/687f2d169546/primes.py#l8">
448 449 687f2d169546</a>
449 450 a
450 451 </div>
451 452 <div><em>&#116;&#101;&#115;&#116;</em></div>
452 453 <div>parents: </div>
453 454 <a href="/diff/687f2d169546/primes.py">diff</a>
454 455 <a href="/rev/687f2d169546">changeset</a>
455 456 </div>
456 457 </td>
457 458 <td class="source followlines-btn-parent"><a href="#l8"> 8</a> </td>
458 459 </tr>
459 460 <tr id="l9" class="thisrev">
460 461 <td class="annotate parity0">
461 462
462 463 <div class="annotate-info">
463 464 <div>
464 465 <a href="/annotate/687f2d169546/primes.py#l9">
465 466 687f2d169546</a>
466 467 a
467 468 </div>
468 469 <div><em>&#116;&#101;&#115;&#116;</em></div>
469 470 <div>parents: </div>
470 471 <a href="/diff/687f2d169546/primes.py">diff</a>
471 472 <a href="/rev/687f2d169546">changeset</a>
472 473 </div>
473 474 </td>
474 475 <td class="source followlines-btn-parent"><a href="#l9"> 9</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></td>
475 476 </tr>
476 477 <tr id="l10" class="thisrev">
477 478 <td class="annotate parity0">
478 479
479 480 <div class="annotate-info">
480 481 <div>
481 482 <a href="/annotate/687f2d169546/primes.py#l10">
482 483 687f2d169546</a>
483 484 a
484 485 </div>
485 486 <div><em>&#116;&#101;&#115;&#116;</em></div>
486 487 <div>parents: </div>
487 488 <a href="/diff/687f2d169546/primes.py">diff</a>
488 489 <a href="/rev/687f2d169546">changeset</a>
489 490 </div>
490 491 </td>
491 492 <td class="source followlines-btn-parent"><a href="#l10"> 10</a> <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></td>
492 493 </tr>
493 494 <tr id="l11" class="thisrev">
494 495 <td class="annotate parity0">
495 496
496 497 <div class="annotate-info">
497 498 <div>
498 499 <a href="/annotate/687f2d169546/primes.py#l11">
499 500 687f2d169546</a>
500 501 a
501 502 </div>
502 503 <div><em>&#116;&#101;&#115;&#116;</em></div>
503 504 <div>parents: </div>
504 505 <a href="/diff/687f2d169546/primes.py">diff</a>
505 506 <a href="/rev/687f2d169546">changeset</a>
506 507 </div>
507 508 </td>
508 509 <td class="source followlines-btn-parent"><a href="#l11"> 11</a> <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
509 510 </tr>
510 511 <tr id="l12" class="thisrev">
511 512 <td class="annotate parity0">
512 513
513 514 <div class="annotate-info">
514 515 <div>
515 516 <a href="/annotate/687f2d169546/primes.py#l12">
516 517 687f2d169546</a>
517 518 a
518 519 </div>
519 520 <div><em>&#116;&#101;&#115;&#116;</em></div>
520 521 <div>parents: </div>
521 522 <a href="/diff/687f2d169546/primes.py">diff</a>
522 523 <a href="/rev/687f2d169546">changeset</a>
523 524 </div>
524 525 </td>
525 526 <td class="source followlines-btn-parent"><a href="#l12"> 12</a> <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></td>
526 527 </tr>
527 528 <tr id="l13" class="thisrev">
528 529 <td class="annotate parity0">
529 530
530 531 <div class="annotate-info">
531 532 <div>
532 533 <a href="/annotate/687f2d169546/primes.py#l13">
533 534 687f2d169546</a>
534 535 a
535 536 </div>
536 537 <div><em>&#116;&#101;&#115;&#116;</em></div>
537 538 <div>parents: </div>
538 539 <a href="/diff/687f2d169546/primes.py">diff</a>
539 540 <a href="/rev/687f2d169546">changeset</a>
540 541 </div>
541 542 </td>
542 543 <td class="source followlines-btn-parent"><a href="#l13"> 13</a> <span class="c"># It is important to yield *here* in order to stop the</span></td>
543 544 </tr>
544 545 <tr id="l14" class="thisrev">
545 546 <td class="annotate parity0">
546 547
547 548 <div class="annotate-info">
548 549 <div>
549 550 <a href="/annotate/687f2d169546/primes.py#l14">
550 551 687f2d169546</a>
551 552 a
552 553 </div>
553 554 <div><em>&#116;&#101;&#115;&#116;</em></div>
554 555 <div>parents: </div>
555 556 <a href="/diff/687f2d169546/primes.py">diff</a>
556 557 <a href="/rev/687f2d169546">changeset</a>
557 558 </div>
558 559 </td>
559 560 <td class="source followlines-btn-parent"><a href="#l14"> 14</a> <span class="c"># infinite recursion.</span></td>
560 561 </tr>
561 562 <tr id="l15" class="thisrev">
562 563 <td class="annotate parity0">
563 564
564 565 <div class="annotate-info">
565 566 <div>
566 567 <a href="/annotate/687f2d169546/primes.py#l15">
567 568 687f2d169546</a>
568 569 a
569 570 </div>
570 571 <div><em>&#116;&#101;&#115;&#116;</em></div>
571 572 <div>parents: </div>
572 573 <a href="/diff/687f2d169546/primes.py">diff</a>
573 574 <a href="/rev/687f2d169546">changeset</a>
574 575 </div>
575 576 </td>
576 577 <td class="source followlines-btn-parent"><a href="#l15"> 15</a> <span class="kn">yield</span> <span class="n">p</span></td>
577 578 </tr>
578 579 <tr id="l16" class="thisrev">
579 580 <td class="annotate parity0">
580 581
581 582 <div class="annotate-info">
582 583 <div>
583 584 <a href="/annotate/687f2d169546/primes.py#l16">
584 585 687f2d169546</a>
585 586 a
586 587 </div>
587 588 <div><em>&#116;&#101;&#115;&#116;</em></div>
588 589 <div>parents: </div>
589 590 <a href="/diff/687f2d169546/primes.py">diff</a>
590 591 <a href="/rev/687f2d169546">changeset</a>
591 592 </div>
592 593 </td>
593 594 <td class="source followlines-btn-parent"><a href="#l16"> 16</a> <span class="n">ns</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></td>
594 595 </tr>
595 596 <tr id="l17" class="thisrev">
596 597 <td class="annotate parity0">
597 598
598 599 <div class="annotate-info">
599 600 <div>
600 601 <a href="/annotate/687f2d169546/primes.py#l17">
601 602 687f2d169546</a>
602 603 a
603 604 </div>
604 605 <div><em>&#116;&#101;&#115;&#116;</em></div>
605 606 <div>parents: </div>
606 607 <a href="/diff/687f2d169546/primes.py">diff</a>
607 608 <a href="/rev/687f2d169546">changeset</a>
608 609 </div>
609 610 </td>
610 611 <td class="source followlines-btn-parent"><a href="#l17"> 17</a> <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></td>
611 612 </tr>
612 613 <tr id="l18" class="thisrev">
613 614 <td class="annotate parity0">
614 615
615 616 <div class="annotate-info">
616 617 <div>
617 618 <a href="/annotate/687f2d169546/primes.py#l18">
618 619 687f2d169546</a>
619 620 a
620 621 </div>
621 622 <div><em>&#116;&#101;&#115;&#116;</em></div>
622 623 <div>parents: </div>
623 624 <a href="/diff/687f2d169546/primes.py">diff</a>
624 625 <a href="/rev/687f2d169546">changeset</a>
625 626 </div>
626 627 </td>
627 628 <td class="source followlines-btn-parent"><a href="#l18"> 18</a> <span class="kn">yield</span> <span class="n">n</span></td>
628 629 </tr>
629 630 <tr id="l19" class="thisrev">
630 631 <td class="annotate parity0">
631 632
632 633 <div class="annotate-info">
633 634 <div>
634 635 <a href="/annotate/687f2d169546/primes.py#l19">
635 636 687f2d169546</a>
636 637 a
637 638 </div>
638 639 <div><em>&#116;&#101;&#115;&#116;</em></div>
639 640 <div>parents: </div>
640 641 <a href="/diff/687f2d169546/primes.py">diff</a>
641 642 <a href="/rev/687f2d169546">changeset</a>
642 643 </div>
643 644 </td>
644 645 <td class="source followlines-btn-parent"><a href="#l19"> 19</a> </td>
645 646 </tr>
646 647 <tr id="l20" class="thisrev">
647 648 <td class="annotate parity0">
648 649
649 650 <div class="annotate-info">
650 651 <div>
651 652 <a href="/annotate/687f2d169546/primes.py#l20">
652 653 687f2d169546</a>
653 654 a
654 655 </div>
655 656 <div><em>&#116;&#101;&#115;&#116;</em></div>
656 657 <div>parents: </div>
657 658 <a href="/diff/687f2d169546/primes.py">diff</a>
658 659 <a href="/rev/687f2d169546">changeset</a>
659 660 </div>
660 661 </td>
661 662 <td class="source followlines-btn-parent"><a href="#l20"> 20</a> <span class="n">odds</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">itertools</span><span class="o">.</span><span class="n">count</span><span class="p">())</span></td>
662 663 </tr>
663 664 <tr id="l21" class="thisrev">
664 665 <td class="annotate parity0">
665 666
666 667 <div class="annotate-info">
667 668 <div>
668 669 <a href="/annotate/687f2d169546/primes.py#l21">
669 670 687f2d169546</a>
670 671 a
671 672 </div>
672 673 <div><em>&#116;&#101;&#115;&#116;</em></div>
673 674 <div>parents: </div>
674 675 <a href="/diff/687f2d169546/primes.py">diff</a>
675 676 <a href="/rev/687f2d169546">changeset</a>
676 677 </div>
677 678 </td>
678 679 <td class="source followlines-btn-parent"><a href="#l21"> 21</a> <span class="n">dropwhile</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">dropwhile</span></td>
679 680 </tr>
680 681 <tr id="l22" class="thisrev">
681 682 <td class="annotate parity0">
682 683
683 684 <div class="annotate-info">
684 685 <div>
685 686 <a href="/annotate/687f2d169546/primes.py#l22">
686 687 687f2d169546</a>
687 688 a
688 689 </div>
689 690 <div><em>&#116;&#101;&#115;&#116;</em></div>
690 691 <div>parents: </div>
691 692 <a href="/diff/687f2d169546/primes.py">diff</a>
692 693 <a href="/rev/687f2d169546">changeset</a>
693 694 </div>
694 695 </td>
695 696 <td class="source followlines-btn-parent"><a href="#l22"> 22</a> <span class="kn">return</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></td>
696 697 </tr>
697 698 <tr id="l23" class="thisrev">
698 699 <td class="annotate parity0">
699 700
700 701 <div class="annotate-info">
701 702 <div>
702 703 <a href="/annotate/687f2d169546/primes.py#l23">
703 704 687f2d169546</a>
704 705 a
705 706 </div>
706 707 <div><em>&#116;&#101;&#115;&#116;</em></div>
707 708 <div>parents: </div>
708 709 <a href="/diff/687f2d169546/primes.py">diff</a>
709 710 <a href="/rev/687f2d169546">changeset</a>
710 711 </div>
711 712 </td>
712 713 <td class="source followlines-btn-parent"><a href="#l23"> 23</a> </td>
713 714 </tr>
714 715 <tr id="l24" class="thisrev">
715 716 <td class="annotate parity0">
716 717
717 718 <div class="annotate-info">
718 719 <div>
719 720 <a href="/annotate/687f2d169546/primes.py#l24">
720 721 687f2d169546</a>
721 722 a
722 723 </div>
723 724 <div><em>&#116;&#101;&#115;&#116;</em></div>
724 725 <div>parents: </div>
725 726 <a href="/diff/687f2d169546/primes.py">diff</a>
726 727 <a href="/rev/687f2d169546">changeset</a>
727 728 </div>
728 729 </td>
729 730 <td class="source followlines-btn-parent"><a href="#l24"> 24</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></td>
730 731 </tr>
731 732 <tr id="l25" class="thisrev">
732 733 <td class="annotate parity0">
733 734
734 735 <div class="annotate-info">
735 736 <div>
736 737 <a href="/annotate/687f2d169546/primes.py#l25">
737 738 687f2d169546</a>
738 739 a
739 740 </div>
740 741 <div><em>&#116;&#101;&#115;&#116;</em></div>
741 742 <div>parents: </div>
742 743 <a href="/diff/687f2d169546/primes.py">diff</a>
743 744 <a href="/rev/687f2d169546">changeset</a>
744 745 </div>
745 746 </td>
746 747 <td class="source followlines-btn-parent"><a href="#l25"> 25</a> <span class="kn">import</span> <span class="nn">sys</span></td>
747 748 </tr>
748 749 <tr id="l26" class="thisrev">
749 750 <td class="annotate parity0">
750 751
751 752 <div class="annotate-info">
752 753 <div>
753 754 <a href="/annotate/687f2d169546/primes.py#l26">
754 755 687f2d169546</a>
755 756 a
756 757 </div>
757 758 <div><em>&#116;&#101;&#115;&#116;</em></div>
758 759 <div>parents: </div>
759 760 <a href="/diff/687f2d169546/primes.py">diff</a>
760 761 <a href="/rev/687f2d169546">changeset</a>
761 762 </div>
762 763 </td>
763 764 <td class="source followlines-btn-parent"><a href="#l26"> 26</a> <span class="kn">try</span><span class="p">:</span></td>
764 765 </tr>
765 766 <tr id="l27" class="thisrev">
766 767 <td class="annotate parity0">
767 768
768 769 <div class="annotate-info">
769 770 <div>
770 771 <a href="/annotate/687f2d169546/primes.py#l27">
771 772 687f2d169546</a>
772 773 a
773 774 </div>
774 775 <div><em>&#116;&#101;&#115;&#116;</em></div>
775 776 <div>parents: </div>
776 777 <a href="/diff/687f2d169546/primes.py">diff</a>
777 778 <a href="/rev/687f2d169546">changeset</a>
778 779 </div>
779 780 </td>
780 781 <td class="source followlines-btn-parent"><a href="#l27"> 27</a> <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></td>
781 782 </tr>
782 783 <tr id="l28" class="thisrev">
783 784 <td class="annotate parity0">
784 785
785 786 <div class="annotate-info">
786 787 <div>
787 788 <a href="/annotate/687f2d169546/primes.py#l28">
788 789 687f2d169546</a>
789 790 a
790 791 </div>
791 792 <div><em>&#116;&#101;&#115;&#116;</em></div>
792 793 <div>parents: </div>
793 794 <a href="/diff/687f2d169546/primes.py">diff</a>
794 795 <a href="/rev/687f2d169546">changeset</a>
795 796 </div>
796 797 </td>
797 798 <td class="source followlines-btn-parent"><a href="#l28"> 28</a> <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></td>
798 799 </tr>
799 800 <tr id="l29" class="thisrev">
800 801 <td class="annotate parity0">
801 802
802 803 <div class="annotate-info">
803 804 <div>
804 805 <a href="/annotate/687f2d169546/primes.py#l29">
805 806 687f2d169546</a>
806 807 a
807 808 </div>
808 809 <div><em>&#116;&#101;&#115;&#116;</em></div>
809 810 <div>parents: </div>
810 811 <a href="/diff/687f2d169546/primes.py">diff</a>
811 812 <a href="/rev/687f2d169546">changeset</a>
812 813 </div>
813 814 </td>
814 815 <td class="source followlines-btn-parent"><a href="#l29"> 29</a> <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></td>
815 816 </tr>
816 817 <tr id="l30" class="thisrev">
817 818 <td class="annotate parity0">
818 819
819 820 <div class="annotate-info">
820 821 <div>
821 822 <a href="/annotate/687f2d169546/primes.py#l30">
822 823 687f2d169546</a>
823 824 a
824 825 </div>
825 826 <div><em>&#116;&#101;&#115;&#116;</em></div>
826 827 <div>parents: </div>
827 828 <a href="/diff/687f2d169546/primes.py">diff</a>
828 829 <a href="/rev/687f2d169546">changeset</a>
829 830 </div>
830 831 </td>
831 832 <td class="source followlines-btn-parent"><a href="#l30"> 30</a> <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></td>
832 833 </tr>
833 834 <tr id="l31" class="thisrev">
834 835 <td class="annotate parity0">
835 836
836 837 <div class="annotate-info">
837 838 <div>
838 839 <a href="/annotate/687f2d169546/primes.py#l31">
839 840 687f2d169546</a>
840 841 a
841 842 </div>
842 843 <div><em>&#116;&#101;&#115;&#116;</em></div>
843 844 <div>parents: </div>
844 845 <a href="/diff/687f2d169546/primes.py">diff</a>
845 846 <a href="/rev/687f2d169546">changeset</a>
846 847 </div>
847 848 </td>
848 <td class="source followlines-btn-parent"><a href="#l31"> 31</a> <span class="kn">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></td>
849 <td class="source followlines-btn-parent"><a href="#l31"> 31</a> <span class="nb">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></td> (pygments25 !)
850 <td class="source followlines-btn-parent"><a href="#l31"> 31</a> <span class="kn">print</span><span class="p">(</span><span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">))))</span></td> (no-pygments25 !)
849 851 </tr>
850 852 <tr id="l32" class="thisrev">
851 853 <td class="annotate parity0">
852 854
853 855 <div class="annotate-info">
854 856 <div>
855 857 <a href="/annotate/687f2d169546/primes.py#l32">
856 858 687f2d169546</a>
857 859 a
858 860 </div>
859 861 <div><em>&#116;&#101;&#115;&#116;</em></div>
860 862 <div>parents: </div>
861 863 <a href="/diff/687f2d169546/primes.py">diff</a>
862 864 <a href="/rev/687f2d169546">changeset</a>
863 865 </div>
864 866 </td>
865 867 <td class="source followlines-btn-parent"><a href="#l32"> 32</a> </td>
866 868 </tr>
867 869 </tbody>
868 870 </table>
869 871 </div>
870 872 </div>
871 873 </div>
872 874
873 875 <script type="text/javascript" src="/static/followlines.js"></script>
874 876
875 877
876 878
877 879 </body>
878 880 </html>
879 881
880 882
881 883 hgweb fileannotate, raw
882 884
883 885 $ (get-with-headers.py localhost:$HGPORT 'annotate/tip/primes.py?style=raw') \
884 886 > | sed "s/test@//" > a
885 887 $ echo "200 Script output follows" > b
886 888 $ echo "" >> b
887 889 $ echo "" >> b
888 890 $ hg annotate "primes.py" >> b
889 891 $ echo "" >> b
890 892 $ echo "" >> b
891 893 $ echo "" >> b
892 894 $ echo "" >> b
893 895 $ cmp b a || diff -u b a
894 896
895 897 hgweb filerevision, raw
896 898
897 899 $ (get-with-headers.py localhost:$HGPORT 'file/tip/primes.py?style=raw') \
898 900 > > a
899 901 $ echo "200 Script output follows" > b
900 902 $ echo "" >> b
901 903 $ hg cat primes.py >> b
902 904 $ cmp b a || diff -u b a
903 905
904 906 hgweb highlightcss friendly
905 907
906 908 $ get-with-headers.py localhost:$HGPORT 'highlightcss' > out
907 909 $ head -n 4 out
908 910 200 Script output follows
909 911
910 912 /* pygments_style = friendly */
911 913
912 914 $ rm out
913 915
914 916 errors encountered
915 917
916 918 $ cat errors.log
917 919 $ killdaemons.py
918 920
919 921 Change the pygments style
920 922
921 923 $ cat > .hg/hgrc <<EOF
922 924 > [web]
923 925 > pygments_style = fruity
924 926 > EOF
925 927
926 928 hg serve again
927 929
928 930 $ hg serve -p $HGPORT -d -n test --pid-file=hg.pid -A access.log -E errors.log
929 931 $ cat hg.pid >> $DAEMON_PIDS
930 932
931 933 hgweb highlightcss fruity
932 934
933 935 $ get-with-headers.py localhost:$HGPORT 'highlightcss' > out
934 936 $ head -n 4 out
935 937 200 Script output follows
936 938
937 939 /* pygments_style = fruity */
938 940
939 941 $ rm out
940 942
941 943 errors encountered
942 944
943 945 $ cat errors.log
944 946 $ killdaemons.py
945 947
946 948 only highlight C source files
947 949
948 950 $ cat > .hg/hgrc <<EOF
949 951 > [web]
950 952 > highlightfiles = **.c
951 953 > EOF
952 954
953 955 hg serve again
954 956
955 957 $ hg serve -p $HGPORT -d -n test --pid-file=hg.pid -A access.log -E errors.log
956 958 $ cat hg.pid >> $DAEMON_PIDS
957 959
958 960 test that fileset in highlightfiles works and primes.py is not highlighted
959 961
960 962 $ get-with-headers.py localhost:$HGPORT 'file/tip/primes.py' | grep 'id="l11"'
961 963 <span id="l11"> def sieve(ns):</span><a href="#l11"></a>
962 964
963 965 errors encountered
964 966
965 967 $ cat errors.log
966 968 $ cd ..
967 969 $ hg init eucjp
968 970 $ cd eucjp
969 971 >>> with open('eucjp.txt', 'wb') as fh:
970 972 ... # Japanese kanji "Kyo"
971 973 ... fh.write(u'\265\376'.encode('utf-8')) and None
972 974 $ hg ci -Ama
973 975 adding eucjp.txt
974 976 $ hgserveget () {
975 977 > killdaemons.py
976 978 > echo % HGENCODING="$1" hg serve
977 979 > HGENCODING="$1" hg serve -p $HGPORT -d -n test --pid-file=hg.pid -E errors.log
978 980 > cat hg.pid >> $DAEMON_PIDS
979 981 >
980 982 > echo % hgweb filerevision, html
981 983 > get-with-headers.py localhost:$HGPORT "file/tip/$2" \
982 984 > | grep '<div class="parity0 source">'
983 985 > echo % errors encountered
984 986 > cat errors.log
985 987 > }
986 988 $ hgserveget euc-jp eucjp.txt
987 989 % HGENCODING=euc-jp hg serve
988 990 % hgweb filerevision, html
989 991 % errors encountered
990 992 $ hgserveget utf-8 eucjp.txt
991 993 % HGENCODING=utf-8 hg serve
992 994 % hgweb filerevision, html
993 995 % errors encountered
994 996 $ hgserveget us-ascii eucjp.txt
995 997 % HGENCODING=us-ascii hg serve
996 998 % hgweb filerevision, html
997 999 % errors encountered
998 1000
999 1001 We attempt to highlight unknown files by default
1000 1002
1001 1003 $ killdaemons.py
1002 1004
1003 1005 $ cat > .hg/hgrc << EOF
1004 1006 > [web]
1005 1007 > highlightfiles = **
1006 1008 > EOF
1007 1009
1008 1010 $ cat > unknownfile << EOF
1009 1011 > #!$PYTHON
1010 1012 > def foo():
1011 1013 > pass
1012 1014 > EOF
1013 1015
1014 1016 $ hg add unknownfile
1015 1017 $ hg commit -m unknown unknownfile
1016 1018
1017 1019 $ hg serve -p $HGPORT -d -n test --pid-file=hg.pid
1018 1020 $ cat hg.pid >> $DAEMON_PIDS
1019 1021
1020 1022 $ get-with-headers.py localhost:$HGPORT 'file/tip/unknownfile' | grep l2
1021 1023 <span id="l2"><span class="k">def</span> <span class="nf">foo</span><span class="p">():</span></span><a href="#l2"></a>
1022 1024
1023 1025 We can prevent Pygments from falling back to a non filename-based
1024 1026 detection mode
1025 1027
1026 1028 $ cat > .hg/hgrc << EOF
1027 1029 > [web]
1028 1030 > highlightfiles = **
1029 1031 > highlightonlymatchfilename = true
1030 1032 > EOF
1031 1033
1032 1034 $ killdaemons.py
1033 1035 $ hg serve -p $HGPORT -d -n test --pid-file=hg.pid
1034 1036 $ cat hg.pid >> $DAEMON_PIDS
1035 1037 $ get-with-headers.py localhost:$HGPORT 'file/tip/unknownfile' | grep l2
1036 1038 <span id="l2">def foo():</span><a href="#l2"></a>
1037 1039
1038 1040 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now