GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch master (f4cf2c)
by dup
02:17
created

versions.byproject   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 246
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 88
dl 0
loc 246
rs 10
c 0
b 0
f 0
wmc 29

9 Functions

Rating   Name   Duplication   Size   Complexity  
A check_versions() 0 10 2
A is_one_entry_field_value_egal_to_last_check() 0 14 2
B get_latest_release_by_title() 0 36 7
A is_entry_last_checked() 0 13 1
A get_values_from_project() 0 30 5
A format_project_feed_filename() 0 12 1
A sort_feed_list() 0 14 3
A get_releases_filtering_feed() 0 25 3
A check_versions_feeds_by_projects() 0 29 5
1
#!/usr/bin/env python
2
# -*- coding: utf8 -*-
3
#
4
#  byproject.py : related to sites that gives an RSS/Atom feed for
5
#                 each project (such as github)
6
#
7
#  (C) Copyright 2016 - 2018 Olivier Delhomme
8
#  e-mail : [email protected]
9
#
10
#  This program is free software; you can redistribute it and/or modify
11
#  it under the terms of the GNU General Public License as published by
12
#  the Free Software Foundation; either version 3, or (at your option)
13
#  any later version.
14
#
15
#  This program is distributed in the hope that it will be useful,
16
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
#  GNU General Public License for more details.
19
#
20
#  You should have received a copy of the GNU General Public License
21
#  along with this program; if not, write to the Free Software Foundation,
22
#  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
#
24
import os
25
import operator
26
import re
27
import caches
28
import common
29
30
31
def format_project_feed_filename(feed_filename, name):
32
    """
33
    Returns a valid filename formatted based on feed_filename (the site name)
34
    and name (the name of the project).
35
    """
36
37
    (root, ext) = os.path.splitext(feed_filename)
38
    norm_name = name.replace('/', '_')
39
40
    filename = "{}_{}{}".format(root, norm_name, ext)
41
42
    return filename
43
44
# End of format_project_feed_filename() function
45
46
47
def is_entry_last_checked(entry):
48
    """
49
    Returns true if entry is equal to last checked and
50
    false otherwise.
51
    >>> is_entry_last_checked('last checked')
52
    True
53
    >>> is_entry_last_checked('')
54
    False
55
    >>> is_entry_last_checked('latest')
56
    False
57
    """
58
59
    return entry == 'last checked'
60
61
# End of is_entry_last_checked() function
62
63
64
def get_values_from_project(project):
65
    """
66
    Gets the values of 'regex' and 'name' keys if found and
67
    returns a tuple (valued, name, regex, entry)
68
    >>> project = {'name': 'version', 'regex': 'v([\d\.]+)\s*:.*', 'entry': 'entry'}
69
    >>> get_values_from_project(project)
70
    (True, 'version', 'v([\\\\d\\\\.]+)\\\\s*:.*', 'entry')
71
    >>> project = {'name': 'version'}
72
    >>> get_values_from_project(project)
73
    (False, 'version', '', '')
74
    """
75
76
    regex = ''
77
    entry = ''
78
    name = project
79
    valued = False
80
81
    if type(project) is dict:
82
        if 'name' in project:
83
            name = project['name']
84
85
        if 'regex' in project:
86
            regex = project['regex']
87
            valued = True
88
89
        if 'entry' in project:
90
            entry = project['entry']
91
            valued = True
92
93
    return (valued, name, regex, entry)
94
95
# End of get_values_from_project() function
96
97
98
def sort_feed_list(feed_list, feed):
99
    """
100
    Sorts the feed list with the right attribute which depends on the feed.
101
    sort is reversed because feed_list is build by inserting ahead when
102
    parsing the feed from the most recent to the oldest entry.
103
    Returns a sorted list (by date) the first entry is the newest one.
104
    """
105
106
    if feed.entries[0]:
107
        (published_date, field_name) = common.get_entry_published_date(feed.entries[0])
108
        if field_name != '':
109
            feed_list = sorted(feed_list, key=operator.attrgetter(field_name), reverse=True)
110
111
    return feed_list
112
113
# End of sort_feed_list() function
114
115
116
def get_releases_filtering_feed(debug, local_dir, filename, feed, last_checked):
117
    """
118
    Filters the feed and returns a list of releases with one
119
    or more elements
120
    """
121
122
    feed_list = []
123
124
    if last_checked:
125
        feed_info = caches.FeedCache(local_dir, filename)
126
        feed_info.read_cache_feed()
127
        feed_list = common.make_list_of_newer_feeds(feed, feed_info, debug)
128
        feed_list = sort_feed_list(feed_list, feed)
129
130
        # Updating feed_info with the latest parsed feed entry date
131
        if len(feed_list) >= 1:
132
            (published_date, field_name) = common.get_entry_published_date(feed_list[0])
133
            feed_info.update_cache_feed(published_date)
134
135
        feed_info.write_cache_feed()
136
137
    else:
138
        feed_list.insert(0, feed.entries[0])
139
140
    return feed_list
141
142
# End of get_releases_filtering_feed() function
143
144
145
def is_one_entry_field_value_egal_to_last_check(site_entry, entry):
146
    """
147
    Returns True if the value of 'entry' field in the yaml file
148
    is last_checked and False otherwise.
149
    It checks firstly the 'entry' field for the whole site and if not
150
    found it then checks it for the project itself.
151
    """
152
153
    if is_entry_last_checked(site_entry):
154
        last_checked = True
155
    else:
156
        last_checked = is_entry_last_checked(entry)
157
158
    return last_checked
159
160
# End of get_relevant_entry_field_value() function
161
162
163
def get_latest_release_by_title(project, debug, feed_url, local_dir, feed_filename, site_entry):
164
    """
165
    Gets the latest release or the releases between the last checked time of
166
    a program on a site of type 'byproject'.
167
    project must be a string that represents the project (user/repository in
168
    github for instance).
169
    Returns a tuple which contains the name of the project, a list of versions
170
    and a boolean that indicates if we checked by last checked time (True) or
171
    by release (False).
172
    """
173
174
    feed_list = []
175
176
    (valued, name, regex, entry) = get_values_from_project(project)
177
178
    last_checked = is_one_entry_field_value_egal_to_last_check(site_entry, entry)
179
    filename = format_project_feed_filename(feed_filename, name)
180
    url = feed_url.format(name)
181
    feed = common.get_feed_entries_from_url(url)
182
183
    if feed is not None and len(feed.entries) > 0:
184
        feed_list = get_releases_filtering_feed(debug, local_dir, filename, feed, last_checked)
185
186
        if valued and regex != '':
187
            # Here we match the whole list against the regex and replace the
188
            # title's entry of the result of that match upon success.
189
            for feed_entry in feed_list:
190
                res = re.match(regex, feed_entry.title)
191
                # Here we should make a new list with the matched entries and leave the other ones
192
                if res:
193
                    feed_entry.title = res.group(1)
194
                common.print_debug(debug, u'\tname: {}\n\tversion: {}\n\tregex: {} : {}'.format(name, feed_entry.title, regex, res))
195
196
            common.print_debug(debug, u'\tProject {}: {}'.format(name, feed.entries[0].title))
197
198
    return (name, feed_list, last_checked)
199
200
# End of get_latest_release_by_title() function
201
202
203
def check_versions_feeds_by_projects(project_list, local_dir, debug, feed_url, cache_filename, feed_filename, site_entry):
204
    """
205
    Checks project's versions on feed_url if any are defined in the yaml
206
    file under the specified tag that got the project_list passed as an argument.
207
    """
208
209
    site_cache = caches.FileCache(local_dir, cache_filename)
210
211
    for project in project_list:
212
        (name, feed_list, last_checked) = get_latest_release_by_title(project, debug, feed_url, local_dir, feed_filename, site_entry)
213
214
        if len(feed_list) >= 1:
215
            # Updating the cache with the latest version (the first feed entry)
216
            version = feed_list[0].title
217
218
            if not last_checked:
219
                # printing only for latest release as last checked is
220
                # already filtered and to be printed entirely
221
                site_cache.print_if_newest_version(name, version, debug)
222
                # we already printed this.
223
                del feed_list[0]
224
225
            site_cache.update_cache_dict(name, version, debug)
226
227
        # Printing all entries in the list.
228
        for feed_entry in feed_list:
229
            common.print_project_version(name, feed_entry.title)
230
231
    site_cache.write_cache_file()
232
233
# End of check_versions_feeds_by_projects() function
234
235
236
def check_versions(versions_conf, byproject_site_list):
237
    """
238
    Checks version by checking each project's feed.
239
    """
240
241
    for site_name in byproject_site_list:
242
        common.print_debug(versions_conf.options.debug, u'Checking {} projects'.format(site_name))
243
        (project_list, project_url, cache_filename, site_entry) = versions_conf.get_infos_for_site(site_name)
244
        feed_filename = u'{}.feed'.format(site_name)
245
        check_versions_feeds_by_projects(project_list, versions_conf.local_dir, versions_conf.options.debug, project_url, cache_filename, feed_filename, site_entry)
246
247
# End of check_versions() function.
248