Completed
Push — master ( 702f68...d96c91 )
by Gonzalo
9s
created

GitHubRepo   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Importance

Changes 11
Bugs 0 Features 0
Metric Value
c 11
b 0
f 0
dl 0
loc 153
rs 8.6
wmc 37

9 Methods

Rating   Name   Duplication   Size   Complexity  
A milestones() 0 3 1
A milestone() 0 14 4
A tags() 0 3 1
B tag() 0 15 5
A __init__() 0 8 1
A pr() 0 3 1
A str_to_date() 0 9 3
A is_merged() 0 12 2
F issues() 0 75 19
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
                    if issue in issues:
115
                        issues.remove(issue)
116
117
        # If until was provided, filter the issue
118
        if until:
119
            until_date = self.str_to_date(until)
120
            for issue in issues[:]:
121
                close_date = self.str_to_date(issue['closed_at'])
122
                if close_date > until_date:
123
                    if issue in issues:
124
                        issues.remove(issue)
125
126
        # If it is a pr check if it is merged or closed, removed closed ones
127
        for issue in issues[:]:
128
            pr = issue.get('pull_request', '')
129
130
            # Add label names inside additional key
131
            issue['loghub_label_names'] = [
132
                l['name'] for l in issue.get('labels')
133
            ]
134
135
            if pr:
136
                number = issue['number']
137
                if not self.is_merged(number):
138
                    if issue in issues:
139
                        issues.remove(issue)
140
141
                if branch:
142
                    # Get PR info and get base branch
143
                    pr_data = self.pr(number)
144
                    base_ref = pr_data['base']['ref']
145
                    if base_ref != branch:
146
                        if issue in issues:
147
                            issues.remove(issue)
148
149
        return issues
150
151
    def is_merged(self, pr):
152
        """
153
        Return wether a PR was merged, or if it was closed and discarded.
154
155
        https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged
156
        """
157
        merged = True
158
        try:
159
            self.repo('pulls')(str(pr))('merge').get()
160
        except Exception:
161
            merged = False
162
        return merged
163
164
    @staticmethod
165
    def str_to_date(string):
166
        """Convert ISO date string to datetime object."""
167
        parts = string.split('T')
168
        date_parts = parts[0]
169
        time_parts = parts[1][:-1]
170
        year, month, day = [int(i) for i in date_parts.split('-')]
171
        hour, minutes, seconds = [int(i) for i in time_parts.split(':')]
172
        return datetime.datetime(year, month, day, hour, minutes, seconds)
173