calibre/setup/check.py
Kovid Goyal 05d9209053 Also check RapydScript files when running python setup.py check
Use sha1 hashes for the check cache instead of mtimes. More reliable
and should work with the travis cache as well, if you decide to run
check on travis
2016-06-25 11:26:23 +05:30

125 lines
4.0 KiB
Python

#!/usr/bin/env python2
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys, os, json, subprocess, errno, hashlib
from setup import Command, build_cache_dir
import __builtin__
def set_builtins(builtins):
for x in builtins:
if not hasattr(__builtin__, x):
setattr(__builtin__, x, True)
yield x
class Message:
def __init__(self, filename, lineno, msg):
self.filename, self.lineno, self.msg = filename, lineno, msg
def __str__(self):
return '%s:%s: %s' % (self.filename, self.lineno, self.msg)
class Check(Command):
description = 'Check for errors in the calibre source code'
CACHE = 'check.json'
def get_files(self):
for x in os.walk(self.j(self.SRC, 'calibre')):
for f in x[-1]:
y = self.j(x[0], f)
if x[0].endswith('calibre/ebooks/markdown'):
continue
if (f.endswith('.py') and f not in (
'feedparser.py', 'markdown.py') and
'prs500/driver.py' not in y) and not f.endswith('_ui.py'):
yield y
if f.endswith('.coffee'):
yield y
for x in os.walk(self.j(self.d(self.SRC), 'recipes')):
for f in x[-1]:
f = self.j(x[0], f)
if f.endswith('.recipe'):
yield f
for x in os.walk(self.j(self.SRC, 'pyj')):
for f in x[-1]:
f = self.j(x[0], f)
if f.endswith('.pyj'):
yield f
if self.has_changelog_check:
yield self.j(self.d(self.SRC), 'Changelog.yaml')
def read_file(self, f):
with open(f, 'rb') as f:
return f.read()
def file_hash(self, f):
try:
return self.fhash_cache[f]
except KeyError:
self.fhash_cache[f] = ans = hashlib.sha1(self.read_file(f)).hexdigest()
return ans
def is_cache_valid(self, f, cache):
return cache.get(f) == self.file_hash(f)
def save_cache(self, cache):
with open(self.j(build_cache_dir(), self.CACHE), 'wb') as f:
json.dump(cache, f)
def file_has_errors(self, f):
ext = os.path.splitext(f)[1]
if ext in {'.py', '.recipe'}:
p = subprocess.Popen(['flake8-python2', '--ignore=E,W', f])
return p.wait() != 0
elif ext == '.pyj':
p = subprocess.Popen(['rapydscript', 'lint', f])
return p.wait() != 0
elif ext == '.yaml':
sys.path.insert(0, self.wn_path)
import whats_new
whats_new.render_changelog(self.j(self.d(self.SRC), 'Changelog.yaml'))
sys.path.remove(self.wn_path)
else:
from calibre.utils.serve_coffee import check_coffeescript
try:
check_coffeescript(f)
except:
return True
def run(self, opts):
self.fhash_cache = {}
cache = {}
self.wn_path = os.path.expanduser('~/work/srv/main/static')
self.has_changelog_check = os.path.exists(self.wn_path)
try:
cache = json.load(open(self.j(build_cache_dir(), self.CACHE), 'rb'))
except EnvironmentError as err:
if err.errno != errno.ENOENT:
raise
try:
for f in self.get_files():
if self.is_cache_valid(f, cache):
continue
self.info('\tChecking', f)
if self.file_has_errors(f):
subprocess.call(['gvim', '-S',
self.j(self.SRC, '../session.vim'), '-f', f])
raise SystemExit(1)
cache[f] = self.file_hash(f)
finally:
self.save_cache(cache)
def report_errors(self, errors):
for err in errors:
self.info('\t\t', str(err))