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.
Passed
Push — master ( d45b0a...2e6b2b )
by dup
02:05
created

caches.FeedCache._calculate_minutes()   A

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 16
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nop 6
crap 1
1
#!/usr/bin/env python
2
# -*- coding: utf8 -*-
3
#
4
#  versions.py : checks releases and versions of programs through RSS
5
#                or Atom feeds and tells you
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 1
import codecs
25 1
import sys
26 1
import locale
27 1
import argparse
28 1
import os
29 1
import re
30 1
import errno
31 1
import time
32 1
import doctest
33 1
import feedparser
34 1
import yaml
35 1
import operator
36 1
import common
37
38
39 1
__author__ = "Olivier Delhomme <[email protected]>"
40
41
42 1
def open_and_truncate_file(filename):
43
    """
44
    Opens filename for writing truncating it to a zero length file
45
    and returns a python file object.
46
    """
47
48 1
    cache_file = codecs.open(filename, 'w', encoding='utf-8')
49 1
    cache_file.truncate(0)
50 1
    cache_file.flush()
51
52 1
    return cache_file
53
54
# End of open_and_truncate_file() function
55
56
57 1
class FileCache:
58
    """
59
    This class should help in managing cache files
60
    """
61
62 1
    cache_filename = ''
63 1
    cache_dict = {}  # Dictionnary of projects and their associated version
64
65 1
    def __init__(self, local_dir, filename):
66
        """
67
        Inits the class. 'local_dir' must be a directory where we want to
68
        store the cache file named 'filename'
69
        """
70
71 1
        self.cache_filename = os.path.join(local_dir, filename)
72 1
        self.cache_dict = {}
73 1
        self._read_cache_file()
74
75
    # End of __init__() function
76
77
78 1
    def _return_project_and_version_from_line(self, line):
79
        """
80
        Splits the line into a project and a version if possible (the line
81
        must contain a whitespace.
82
        """
83
84 1
        line = line.strip()
85
86 1
        if line.count(' ') > 0:
87 1
            (project, version) = line.split(' ', 1)
88
89
        elif line != '':
90
            project = line
91
            version = ''
92
93 1
        return (project, version)
0 ignored issues
show
introduced by
The variable version does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable project does not seem to be defined for all execution paths.
Loading history...
94
95
    # End of _return_project_and_version_from_line() function
96
97
98 1
    def _read_cache_file(self):
99
        """
100
        Reads the cache file and puts it into a dictionnary of project with
101
        their associated version
102
        """
103
104 1
        if os.path.isfile(self.cache_filename):
105 1
            cache_file = codecs.open(self.cache_filename, 'r', encoding='utf-8')
106
107 1
            for line in cache_file:
108 1
                (project, version) = self._return_project_and_version_from_line(line)
109 1
                self.cache_dict[project] = version
110
111 1
            cache_file.close()
112
113
    # End of _read_cache_file() function
114
115
116 1
    def write_cache_file(self):
117
        """
118
        Owerwrites dictionnary cache to the cache file
119
        """
120
121 1
        cache_file = open_and_truncate_file(self.cache_filename)
122
123 1
        for (project, version) in self.cache_dict.items():
124 1
            cache_file.write('%s %s\n' % (project, version))
125
126 1
        cache_file.close()
127
128
    # End of write_cache_file() function
129
130 1
    def print_if_newest_version(self, project, version, debug):
131
        """
132
        Prints the project and it's version if it is newer than the
133
        one in cache.
134
        """
135 1
        try:
136 1
            version_cache = self.cache_dict[project]
137 1
            common.print_debug(debug, u'\t\tIn cache: {}'.format(version_cache))
138
139 1
            if version != version_cache:
140 1
                common.print_project_version(project, version)
141
142 1
        except KeyError:
143 1
            common.print_project_version(project, version)
144
145
    # End of print_if_newest_version() function.
146
147
148 1
    def update_cache_dict(self, project, version, debug):
149
        """
150
        Updates cache dictionnary if needed. We always keep the latest version.
151
        """
152
153 1
        try:
154 1
            version_cache = self.cache_dict[project]
155 1
            common.print_debug(debug, u'\t\tUpdating cache with in cache: {} / new ? version {}'.format(version_cache, version))
156
157 1
            if version != version_cache:
158 1
                self.cache_dict[project] = version
159
160 1
        except KeyError:
161 1
            self.cache_dict[project] = version
162
163
    # End of update_cache_dict() function
164
165
166 1
    def print_cache_dict(self, sitename):
167
        """
168
        Pretty prints the cache dictionary as it is recorded in the files.
169
        """
170
171 1
        print(u'{}:'.format(sitename))
172
173
        # Gets project and version tuple sorted by project lowered while sorting
174 1
        for project, version in sorted(self.cache_dict.items(), key=lambda proj: proj[0].lower()):
175 1
            print(u'\t{} {}'.format(project, version))
176
177 1
        print('')
178
179
    # End of print_cache_dict() function
180
# End of FileCache class
181
182
183 1
class FeedCache:
184
185 1
    cache_filename = ''
186 1
    year = 2016
187 1
    month = 5
188 1
    day = 1
189 1
    hour = 0
190 1
    minute = 0
191 1
    date_minutes = 0
192
193
194 1
    def __init__(self, local_dir, filename):
195
        """
196
        Inits the class. 'local_dir' must be a directory where we want to
197
        store the cache file named 'filename'
198
        """
199
200 1
        self.cache_filename = os.path.join(local_dir, filename)
201 1
        self.read_cache_feed()
202
203
    # End of __init__() function
204
205
206 1
    def read_cache_feed(self):
207
        """
208
        Reads the cache file which should only contain one date on the
209
        first line
210
        """
211
212 1
        if os.path.isfile(self.cache_filename):
213 1
            cache_file = codecs.open(self.cache_filename, 'r', encoding='utf-8')
214 1
            (self.year, self.month, self.day, self.hour, self.minute) = cache_file.readline().strip().split(' ', 4)
215 1
            self.date_minutes = self._calculate_minutes(int(self.year), int(self.month), int(self.day), int(self.hour), int(self.minute))
216 1
            cache_file.close()
217
218
    # End of read_cache_feed() function
219
220
221 1
    def write_cache_feed(self):
222
        """
223
        Overwrites the cache file with values stored in this class
224
        """
225 1
        cache_file = open_and_truncate_file(self.cache_filename)
226
227 1
        cache_file.write('%s %s %s %s %s' % (self.year, self.month, self.day, self.hour, self.minute))
228
229 1
        cache_file.close()
230
231
    # End of write_cache_feed() function
232
233
234 1
    def update_cache_feed(self, date):
235
        """
236
        Updates the values stored in the class with the date which should
237
        be a time.struct_time
238
        """
239
240 1
        self.year = date.tm_year
241 1
        self.month = date.tm_mon
242 1
        self.day = date.tm_mday
243 1
        self.hour = date.tm_hour
244 1
        self.minute = date.tm_min
245 1
        self.date_minutes = self._calculate_minutes_from_date(date)
246
247
    # End of update_cache_feed() function
248
249
250 1
    def _calculate_minutes(self, year, mon, day, hour, mins):
251
        """
252
        Calculate a number of minutes with all parameters and returns
253
        this.
254
        >>> fc = FeedCache('localdir','filename')
255
        >>> fc._calculate_minutes(2016, 5, 1, 0, 0)
256
        1059827040
257
        """
258
259 1
        minutes = (year * 365 * 24 * 60) + \
260
                  (mon * 30 * 24 * 60) + \
261
                  (day * 24 * 60) + \
262
                  (hour * 60) + \
263
                  (mins)
264
265 1
        return minutes
266
267
    # End of _calculate_minutes() function
268
269
270 1
    def _calculate_minutes_from_date(self, date):
271
        """
272
        Transforms a date in a number of minutes to ease comparisons
273
        and returns this number of minutes
274
        """
275
276 1
        return self._calculate_minutes(date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour, date.tm_min)
277
278
    # End of _calculate_minutes() function
279
280
281 1
    def is_newer(self, date):
282
        """
283
        Tells wether "date" is newer than the one in the cache (returns True
284
        or not (returns False)
285
        """
286
287 1
        minutes = self._calculate_minutes_from_date(date)
288
289 1
        if minutes > self.date_minutes:
290 1
            return True
291
292
        else:
293 1
            return False
294
295
    # End of is_newer() function
296
# End of FeedCache class
297
298
299 1
def print_versions_from_cache(local_dir, cache_filename_list):
300
    """
301
    Prints all projects and their associated data from the cache
302
    """
303 1
    for cache_filename in cache_filename_list:
304 1
        site_cache = FileCache(local_dir, cache_filename)
305 1
        site_cache.print_cache_dict(cache_filename)
306
307
# End of print_versions_from_cache()
308