构建Python代码审核计划程序:保留审核信息

本系列第二部分中 ,您了解了如何从git日志中收集提交信息,以及如何向从项目成员列表中选择的随机开发者发送审阅请求。

在这一部分中,您将看到如何保存代码检查信息以在每次运行代码调度程序时进行后续操作。 您还将看到如何阅读电子邮件以检查审阅者是否已回复审阅请求。

入门

首先从教程系列的第二部分克隆源代码。

git clone https://github.com/royagasthyan/CodeReviewer-Part2 CodeReviewer

修改config.json文件,使其包含一些相关的电子邮件地址,并保留royagasthyan@gmail.com电子邮件地址。 这是因为git具有与特定电子邮件地址相关的提交,该代码是代码按预期执行所必需的。 修改schedule.py文件中的SMTP凭据:

FROM_EMAIL      = "your_email_address@gmail.com"
FROM_PWD        = "your_password"

导航到项目目录CodeReviewer并尝试在终端中执行以下命令。

python scheduler.py -n 20 -p "project_x"

它应该将代码审查请求发送给随机开发人员进行审查。

保留审查请求信息

要跟踪审阅请求信息,您需要将其保留在某处以供参考。 您可以选择将代码检查请求信息保留在何处。 它可以是任何数据库,也可以是文件。 为了本教程的缘故,我们将审阅请求信息保留在reviewer.json文件中。 每次运行调度程序时,它将检查信息文件以跟进尚未响应的审阅请求。

创建一个名为save_review_info的方法,该方法会将审阅请求信息保存在文件中。 在save_review_info方法内,创建一个带有审阅者,主题和唯一ID的info对象。

def save_review_info(reviewer, subject):
    info = {'reviewer':reviewer,'subject':subject,'id':str(uuid.uuid4()),'sendDate':str(datetime.date.today())}

对于唯一ID,请导入uuid Python模块。

import uuid

您还需要datetime Python模块来获取当前日期。 导入datetime Python模块。

import datetime

如果程序不存在,则需要在程序启动时初始化reviewer.json文件。

if not os.path.exists('reviewer.json'):
    with open('reviewer.json','w+') as outfile:
        json.dump([],outfile)

如果该文件不存在,则需要创建一个名为reviewer.json的文件,并用一个空的JSON数组填充该文件,如上面的代码所示。

每次发送审阅请求时,都会调用此方法。 因此,在save_review_info方法内部,以读取模式打开reviewer.json文件并读取内容。 将新的内容信息附加到现有内容中,然后将其写回到reviewer.json文件。 代码如下所示:

def save_review_info(reviewer, subject):
    info = {'reviewer':reviewer,'subject':subject,'id':str(uuid.uuid4()),'sendDate':str(datetime.date.today())}

    with open('reviewer.json','r') as infile:
        review_data = json.load(infile)

    review_data.append(info)

    with open('reviewer.json','w') as outfile:
        json.dump(review_data,outfile)

schedule_review_request方法内部,在发送代码审阅请求邮件之前,调用save_review_info方法以保存审阅信息。

def schedule_review_request(commits):
    date = time.strftime("%Y-%m-%d")
    
    for commit in commits:
        reviewer = select_reviewer(commit.Author, project_members)
        subject = date + " Code Review [commit:" + commit.Id + "]"
        body = "Hello '" + reviewer + "', you have been selected to review the code for commit\n"
        body += "done by '" + commit.Author + "'.\n"
        body += "\n"
        
        body += format_review_commit(commit)

        save_review_info(reviewer,subject);

        send_email(reviewer,subject,body)

保存以上更改并执行调度程序。 调度程序运行后,您应该能够在项目目录中查看带有代码审阅请求信息的reviewer.json文件。 外观如下:

[{
    "reviewer": "samson1987@gmail.com",
    "id": "8ca7da84-9da7-4a17-9843-be293ea8202c",
    "sendDate": "2017-02-24",
    "subject": "2017-02-24 Code Review [commit:16393106c944981f57b2b48a9180a33e217faacc]"
}, {
    "reviewer": "roshanjames@gmail.com",
    "id": "68765291-1891-4b50-886e-e30ab41a8810",
    "sendDate": "2017-02-24",
    "subject": "2017-02-24 Code Review [commit:04d11e21fb625215c5e672a93d955f4a176e16e4]"
}]

读取电子邮件数据

您已经收集了所有代码审查请求信息,并将其保存在reviewer.json文件中。 现在,每次运行调度程序时,您都需要检查您的邮件收件箱,以查看审阅者是否已响应代码审阅请求。 因此,首先您需要定义一种读取Gmail收件箱的方法。

创建一个名为read_email的方法,该方法需要将天数作为参数来检查收件箱。 您将利用imaplib Python模块读取电子邮件收件箱。 导入imaplib Python模块:

import imaplib

要使用imaplib模块阅读电子邮件,首先需要创建服务器。

email_server = imaplib.IMAP4_SSL(SERVER)

使用电子邮件地址和密码登录到服务器:

email_server.login(FROM_EMAIL,FROM_PWD)

登录后,选择收件箱以阅读电子邮件:

email_server.select('inbox')

自从发送代码审查请求以来,您将阅读过去n天的电子邮件。 导入timedelta Python模块。

import timedelta

创建电子邮件日期,如下所示:

email_date = datetime.date.today() - timedelta(days=num_days)
formatted_date = email_date.strftime('%d-%b-%Y')

使用formatted_date ,在电子邮件服务器中搜索电子邮件。

typ, data = email_server.search(None, '(SINCE "' + formatted_date + '")')

它将返回每封电子邮件的唯一ID,并使用唯一ID可以获取电子邮件详细信息。

ids = data[0]

id_list = ids.split()

first_email_id = int(id_list[0])
last_email_id = int(id_list[-1])

现在,您将使用first_email_idlast_email_id遍历电子邮件,并获取主题和电子邮件的“ last_email_id ”地址。

for i in range(last_email_id,first_email_id, -1):
    typ, data = email_server.fetch(i, '(RFC822)' )

data将包含电子邮件内容,因此请迭代数据部分并检查元组。 您将利用电子邮件Python模块提取详细信息。 因此,导入email Python模块。

import email

您可以提取电子邮件主题和“发件人”地址,如下所示:

for response_part in data:
    if isinstance(response_part, tuple):
        msg = email.message_from_string(response_part[1])
        print 'From: ' + msg['from']
        print '\n'
        print 'Subject: ' + msg['subject']
        print '\n'
        print '------------------------------------------------'

这是完整的read_email方法:

def read_email(num_days):
    try:
        email_server = imaplib.IMAP4_SSL(SERVER)
        email_server.login(FROM_EMAIL,FROM_PWD)
        email_server.select('inbox')

        email_date = datetime.date.today() - timedelta(days=num_days)
        formatted_date = email_date.strftime('%d-%b-%Y')

        typ, data = email_server.search(None, '(SINCE "' + formatted_date + '")')
        ids = data[0]

        id_list = ids.split()

        first_email_id = int(id_list[0])
        last_email_id = int(id_list[-1])

        for i in range(last_email_id,first_email_id, -1):
            typ, data = email_server.fetch(i, '(RFC822)' )

            for response_part in data:
                if isinstance(response_part, tuple):
                    msg = email.message_from_string(response_part[1])
                    print 'From: ' + msg['from']
                    print '\n'
                    print 'Subject: ' + msg['subject']
                    print '\n'
                    print '------------------------------------------------'

    except Exception, e:
        print str(e)

保存以上更改,然后尝试运行以上的read_email方法:

read_email(1)

它应该在终端上打印电子邮件主题和“发件人”地址。

从Gmail读取电子邮件

现在,让我们将“ email_info ”地址和主题收集到email_info列表中并返回数据。

email_info = []

而不是打印主题和“ email_info ”地址,而是将数据附加到email_info列表并返回email_info列表。

email_info.append({'From':msg['from'],'Subject':msg['subject'].replace("\r\n","")})

这是修改后的read_email方法:

def read_email(num_days):
    try:
        email_info = []
        email_server = imaplib.IMAP4_SSL(SERVER)
        email_server.login(FROM_EMAIL,FROM_PWD)
        email_server.select('inbox')

        email_date = datetime.date.today() - timedelta(days=num_days)
        formatted_date = email_date.strftime('%d-%b-%Y')

        typ, data = email_server.search(None, '(SINCE "' + formatted_date + '")')
        ids = data[0]

        id_list = ids.split()

        first_email_id = int(id_list[0])
        last_email_id = int(id_list[-1])

        for i in range(last_email_id,first_email_id, -1):
            typ, data = email_server.fetch(i, '(RFC822)' )

            for response_part in data:
                if isinstance(response_part, tuple):
                    msg = email.message_from_string(response_part[1])
                    email_info.append({'From':msg['from'],'Subject':msg['subject'].replace("\r\n","")})

    except Exception, e:
        print str(e)

    return email_info

添加日志记录以进行错误处理

错误处理是软件开发的重要方面。 在调试阶段跟踪错误非常有用。 如果您没有错误处理,那么很难跟踪错误。 由于您正在使用两种新方法,因此我认为现在是向调度程序代码添加错误处理的正确时机。

要开始进行错误处理,您将需要logging Python模块和RotatingFileHandler类。 如图所示导入它们:

import logging
from logging.handlers import RotatingFileHandler

获得所需的导入后,请如下所示初始化记录器:

logger = logging.getLogger("Code Review Log")
logger.setLevel(logging.INFO)

在上面的代码中,您初始化了记录器并将日志级别设置为INFO。

创建一个旋转文件日志处理程序,该日志处理程序将在每次日志文件达到最大大小时创建一个新文件。

logHandler = RotatingFileHandler('app.log',maxBytes=3000,backupCount=2)

logHandler附加到logger对象。

logger.addHandler(logHandler)

让我们添加错误记录器以在捕获异常时记录错误。 在read_email方法的异常部分中,添加以下代码:

logger.error(str(datetime.datetime.now()) + " - Error while reading mail : " + str(e) + "\n")
logger.exception(str(e))

第一行将错误消息以及当前日期和时间记录到日志文件中。 第二行将堆栈跟踪记录到错误中。

同样,您可以将错误处理添加到代码的主要部分。 这是带有错误处理的代码的外观:

try:
    commits = process_commits()

    if len(commits) == 0:
        print 'No commits found '
    else:
        schedule_review_request(commits)
except Exception,e:
    print 'Error occurred. Check log for details.'
    logger.error(str(datetime.datetime.now()) + " - Error while reading mail : " + str(e) + "\n")
    logger.exception(str(e))

包起来

在本系列的这一部分中,您将审阅请求信息搁置在reviewer.json文件中。 您还创建了一种读取电子邮件的方法。 您将使用这两个功能来跟踪本系列最后一部分中的代码审查请求。

此外,不要犹豫,看看我们在市场上有哪些可供出售和研究的东西 ,也不要犹豫,使用下面的提要来问任何问题并提供宝贵的反馈。

该教程的源代码可在GitHub上获得

请在下面的评论中告诉我们您的想法和建议。

翻译自: https://code.tutsplus.com/tutorials/building-a-python-code-review-scheduler-keeping-the-review-info--cms-28316

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值