Python: If/else statement parsing dictionary content

时间:2015-12-10 01:14:17

标签: python git github

I have some code that analyzes pull request in GitHub based on certain conditions and then prints output to the console.

The if/else statement below evaluates the set of files associated with a pull request and if any file in that set has a 'status' of 'added' or 'removed', output True/False once.

if 'added' in (data.status for data in repo.pull_request(prs.number).files()) or 'removed' in (data.status for data in repo.pull_request(prs.number).files()):
   print('Added or Deleted Files: True')
else:
   print('Added or Deleted Files: False')

I'm trying to achieve this same result with a second if/else statement that's contained in a for loop pertaining to the number of files within each commit of a pull request, but it is evaluating and outputting each individual file within a commit as opposed to the set of files associate with all commits for a pull request.

for pullrequestcommits in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(pullrequestcommits.sha).as_dict()

    if len([file['filename'] for file in files_in_commit['files']]) <= 10:
       print("Commits in pr less than/equal 10 files: True")
    else:
       print("Commit in pr less than/equal 10 files: False")

In the output, I get the desired result for the evaluation of added or deleted files as it is evaluating the set files and then outputs True or False based on the evaluation of the set. I'm trying to achieve the same result with commits, but it's outputting True/False based on each individual commit and not analyzing the set of files within the commits. For Title: update1, it should output Commits in pr less than/equal 10 files: True once and for Title: update 2, it should output Commits in pr less than/equal 10 files: False just once, as one of the commits in the pull request has more than 10 files.

Current output:

Title:  update 1
Added or Deleted Files: True
Commits in pr less than/equal 10 files: True
Commits in pr less than/equal 10 files: True

Title:  update 2
Added or Deleted Files: True
Commits in pr less than/equal 10 files: True
Commit in pr less than/equal 10 files: False
Commits in pr less than/equal 10 files: True

Desired output:

Title:  update 1
Added or Deleted Files: True
Commits in pr less than/equal 10 files: True

Title:  update 2
Added or Deleted Files: True
Commit in pr less than/equal 10 files: False

Code in full:

for prs in repo.pull_requests():
        getlabels = repo.issue(prs.number).as_dict()

        if 'ready-to-merge' in [getlabels['name'] for getlabels in getlabels['labels']] and 'Validation Succeeded' in [getlabels['name'] for getlabels in getlabels['labels']]:
            changes = repo.pull_request(prs.number).as_dict()
            print('Title: ', changes['title'])

            if 'added' in (data.status for data in repo.pull_request(prs.number).files()) or 'removed' in (data.status for data in repo.pull_request(prs.number).files()):
                print('Added or Deleted Files: True')
            else:
                print('Added or Deleted Files: False'

            for pullrequestcommits in repo.pull_request(prs.number).commits():
                files_in_commit = repo.commit(pullrequestcommits.sha).as_dict()

                if len([file['filename'] for file in files_in_commit['files']]) <= 10:
                    print("Commits in pr less than/equal 10 files: True")
                else:
                    print("Commit in pr less than/equal 10 files: False")

2 个答案:

答案 0 :(得分:0)

The PullRequest object has a .files() method, which should help you count the files regardless of which commit they're in.


This

if 'added' in (data.status for data in repo.pull_request(prs.number).files()) or 'removed' in (data.status for data in repo.pull_request(prs.number).files()):

can be (using any)

if any(data.status in ['added', 'removed'] for data in repo.pull_request(prs.number).files()):

You don't need to get the file names to count the files, so this

if len([file['filename'] for file in files_in_commit['files']]) <= 10:

should be

if len(files_in_commit['files']) <= 10:

or if files_in_commit['files'] is an iterable and not a list, make it a list first:

if len(list(files_in_commit['files'])) <= 10:

If you want the number of things that satify a condition, you can write a sum:

if sum(file.status in ['added', 'removed'] for file in commit) <= 10:

or, less preferable, make a list filtered by an if, and find its length:

if len([file for file in commit if file.status in ['added', 'removed']]) <= 10:

It's better to define a function for your criteria:

def added_or_removed(file):
    return file.status in ['added', 'removed']

if sum(added_or_removed(file) for file in commit) <= 10:

For this:

for pullrequestcommits in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(pullrequestcommits.sha).as_dict()

    if len([file['filename'] for file in files_in_commit['files']]) <= 10:
        print("Commits in pr less than/equal 10 files: True")
    else:
        print("Commit in pr less than/equal 10 files: False")

you are taking each pullrequestcommits (named wrong; should be pullrequestcommit, singular) and checking whether it satisfies your condition (total changed files <= 10).

With corrected variable names and corrections above:

for commit in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(commit.sha).as_dict()['files']

    if len(files_in_commit) <= 10:
        print("Commits in pr less than/equal 10 files: True")
    else:
        print("Commits in pr less than/equal 10 files: False")

Define the conditions as functions:

def added_or_removed(file):
    return file.status in ['added', 'removed']

def added_or_removed_at_most_ten_files(files):
    return sum(added_or_removed(file) for file in files) <= 10

def changed_at_most_ten_files(files):
    return len(files) <= 10

To check if any single commit has greater than ten files:

no_commit_has_more_than_ten_files = True
for commit in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(commit.sha).as_dict()['files']

    if not changed_at_most_ten_files(files_in_commit):
        no_commit_has_more_than_ten_files = False
        break

if no_commit_has_more_than_ten_files:
    print("Commits in pr less than/equal 10 files: True")
else:
    print("Commits in pr less than/equal 10 files: False")

This can be rewritten as an any or an all:

def changed_at_most_ten_files(repo, commit):
    return len(repo.commit(commit.sha).as_dict()['files']) <= 10

commits = repo.pull_request(prs.number).commits()
result = all(changed_at_most_ten_files(repo, commit) for commit in commits):
print("Commits in pr less than/equal 10 files:", result)

To check if the commit itself changes at most ten files, you would have to be careful that no file is counted twice. To do that, you would usually use a set(), add the files to the set, and check the length at the end. You have to pass in something that would uniquely identify each file, and which can be hashed. In this case, the file path would work.

答案 1 :(得分:0)

Improved solution

Sounds like you need to sum up all file counts per PR:

files_in_pr = 0
for pullrequestcommits in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(pullrequestcommits.sha).as_dict()
    files_in_pr += len([file['filename'] for file in files_in_commit['files']]) 
    # This should do. No?
    # files_in_pr += len(files_in_commit['files']]) 

 if files_in_pr <= 10:
     print("Commits in pr less than/equal 10 files: True")
 else:
     print("Commit in pr less than/equal 10 files: False")

Your code:

for pullrequestcommits in repo.pull_request(prs.number).commits():
    files_in_commit = repo.commit(pullrequestcommits.sha).as_dict()

    if len([file['filename'] for file in files_in_commit['files']]) <= 10:
        print("Commits in pr less than/equal 10 files: True")
    else:
        print("Commit in pr less than/equal 10 files: False")

Counts the number of files per commit but prints out how many commits it found.

First attempt

It looks like, this is closer to what you intent to do:

number_of_commits = len(repo.commit(pullrequestcommits.sha).as_dict())
if number_of_commits <= 10:
    print("Commits in pr less than/equal 10 files: True")
else:
    print("Commit in pr less than/equal 10 files: False")
相关问题