changeset 2db1df034e01 in tryton-tools:default
details: https://hg.tryton.org/tryton-tools?cmd=changeset;node=2db1df034e01
description:
Call flake8 as subprocess and add issue and force option
issue7213
review289371002
diffstat:
.flake8 | 2 +
reviewbot.py | 136 ++++++++++++++++++++++++----------------------------------
2 files changed, 58 insertions(+), 80 deletions(-)
diffs (213 lines):
diff -r 4ebb074021fb -r 2db1df034e01 .flake8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.flake8 Sat Feb 29 23:25:17 2020 +0100
@@ -0,0 +1,2 @@
+[flake8]
+ignore=E123,E124,E126,E128,W503
diff -r 4ebb074021fb -r 2db1df034e01 reviewbot.py
--- a/reviewbot.py Sun Feb 02 17:07:34 2020 +0100
+++ b/reviewbot.py Sat Feb 29 23:25:17 2020 +0100
@@ -1,23 +1,22 @@
#!/usr/bin/env python3
+import argparse
+import dbm
+import glob
+import json
+import os.path
import re
-import os.path
+import shutil
+import smtplib
+import subprocess
import tempfile
import urllib.parse
-import shutil
-import json
-import dbm
-import argparse
import xmlrpc.client
-import smtplib
-import subprocess
from email.mime.text import MIMEText
-import pep8
-import flake8.engine
import lxml.objectify
import requests
-TITLE_FORMAT = re.compile('^([A-Za-z_][\w\.-]+)( [0-9.]+)?:')
+TITLE_FORMAT = re.compile(r'^([A-Za-z_][\w\.-]+)( [0-9.]+)?:')
ISSUE_FORMAT = re.compile(
r'(?:#|\bissue|\bbug)\s*(?P<issue_id>[0-9]{4,})', re.I)
CODEREVIEW_URL = 'https://codereview.tryton.org'
@@ -28,9 +27,9 @@
TO = '[email protected]'
TO_ROUNDUP = '[email protected]'
COMMENT_TEMPLATE = """\
-%(url)s
-%(filename)s:%(lineno)s:
-%(text)s
+%(url)s/%(issue_id)s/diff/%(patchset)s/%%(path)s#newcode%%(row)s
+%%(path)s:%%(row)s:
+%%(text)s
"""
@@ -51,65 +50,6 @@
url_full, transport=SpecialTransport(), allow_none=True)
-class RietveltStyle(pep8.StyleGuide):
-
- def __init__(self, basename, *args, **kwargs):
- self.basename = basename
- super(RietveltStyle, self).__init__(*args, **kwargs)
- self.options.max_complexity = -1 # do not check code complexity
- self.options.builtins = [] # use the default builtins
- self.options.ignore = ('E122', 'E123', 'E124', 'E126', 'E128', 'W503')
- self.options.doctests = True
- self.options.include_in_doctest = ''
- self.options.exclude_from_doctest = ''
-
- def init_report(self, reporter=None):
- self.options.report = RietveltReport(self.basename, self.options)
- return self.options.report
-
-
-class RietveltReport(pep8.BaseReport):
-
- def __init__(self, basename, options):
- super(RietveltReport, self).__init__(options)
- self.basename_prefix = len(basename)
- self.errors = []
-
- def error(self, line_number, offset, text, check):
- code = super(RietveltReport, self).error(line_number, offset, text,
- check)
- if not code:
- return
- self.errors.append({
- 'text': text,
- 'lineno': line_number,
- 'filename': self.filename[self.basename_prefix + 1:],
- })
-
- def comments(self, issue_id, patchset, files=None):
- comments = []
- for error in self.errors:
- if files:
- if error['filename'] not in files:
- continue
- url = CODEREVIEW_URL + '/%s/diff/%s/%s#newcode%s' % (
- issue_id, patchset, error['filename'], error['lineno'])
- error['url'] = url
- comments.append(COMMENT_TEMPLATE % error)
- return '\n'.join(comments)
-
-
-def get_style(repository):
- # This is the way to initialize the pyflake checker
- parser, option_hooks = flake8.engine.get_parser()
- styleguide = flake8.engine.StyleGuide(
- styleguide=RietveltStyle(repository, parser=parser))
- options = styleguide.options
- for hook in option_hooks:
- hook(options)
- return styleguide
-
-
def install_repository(repo_url, branch=None):
repo_dir = tempfile.mkdtemp(prefix='reviewbot-')
if not repo_url:
@@ -128,9 +68,37 @@
+ '/'.join(['', 'download', 'issue%s_%s.diff' % (issue_id, patchset)]))
subprocess.check_call(
['hg', 'import', '-q', '--cwd', repo_dir, '--no-commit', patch_url])
+ # Run status to create new subrepo
+ subprocess.check_call(
+ ['hg', 'status', '-q', '--subrepos', '--cwd', repo_dir],
+ stdout=subprocess.DEVNULL)
+ # Add files to new subrepo
+ for subrepo in glob.glob(
+ os.path.join(repo_dir, '**', '.hg'), recursive=True):
+ subrepo = os.path.dirname(subrepo)
+ subprocess.check_call(['hg', 'add', '-q', '--cwd', subrepo])
return
+def check_repository(repo_dir, issue_id, patchset):
+ cwd = os.getcwd()
+ os.chdir(repo_dir)
+ format_ = COMMENT_TEMPLATE % {
+ 'url': CODEREVIEW_URL,
+ 'issue_id': issue_id,
+ 'patchset': patchset,
+ }
+ try:
+ return subprocess.check_output(
+ 'hg diff --subrepos | '
+ 'flake8 --format="%(format)s" --diff --exit-zero' % {
+ 'format': format_,
+ },
+ shell=True).decode('utf-8')
+ finally:
+ os.chdir(cwd)
+
+
def has_update(entry_id, patchset):
with dbm.open(DB_PATH, 'c') as db:
if entry_id not in db:
@@ -163,8 +131,7 @@
s.quit()
-def process_issue(session, roundup, issue_url, fromaddr):
- issue_id = urllib.parse.urlparse(issue_url).path.split('/')[1]
+def process_issue(session, roundup, issue_id, fromaddr, force=False):
issue_info = session.get(CODEREVIEW_URL
+ '/'.join(['', 'api', str(issue_id)]))
issue_info.raise_for_status()
@@ -180,7 +147,7 @@
patchset_info = json.loads(patchset_info.text)
# Test only last patchset has changed
- if not has_update(issue_id, patchset):
+ if not has_update(issue_id, patchset) and not force:
return
set_update(issue_id, patchset)
@@ -212,9 +179,7 @@
send_comments(fromaddr, owner, None, issue_id, subject,
'patch is not applicable')
return
- style_guide = get_style(repo_dir)
- report = style_guide.check_files([repo_dir])
- comment = report.comments(issue_id, patchset, patchset_info['files'])
+ comment = check_repository(repo_dir, issue_id, patchset)
if comment:
send_comments(fromaddr, owner, None, issue_id, subject, comment)
else:
@@ -276,10 +241,21 @@
parser.add_argument('email')
parser.add_argument('username')
parser.add_argument('password')
+ parser.add_argument('--issues', nargs='+')
+ parser.add_argument('--force', action='store_true')
args = parser.parse_args()
session = requests.Session()
roundup = get_roundup(ROUNDUP_URL, args.username, args.password)
- issues = fetch_issues(CODEREVIEW_URL + '/rss/all', session)
+ if not args.issues:
+
+ def extract_issue_id(element):
+ href = element.link.attrib['href']
+ return urllib.parse.urlparse(href).path.split('/')[1]
+ issues = list(map(
+ extract_issue_id,
+ fetch_issues(CODEREVIEW_URL + '/rss/all', session)))
+ else:
+ issues = args.issues
for issue in reversed(issues):
- process_issue(session, roundup, issue.link.attrib['href'], args.email)
+ process_issue(session, roundup, issue, args.email, force=args.force)