Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.80 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """
  3. Compare PDF reports pixel-wise.
  4.  
  5. When reportgen functional tests fail, you may want to see visually what
  6. exactly changed. To do that:
  7.  
  8. (1) set your changes aside, e.g.
  9.  
  10. git stash
  11.  
  12. (2) run bin/compare-reportgen-output to generate pristine PDFs in the
  13. reportgen-output directory
  14.  
  15. (3) move your changes back
  16.  
  17. git stash pop
  18.  
  19. (4) run bin/compare-reportgen-output to compare pristine PDFs with new ones
  20.  
  21. If you make further changes in your sandbox, to re-run the comparison do
  22.  
  23. (5) bin/compare-reportgen-output -r
  24.  
  25. To compare the current output with some older version (if you've got the PDFs
  26. for that older version pregenerated, run
  27.  
  28. bin/compare-reportgen-output oldver
  29.  
  30. To compare the outputs of two versions (if you've got PDFs for them), run
  31.  
  32. bin/compare-reportgen-output ver1 ver2
  33.  
  34. Use Git revspecs to specify versions.
  35.  
  36. To compare the outputs of two ReportLab versions (if you've got PDFs for them),
  37. run
  38.  
  39. bin/compare-reportgen-output reportlab-ver1 reportlab-ver2
  40.  
  41. Before you can do that you'll have to generate the PDFs for a particular
  42. ReportLab version, which is a bit complicated:
  43.  
  44. .tox/py27-latest/bin/pip install reportlab==rlver
  45. .tox/py27-latest/bin/python scripts/compare_reportgen_output.py
  46.  
  47. You'll need imagemagick and xdg-utils installed.
  48. """
  49.  
  50. # TODO:
  51. # - figure out how to check out a fresh copy of the sw to get pristine PDFs
  52. # of a non-current version (virtualenv or something)
  53.  
  54. from __future__ import print_function
  55.  
  56. import os
  57. import sys
  58. import glob
  59. import hashlib
  60. import tempfile
  61. import shutil
  62. import subprocess
  63. import filecmp
  64. import optparse
  65.  
  66. from six.moves import cStringIO as StringIO
  67.  
  68. try:
  69. # Python 3
  70. from html import escape
  71. from urllib.request import pathname2url
  72. except ImportError:
  73. # Python 2
  74. from cgi import escape
  75. from urllib import pathname2url
  76.  
  77. # Note: *no* ReportLab/PIL/lxml imports here since we fiddle with sys.path in
  78. # main()
  79.  
  80.  
  81. class EmptyReportMaker(object):
  82.  
  83. def start_pdf(self, one_pdf_file, another_pdf_file):
  84. pass
  85.  
  86. def start_page(self, one_png_file, another_png_file):
  87. pass
  88.  
  89. def end_page(self):
  90. pass
  91.  
  92. def different_page_counts(self, one_count, another_count):
  93. pass
  94.  
  95. def end_pdf(self):
  96. pass
  97.  
  98. def done(self, total_pdfs, differing_pdfs):
  99. pass
  100.  
  101.  
  102. class ReportMaker(EmptyReportMaker):
  103.  
  104. stylesheet = "summary > h2, summary > h3 { display: inline; cursor: pointer; }"
  105.  
  106. def __init__(self, title, output_dir=None, launch_browser=False):
  107. self.title = title
  108. self.output_dir = output_dir
  109. self.output_file = None
  110. self.out = None
  111. self.cur_pdf = None
  112. self.page_differences = 0
  113. self.total_page_differences = 0
  114. self.pending_pdf_end = False
  115. self.launch_browser = launch_browser
  116.  
  117. def start_writing(self):
  118. if self.output_dir is None:
  119. self.output_dir = tempfile.mkdtemp(prefix='cmp-reportgen-output-')
  120. try:
  121. os.makedirs(self.output_dir)
  122. except OSError:
  123. pass
  124. self.output_file = os.path.join(self.output_dir, 'index.html')
  125. self.out = open(self.output_file, 'w')
  126. print("creating %s" % self.output_file)
  127.  
  128. def write_header(self):
  129. print("<html><head><title>%s</title><style>%s</style></head>" %
  130. (escape(self.title), self.stylesheet), file=self.out)
  131. print("<body><h1>%s</h1>" %
  132. escape(self.title), file=self.out)
  133.  
  134. def write_stats(self, total_pdfs, differences):
  135. print("<h2>Stats</h2>", file=self.out)
  136. print("<p>Total PDFs compared: %d</p>" % total_pdfs, file=self.out)
  137. print("<p>PDFs with differences: %d</p>" % differences, file=self.out)
  138. print("<p>Total pages with differences: %d</p>"
  139. % self.total_page_differences, file=self.out)
  140.  
  141. def write_footer(self):
  142. print("</body></html>", file=self.out)
  143.  
  144. def urlize(self, filename):
  145. # XXX: there's a Linux vs Windows difference wrt the necessity to add
  146. # // after file:, but I don't care about Windows.
  147. return 'file://' + pathname2url(os.path.abspath(filename))
  148.  
  149. def write_pdf_title(self, one_pdf_file, another_pdf_file):
  150. if not self.out:
  151. self.start_writing()
  152. self.write_header()
  153. elif self.pending_pdf_end:
  154. self.write_pdf_end()
  155. one_title = os.path.basename(one_pdf_file)
  156. another_title = os.path.basename(another_pdf_file)
  157. one_url = self.urlize(one_pdf_file)
  158. another_url = self.urlize(another_pdf_file)
  159. print("<details open>", file=self.out)
  160. print("<summary>", file=self.out)
  161. print("<h2>%s</h2>" % escape(one_title), file=self.out)
  162. print("</summary>", file=self.out)
  163. print('<p>Before: <a href="%s">%s</a></p>' % (
  164. escape(one_url, True), escape(one_title)), file=self.out)
  165. print('<p>After: <a href="%s">%s</a></p>' % (
  166. escape(another_url, True), escape(another_title)), file=self.out)
  167. self.pending_pdf_end = True
  168.  
  169. def write_pdf_end(self):
  170. if self.page_differences:
  171. self.write_page_differences()
  172. print("</details>", file=self.out)
  173. self.pending_pdf_end = False
  174.  
  175. def write_page_thumbnail(self, one_png_file, another_png_file, diff_file):
  176. one_url = self.urlize(one_png_file)
  177. another_url = self.urlize(another_png_file)
  178. diff_url = self.urlize(diff_file)
  179. page_number = one_png_file[:-len('.png')].rsplit('-', 1)[-1]
  180. page_number = int(page_number) + 1
  181. w, h = 595, 842 # A4 PDF rendered to png at imagemagick's standard dpi
  182. scale_factor = 3
  183. size = ' width="%d" height="%d"' % (w // scale_factor, h // scale_factor)
  184. print("<details open>", file=self.out)
  185. print("<summary>", file=self.out)
  186. print("<h3>Page %d</h3>" % page_number, file=self.out)
  187. print("</summary>", file=self.out)
  188. print('<p><a href="%s"><img src="%s" %s alt="before" /></a>' % (
  189. escape(one_url, True), escape(one_url, True), size), file=self.out)
  190. print(' <a href="%s"><img src="%s" %s alt="after" /></a>' % (
  191. escape(another_url, True), escape(another_url, True), size), file=self.out)
  192. print(' <a href="%s"><img src="%s" %s alt="diff" /></a>' % (
  193. escape(diff_url, True), escape(diff_url, True), size), file=self.out)
  194. print('<br />Page %d: before, after, difference.</p>' % page_number, file=self.out)
  195. print("</details>", file=self.out)
  196. self.out.flush()
  197. self.page_differences += 1
  198. self.total_page_differences += 1
  199.  
  200. def write_page_counts(self, one_count, another_count):
  201. print('<p>Before: %d pages.</p>' % one_count, file=self.out)
  202. print('<p>After: %d pages.</p>' % another_count, file=self.out)
  203. self.out.flush()
  204.  
  205. def write_page_differences(self):
  206. print('<p>Differeces in %d page%s.</p>' % (
  207. self.page_differences, 's' if self.page_differences != 1 else ''), file=self.out)
  208. self.out.flush()
  209. self.page_differences = 0
  210.  
  211. def start_pdf(self, one_pdf_file, another_pdf_file):
  212. self.cur_pdf = one_pdf_file, another_pdf_file
  213.  
  214. def start_page(self, one_png_file, another_png_file):
  215. if self.cur_pdf:
  216. self.write_pdf_title(*self.cur_pdf)
  217. self.cur_pdf = None
  218. diff_file = os.path.join(self.output_dir,
  219. os.path.basename(one_png_file))
  220. self.write_page_thumbnail(one_png_file, another_png_file, diff_file)
  221. return diff_file
  222.  
  223. def different_page_counts(self, one_count, another_count):
  224. if self.cur_pdf:
  225. self.write_pdf_title(*self.cur_pdf)
  226. self.cur_pdf = None
  227. self.write_page_counts(one_count, another_count)
  228.  
  229. def done(self, total_pdfs, differing_pdfs):
  230. if self.out:
  231. if self.pending_pdf_end:
  232. self.write_pdf_end()
  233. self.write_stats(total_pdfs, differing_pdfs)
  234. self.write_footer()
  235. self.out.close()
  236. self.out = None
  237. if self.launch_browser:
  238. print("Launching %s in a browser..." % self.output_file)
  239. subprocess.call(["xdg-open", self.output_file])
  240. print("Please 'rm -r %s' when done" % self.output_dir)
  241. else:
  242. print("Output in %s" % self.output_dir)
  243.  
  244.  
  245. class Job(object):
  246.  
  247. def __init__(self, name=None):
  248. self.name = name
  249.  
  250. def __call__(self):
  251. # possibly returns JobError()
  252. pass
  253.  
  254.  
  255. class JobError(object):
  256.  
  257. def __init__(self, message):
  258. self.message = message
  259.  
  260.  
  261. class GeneratePdfJob(Job):
  262.  
  263. def __init__(self, input_file, output_file):
  264. Job.__init__(self, 'building %s' % output_file)
  265. self.input_file = input_file
  266. self.output_file = output_file
  267.  
  268. def __call__(self):
  269. from ivija.reportgen import engine, zLOG
  270. input_file = self.input_file
  271. output_file = self.output_file
  272. cwd = os.getcwd()
  273. temp_dir = tempfile.mkdtemp(prefix='cmp-reportgen-output-')
  274. errs = StringIO()
  275. success = False
  276. try:
  277. input_file = os.path.abspath(input_file)
  278. output_file = os.path.abspath(output_file)
  279. os.chdir(os.path.dirname(input_file))
  280. engine.run_as_command = True # hack :(
  281. zLOG._set_log_dest(errs)
  282. rg = engine.ReportGenerator(temp_dir, '.', input_file,
  283. date='2007-06-22',
  284. output_callback=lambda filename:
  285. shutil.move(filename, output_file))
  286. rg.generate()
  287. success = os.path.exists(output_file)
  288. finally:
  289. os.chdir(cwd)
  290. shutil.rmtree(temp_dir)
  291. if not success:
  292. return JobError("could not build %s\n\n%s" % (output_file, errs.getvalue()))
  293.  
  294.  
  295. class ConvertPdfToPngJob(Job):
  296.  
  297. def __init__(self, pdf_file):
  298. Job.__init__(self, "converting %s to PNG files" % pdf_file)
  299. self.pdf_file = pdf_file
  300.  
  301. def __call__(self):
  302. png_file = os.path.splitext(self.pdf_file)[0] + '.png'
  303. subprocess.call(["convert", self.pdf_file, "-alpha", "remove", png_file])
  304.  
  305.  
  306. class CompareImagesJob(Job):
  307.  
  308. def __init__(self, one_file, another_file, diff_file):
  309. Job.__init__(self)
  310. self.one_file = one_file
  311. self.another_file = another_file
  312. self.diff_file = diff_file
  313.  
  314. def __call__(self):
  315. one_file = self.one_file
  316. another_file = self.another_file
  317. diff_file = self.diff_file
  318. subprocess.call(["compare", one_file, another_file, diff_file])
  319.  
  320.  
  321. class TheGreatPdfComparator(object):
  322.  
  323. output_cache = 'reportgen-output'
  324. verbose = False
  325. quiet = False
  326. report = EmptyReportMaker()
  327.  
  328. def chatter(self, msg):
  329. if self.verbose:
  330. print(msg)
  331.  
  332. def info(self, msg):
  333. if not self.quiet:
  334. print(msg)
  335.  
  336. def warn(self, msg):
  337. print(msg, file=sys.stderr)
  338.  
  339. def error(self, msg):
  340. print(msg, file=sys.stderr)
  341.  
  342. def find_input_files(self):
  343. return sorted(glob.glob('src/ivija/reportgen/ftests/*.xml'))
  344.  
  345. def determine_reportlab_version(self):
  346. import reportlab
  347. return reportlab.Version
  348.  
  349. def perform_jobs(self, jobs):
  350. if not jobs:
  351. return
  352. from multiprocessing import Pool
  353. pool = Pool()
  354. outstanding = []
  355. for job in jobs:
  356. result = pool.apply_async(job)
  357. outstanding.append((job, result))
  358. pool.close()
  359. for job, result in outstanding:
  360. self._perform_job(job, result)
  361. pool.join()
  362.  
  363. def _perform_job(self, job, result=None):
  364. if job.name:
  365. self.info(job.name)
  366. if result is not None:
  367. retval = result.wait()
  368. else:
  369. retval = job()
  370. if isinstance(retval, JobError):
  371. self.error(retval.message)
  372.  
  373. def pipe(self, cmd):
  374. with subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout as p:
  375. return p.read().strip().decode('UTF-8')
  376.  
  377. def resolve_version(self, revspec):
  378. return self.pipe(['git', 'describe', '--match', '^$', '--always', revspec])
  379.  
  380. def resolve_branch(self, revspec):
  381. branch = self.pipe(['git', 'name-rev', '--name-only', '--refs=refs/heads/*', revspec])
  382. return branch.partition('~')[0]
  383.  
  384. def determine_version(self):
  385. return self.pipe(['git', 'describe', '--match', '^$', '--always', '--dirty'])
  386.  
  387. def determine_branch(self):
  388. return self.pipe(['git', 'symbolic-ref', '--short', 'HEAD'])
  389.  
  390. def produce_a_pdf(self, input_file, output_file):
  391. self._perform_job(GeneratePdfJob(input_file, output_file))
  392.  
  393. def list_known_reportlab_versions(self):
  394. return sorted(n[len('reportlab-'):]
  395. for n in os.listdir(self.output_cache)
  396. if n.startswith('reportlab-'))
  397.  
  398. def make_output_dir_name(self, ivija_branch=None, reportlab_version=None, ivija_version=None):
  399. if reportlab_version is None:
  400. reportlab_version = self.determine_reportlab_version()
  401. if ivija_version is None:
  402. ivija_version = self.determine_version()
  403. ivija_branch = self.determine_branch()
  404. if ivija_branch is None:
  405. ivija_branch = self.resolve_branch(ivija_version) or self.determine_branch()
  406. return os.path.join(self.output_cache,
  407. 'reportlab-%s' % reportlab_version,
  408. 'ivija-%s' % ivija_version if ivija_branch is None
  409. else 'ivija-%s-%s' % (ivija_branch, ivija_version))
  410.  
  411. def make_output_file_name(self, input_file):
  412. basename = os.path.basename(input_file)
  413. name = os.path.splitext(basename)[0]
  414. output_dir = self.make_output_dir_name()
  415. return os.path.join(output_dir, name + '.pdf')
  416.  
  417. def wipe_current_pdf_cache(self):
  418. output_dir = self.make_output_dir_name()
  419. try:
  420. shutil.rmtree(output_dir)
  421. except OSError:
  422. pass
  423.  
  424. def populate_pdf_cache(self):
  425. self.info("building PDFs for rev %s with ReportLab %s"
  426. % (self.determine_version(),
  427. self.determine_reportlab_version()))
  428. pdf_jobs = []
  429. png_jobs = []
  430. for input_file in self.find_input_files():
  431. output_file = self.make_output_file_name(input_file)
  432. if not os.path.exists(output_file):
  433. try:
  434. os.makedirs(os.path.dirname(output_file))
  435. except OSError:
  436. pass
  437. pdf_jobs.append(GeneratePdfJob(input_file, output_file))
  438. png_jobs.append(ConvertPdfToPngJob(output_file))
  439. self.perform_jobs(pdf_jobs)
  440. self.perform_jobs(png_jobs)
  441.  
  442. def generate_pngs(self, pdf_file):
  443. self._perform_job(ConvertPdfToPngJob(pdf_file))
  444.  
  445. def glob_pages(self, pdf_file):
  446. dirname = os.path.dirname(pdf_file)
  447. prefix = os.path.splitext(os.path.basename(pdf_file))[0] + '-'
  448. suffix = '.png'
  449. # I apologize for writing this
  450. return [
  451. os.path.join(dirname, fn)
  452. for fn in sorted((
  453. fn for fn in os.listdir(dirname)
  454. if fn.startswith(prefix) and fn.endswith(suffix)
  455. and fn[len(prefix):-len(suffix)].isdigit()
  456. ), key=lambda fn: int(fn[len(prefix):-len(suffix)]))
  457. ]
  458.  
  459. def get_pngs(self, pdf_file):
  460. all_files = self.glob_pages(pdf_file)
  461. if not all_files:
  462. self.generate_pngs(pdf_file)
  463. all_files = self.glob_pages(pdf_file)
  464. return all_files
  465.  
  466. def compare_two_pdfs(self, one_file, another_file):
  467. self.chatter("comparing %s and %s" % (one_file, another_file))
  468. self.report.start_pdf(one_file, another_file)
  469. pages_of_one_file = self.get_pngs(one_file)
  470. pages_of_another_file = self.get_pngs(another_file)
  471. diffs = False
  472. jobs = []
  473. for (one, another) in zip(pages_of_one_file, pages_of_another_file):
  474. diffs = self.compare_two_pngs(one, another, jobs) or diffs
  475. self.perform_jobs(jobs)
  476. if len(pages_of_one_file) != len(pages_of_another_file):
  477. diffs = True
  478. self.report.different_page_counts(len(pages_of_one_file), len(pages_of_another_file))
  479. self.warn('%s has %d pages, but %s has %d pages' % (one_file, len(pages_of_one_file),
  480. another_file, len(pages_of_another_file)))
  481. self.report.end_pdf()
  482. return diffs
  483.  
  484. def pixels_of(self, filename):
  485. from PIL import Image
  486. return Image.open(filename).tobytes()
  487.  
  488. def pixel_hash_of(self, filename):
  489. hashfile = filename + ".pixelhash"
  490. if os.path.exists(hashfile):
  491. with open(hashfile) as fp:
  492. return fp.read().strip()
  493. pixeldata = self.pixels_of(filename)
  494. hashvalue = hashlib.sha256(pixeldata).hexdigest()
  495. with open(hashfile, 'w') as fp:
  496. print(hashvalue, file=fp)
  497. return hashvalue
  498.  
  499. def compare_two_pngs(self, one_file, another_file, jobs=None):
  500. self.chatter("comparing %s and %s" % (one_file, another_file))
  501. if filecmp.cmp(one_file, another_file):
  502. # files are bitwise identical
  503. return False
  504. # make sure it's not some irrelevant metadata
  505. if self.pixel_hash_of(one_file) == self.pixel_hash_of(another_file):
  506. self.chatter("%s and %s differ in metadata only" % (one_file, another_file))
  507. return False
  508. self.warn("%s and %s differ" % (one_file, another_file))
  509. diff_file = self.report.start_page(one_file, another_file)
  510. if not os.path.exists(diff_file):
  511. # NB: this helps only if the user passes -o to reuse the output
  512. # directory
  513. job = CompareImagesJob(one_file, another_file, diff_file)
  514. if jobs is not None:
  515. jobs.append(job)
  516. else:
  517. self._perform_job(job)
  518. self.report.end_page()
  519. return True
  520.  
  521. def find_all_pdfs(self, dir):
  522. return sorted(fn for fn in os.listdir(dir) if fn.endswith('.pdf'))
  523.  
  524. def compare_all_pdfs(self, one_dir, another_dir):
  525. files_in_one_dir = self.find_all_pdfs(one_dir)
  526. files_in_another_dir = self.find_all_pdfs(another_dir)
  527. if files_in_one_dir != files_in_another_dir:
  528. self.warn('%s and %s have different PDF files'
  529. % (one_dir, another_dir))
  530. only_in_one_dir = sorted(set(files_in_one_dir) - set(files_in_another_dir))
  531. if only_in_one_dir:
  532. self.warn('only in %s: %s' % (one_dir, ' '.join(only_in_one_dir)))
  533. only_in_another_dir = sorted(set(files_in_another_dir) - set(files_in_one_dir))
  534. if only_in_another_dir:
  535. self.warn('only in %s: %s' % (another_dir, ' '.join(only_in_another_dir)))
  536. diffs = 0
  537. for filename in files_in_one_dir:
  538. one_pdf = os.path.join(one_dir, filename)
  539. another_pdf = os.path.join(another_dir, filename)
  540. diffs += self.compare_two_pdfs(one_pdf, another_pdf)
  541. self.info("%d PDFs compared, %d PDFs differ" % (len(files_in_one_dir), diffs))
  542. self.report.done(len(files_in_one_dir), diffs)
  543.  
  544. def populate_pdf_cache_for_other_ver(self, ver):
  545. if ver == self.determine_version():
  546. return self.populate_pdf_cache()
  547. cache_dir = self.make_output_dir_name(ivija_version=ver)
  548. # XXX: hard to do, not implemented yet
  549. self.error("no cache of version %s (%s)" % (ver, cache_dir))
  550. self.info("please check out a fresh copy of changeset %s and run this script to produce pristine PDF files to compare against" % ver)
  551. self.info("e.g. git stash; git checkout %s; bin/compare-reportgen-output -r; git checkout master; git stash pop" % ver)
  552. self.info("then try again")
  553. self.info("or specify some other version to compare against (--list shows available)")
  554. sys.exit(1)
  555.  
  556.  
  557. def main():
  558. parser = optparse.OptionParser(
  559. "usage: %prog [options] [revno|rl-ver|dir] [revno|rl-ver|dir]")
  560. parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
  561. help='print names of every pair of files when comparing',
  562. default=False)
  563. parser.add_option('-q', '--quiet', action='store_true', dest='quiet',
  564. help='suppress informative messages',
  565. default=False)
  566. parser.add_option('--list', action='store_true',
  567. help='list cached versions')
  568. parser.add_option('-o', '--outdir',
  569. help='output directory for the report')
  570. parser.add_option('-l', '--launch-browser', action='store_true',
  571. help='launch browser if there are differences (default)',
  572. dest='launch_browser', default=True)
  573. parser.add_option('--no-launch-browser', action='store_false',
  574. dest='launch_browser')
  575. parser.add_option('-r', '--regenerate', action='store_true',
  576. dest='regenerate', default=False,
  577. help='discard cached files, generate new ones')
  578. parser.add_option('--path', action='append', default=[],
  579. help="extra Python path to insert in front")
  580. parser.add_option('--ivija-version', dest='ivija_version_override',
  581. help='override ivija version to be used by default')
  582. parser.add_option('--ivija-branch', dest='ivija_branch_override',
  583. help='override ivija branch to be used by default')
  584. opts, args = parser.parse_args()
  585. sys.path[0:0] = opts.path
  586.  
  587. tcmp = TheGreatPdfComparator()
  588.  
  589. if opts.verbose:
  590. tcmp.verbose = True
  591. tcmp.quiet = False
  592. elif opts.quiet:
  593. tcmp.verbose = False
  594. tcmp.quiet = True
  595.  
  596. if opts.ivija_version_override:
  597. cur_ver = opts.ivija_version_override
  598. else:
  599. cur_ver = tcmp.determine_version()
  600.  
  601. if opts.list:
  602. my_rl_version = tcmp.determine_reportlab_version()
  603. had_alt_versions = False
  604. for rl_version in tcmp.list_known_reportlab_versions():
  605. directory = os.path.dirname(tcmp.make_output_dir_name(reportlab_version=rl_version))
  606. pending = "cached PDFs in %s" % directory
  607. if rl_version == my_rl_version:
  608. pending += " (current reportlab version)"
  609. else:
  610. had_alt_versions = True
  611. for fn in sorted(os.listdir(directory),
  612. key=lambda fn: os.stat(os.path.join(directory, fn)).st_mtime):
  613. if fn.startswith('ivija-'):
  614. branch_and_ver = fn[len('ivija-'):]
  615. if (rl_version == my_rl_version
  616. and branch_and_ver.endswith('-' + cur_ver)):
  617. cur = "* "
  618. else:
  619. cur = " "
  620. if pending:
  621. print(pending)
  622. pending = None
  623. print(cur + branch_and_ver)
  624. if pending:
  625. print("no " + pending)
  626. if had_alt_versions:
  627. print("To compare across reportlab versions, pass a full directory name like this:")
  628. print(" reportlab-output/reportlab-<rlver>/ivija-<ver>")
  629. return
  630. elif len(args) == 0:
  631. if not cur_ver.endswith('-dirty'):
  632. if opts.regenerate:
  633. tcmp.wipe_current_pdf_cache()
  634. tcmp.populate_pdf_cache()
  635. tcmp.info("pristine checkout: nothing to compare")
  636. return
  637. old_ver = cur_ver[:-len('-dirty')]
  638. tcmp.chatter("trying to compare %s to %s" % (cur_ver, old_ver))
  639. one_dir = tcmp.make_output_dir_name(ivija_version=old_ver)
  640. if not os.path.exists(one_dir):
  641. tcmp.populate_pdf_cache_for_other_ver(old_ver)
  642. return
  643. elif len(args) == 1:
  644. old_ver = args[0]
  645. elif len(args) == 2:
  646. old_ver, cur_ver = args
  647. else:
  648. tcmp.info("too many arguments")
  649. sys.exit(1)
  650.  
  651. try:
  652. subprocess.call("convert -version > /dev/null", shell=True)
  653. except OSError:
  654. tcmp.info("please install imagemagick")
  655. sys.exit(1)
  656.  
  657. if opts.regenerate:
  658. tcmp.wipe_current_pdf_cache()
  659.  
  660. if os.path.exists(old_ver):
  661. one_dir = old_ver
  662. old_title = one_dir
  663. elif old_ver.startswith('reportlab-'):
  664. rl_ver = old_ver[len('reportlab-'):]
  665. old_title = old_ver
  666. one_dir = tcmp.make_output_dir_name(ivija_branch=opts.ivija_branch_override,
  667. ivija_version=opts.ivija_version_override,
  668. reportlab_version=rl_ver)
  669. if not os.path.exists(one_dir):
  670. tcmp.error("no cache of %s (%s)" % (old_ver, one_dir))
  671. sys.exit(1)
  672. else:
  673. old_title = old_ver
  674. old_branch = tcmp.resolve_branch(old_ver)
  675. old_ver = tcmp.resolve_version(old_ver)
  676. one_dir = tcmp.make_output_dir_name(ivija_branch=old_branch,
  677. ivija_version=old_ver)
  678. if not os.path.exists(one_dir):
  679. tcmp.populate_pdf_cache_for_other_ver(old_ver)
  680.  
  681. if os.path.exists(cur_ver):
  682. another_dir = cur_ver
  683. new_title = another_dir
  684. elif cur_ver.startswith('reportlab-'):
  685. # XXX: this is very asymmetric compared to
  686. # old_ver.startswith('reportlab-')! rethink this.
  687. rl_ver = cur_ver[len('reportlab-'):]
  688. new_title = cur_ver
  689. another_dir = tcmp.make_output_dir_name(ivija_branch=opts.ivija_branch_override,
  690. ivija_version=opts.ivija_version_override,
  691. reportlab_version=rl_ver)
  692. if not os.path.exists(another_dir):
  693. tcmp.error("no cache of %s (%s)" % (cur_ver, another_dir))
  694. sys.exit(1)
  695. else:
  696. new_title = cur_ver
  697. if cur_ver != tcmp.determine_version():
  698. cur_branch = tcmp.resolve_branch(cur_ver)
  699. cur_ver = tcmp.resolve_version(cur_ver)
  700. else:
  701. cur_branch = None
  702. another_dir = tcmp.make_output_dir_name(ivija_branch=cur_branch,
  703. ivija_version=cur_ver)
  704. if not os.path.exists(another_dir):
  705. tcmp.populate_pdf_cache_for_other_ver(cur_ver)
  706.  
  707. title = "Comparing reportgen %s and %s" % (old_title, new_title)
  708. tcmp.report = ReportMaker(title, launch_browser=opts.launch_browser,
  709. output_dir=opts.outdir)
  710. tcmp.info("comparing %s and %s" % (one_dir, another_dir))
  711. if os.path.isfile(one_dir) and os.path.isfile(another_dir):
  712. tcmp.report.done(1, tcmp.compare_two_pdfs(one_dir, another_dir))
  713. else:
  714. tcmp.compare_all_pdfs(one_dir, another_dir)
  715.  
  716.  
  717. if __name__ == "__main__":
  718. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement