Completed
Push — master ( 210122...f0fc46 )
by Gonzalo
9s
created

GitHubRepo.pr()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Copyright (c) The Spyder Development Team
4
#
5
# Licensed under the terms of the MIT License
6
# (See LICENSE.txt for details)
7
# -----------------------------------------------------------------------------
8
"""Github repo wrapper."""
9
10
from __future__ import print_function
11
12
# Standard library imports
13
import datetime
14
import sys
15
16
# Local imports
17
from loghub.external.github import GitHub
18
19
20
class GitHubRepo(object):
21
    """Github repository wrapper."""
22
23
    def __init__(self, username=None, password=None, token=None, repo=None):
24
        """Github repository wrapper."""
25
        self.gh = GitHub(
26
            username=username,
27
            password=password,
28
            access_token=token, )
29
        repo_organization, repo_name = repo.split('/')
30
        self.repo = self.gh.repos(repo_organization)(repo_name)
31
32
    def tags(self):
33
        """Return all tags."""
34
        return self.repo('git')('refs')('tags').get()
35
36
    def tag(self, tag_name):
37
        """Get tag information."""
38
        refs = self.repo('git')('refs')('tags').get()
39
        sha = -1
40
        for ref in refs:
41
            ref_name = 'refs/tags/{tag}'.format(tag=tag_name)
42
            if 'object' in ref and ref['ref'] == ref_name:
43
                sha = ref['object']['sha']
44
                break
45
46
        if sha == -1:
47
            print("You didn't pass a valid tag name!")
48
            sys.exit(1)
49
50
        return self.repo('git')('tags')(sha).get()
51
52
    def milestones(self):
53
        """Return all milestones."""
54
        return self.repo.milestones.get(state='all')
55
56
    def milestone(self, milestone_title):
57
        """Return milestone with given title."""
58
        milestones = self.milestones()
59
        milestone_number = -1
60
        for milestone in milestones:
61
            if milestone['title'] == milestone_title:
62
                milestone_number = milestone['number']
63
                break
64
65
        if milestone_number == -1:
66
            print("You didn't pass a valid milestone name!")
67
            sys.exit(1)
68
69
        return milestone
70
71
    def pr(self, pr_number):
72
        """Get PR information."""
73
        return self.repo('pulls')(str(pr_number)).get()
74
75
    def issues(self,
76
               milestone=None,
77
               state=None,
78
               assignee=None,
79
               creator=None,
80
               mentioned=None,
81
               labels=None,
82
               sort=None,
83
               direction=None,
84
               since=None,
85
               until=None,
86
               branch=None):
87
        """Return Issues and Pull Requests."""
88
        page = 1
89
        issues = []
90
        while True:
91
            result = self.repo.issues.get(page=page,
92
                                          per_page=100,
93
                                          milestone=milestone,
94
                                          state=state,
95
                                          assignee=assignee,
96
                                          creator=creator,
97
                                          mentioned=mentioned,
98
                                          labels=labels,
99
                                          sort=sort,
100
                                          direction=direction,
101
                                          since=since)
102
            if len(result) > 0:
103
                issues += result
104
                page = page + 1
105
            else:
106
                break
107
108
        # If since was provided, filter the issue
109
        if since:
110
            since_date = self.str_to_date(since)
111
            for issue in issues[:]:
112
                close_date = self.str_to_date(issue['closed_at'])
113
                if close_date < since_date:
114
                    issues.remove(issue)
115
116
        # If until was provided, filter the issue
117
        if until:
118
            until_date = self.str_to_date(until)
119
            for issue in issues[:]:
120
                close_date = self.str_to_date(issue['closed_at'])
121
                if close_date > until_date:
122
                    issues.remove(issue)
123
124
        # If it is a pr check if it is merged or closed, removed closed ones
125
        for issue in issues[:]:
126
            pr = issue.get('pull_request', '')
127
128
            # Add label names inside additional key
129
            issue['_label_names'] = [l['name'] for l in issue.get('labels')]
130
131
            if pr:
132
                number = issue['number']
133
                if not self.is_merged(number):
134
                    issues.remove(issue)
135
136
                if branch:
137
                    # Get PR info and get base branch
138
                    pr_data = self.pr(number)
139
                    base_ref = pr_data['base']['ref']
140
                    if base_ref != branch:
141
                        issues.remove(issue)
142
143
        return issues
144
145
    def is_merged(self, pr):
146
        """
147
        Return wether a PR was merged, or if it was closed and discarded.
148
149
        https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged
150
        """
151
        merged = True
152
        try:
153
            self.repo('pulls')(str(pr))('merge').get()
154
        except Exception:
155
            merged = False
156
        return merged
157
158
    @staticmethod
159
    def str_to_date(string):
160
        """Convert ISO date string to datetime object."""
161
        parts = string.split('T')
162
        date_parts = parts[0]
163
        time_parts = parts[1][:-1]
164
        year, month, day = [int(i) for i in date_parts.split('-')]
165
        hour, minutes, seconds = [int(i) for i in time_parts.split(':')]
166
        return datetime.datetime(year, month, day, hour, minutes, seconds)
167