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)

Reply via email to