Subversion Repositories basico

Rev

Rev 365 | Rev 375 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
340 t00mlabs 1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3
"""
4
# File: srv_utils.py
5
# Author: Tomás Vírseda
6
# License: GPL v3
7
# Description: Generic functions service
8
"""
9
 
374 t00mlabs 10
import os
340 t00mlabs 11
import re
12
import sys
355 t00mlabs 13
import json
357 t00mlabs 14
from html import escape
356 t00mlabs 15
from stat import ST_SIZE
340 t00mlabs 16
import subprocess
17
import tarfile
18
import zipfile
19
import shutil
20
import requests
21
import webbrowser
22
import feedparser
23
from datetime import datetime
359 t00mlabs 24
from gi.repository import Gio
355 t00mlabs 25
from basico.core.mod_env import GPATH, LPATH, FILE
340 t00mlabs 26
from basico.core.mod_srv import Service
27
 
28
class Utils(Service):
29
    """
30
    Missing class docstring (missing-docstring)
31
    """
32
 
33
    def initialize(self):
34
        """
35
        Missing method docstring (missing-docstring)
36
        """
37
        self.get_services()
38
 
39
 
356 t00mlabs 40
    def get_services(self):
41
        """
42
        Missing method docstring (missing-docstring)
43
        """
374 t00mlabs 44
        # ~ self.srvdtb = self.get_service('DB')
45
        pass
359 t00mlabs 46
 
374 t00mlabs 47
 
356 t00mlabs 48
    def get_file_metadata(self, path):
49
        self.log.debug("Getting metadata from: %s", path)
50
        metadata = {}
357 t00mlabs 51
        metadata['Title'] = escape(self.get_file_name_with_ext(path))
52
        metadata['Basename'] = escape(self.get_file_basename(path))
53
        metadata['Extension'] = escape(self.get_file_extension(path))
356 t00mlabs 54
        metadata['Size'] = self.get_file_size(path)
359 t00mlabs 55
        metadata['Mimetype'] = escape(self.get_file_mimetype(path))
56
        metadata['Description'] = escape(self.get_file_description(metadata['Mimetype']))
357 t00mlabs 57
        metadata['Doctype'] = escape(self.get_file_doctype(metadata['Mimetype']))
356 t00mlabs 58
        return metadata
340 t00mlabs 59
 
359 t00mlabs 60
 
356 t00mlabs 61
    def get_file_size(self, path):
62
        # Get size in bytes
63
        size = os.stat(path)[ST_SIZE]
64
        self.log.debug("\tSize: %s", str(size))
65
        return size
340 t00mlabs 66
 
356 t00mlabs 67
 
68
    def get_file_extension(self, path):
69
        # Get extension
70
        rest, extension = os.path.splitext(path)
71
        ext = (extension[1:]).lower()
358 t00mlabs 72
        ext = ext.strip()
73
        if len(ext) > 0:
356 t00mlabs 74
            return '%s' % ext
75
        else:
76
            return '#noext#'
77
 
78
 
79
    def get_file_basename(self, path):
80
        # Get basename
81
        rest, extension = os.path.splitext(path)
82
        basename = os.path.basename(rest)
83
        self.log.debug("\tBasename: %s", basename)
84
        return basename
85
 
86
 
87
    def get_file_name_with_ext(self, path):
88
        # Filename
89
        basename = self.get_file_basename(path)
90
        extension = self.get_file_extension(path)
91
        if extension == '#noext#':
358 t00mlabs 92
            title = basename
93
        else:
94
            title = '%s.%s' % (basename, extension)
356 t00mlabs 95
        self.log.debug("\tTitle: %s", title)
96
        return title
97
 
374 t00mlabs 98
 
359 t00mlabs 99
    def get_file_mimetype(self, path):
100
        mimetype, val = Gio.content_type_guess('filename=%s' % path, data=None)
101
        return mimetype
356 t00mlabs 102
 
103
 
104
    def get_file_doctype(self, mimetype):
105
        mtype = mimetype[:mimetype.rfind('/')]
106
        doctype = mtype.title()
107
        self.log.debug("\tDoctype: %s", doctype)
108
        return doctype
109
 
110
 
359 t00mlabs 111
    def get_file_description(self, mimetype):
112
        description = Gio.content_type_get_description(mimetype)
113
        return description
355 t00mlabs 114
 
115
 
353 t00mlabs 116
    def get_disk_usage(self, path):
117
        """
118
        Get disk usage for a given path
119
        """
120
        return shutil.disk_usage(path)
121
 
122
 
123
    def get_disk_usage_fraction(self, path):
124
        """
125
        Get disk usage as a fraction for using with Gtk.Progressbar)
126
        """
127
        total, used, free = self.get_disk_usage(path)
128
        return used/total
129
 
356 t00mlabs 130
 
131
    def get_kilobytes(self, integer_bytes):
132
        kilo, bites = divmod(int(abs(integer_bytes)), 1_024)
133
        # ~ self.log.debug("%d bytes -> %d Kb", integer_bytes, kilo)
134
        return kilo
135
 
136
 
137
    def get_megabytes(self, integer_bytes):
138
        kilo = self.get_kilobytes(integer_bytes)
139
        mega, kilo = divmod(kilo, 1_024)
140
        # ~ self.log.debug("%d bytes -> %d Mb", integer_bytes, mega)
141
        return mega
142
 
143
 
144
    def get_gigabytes(self, integer_bytes):
145
        mega = self.get_megabytes(integer_bytes)
146
        giga, mega = divmod(mega, 1_024)
147
        # ~ self.log.debug("%d bytes -> %d Gb", integer_bytes, giga)
148
        return giga
149
 
150
 
151
    def get_human_sizes(self, integer_bytes):
152
        if integer_bytes < 1024:
153
            return "%d bytes" % integer_bytes
154
        elif integer_bytes > 1024 and integer_bytes < (1024*1024):
155
            return "%d Kb" % self.get_kilobytes(integer_bytes)
156
        elif integer_bytes > 1024*1024 and integer_bytes < (1024*1024*1024):
157
            return "%d Mb" % self.get_megabytes(integer_bytes)
158
        elif integer_bytes > 1024*1024*1024 and integer_bytes < (1024*1024*1024*1024):
159
            return "%d Gb" % self.get_gigabytes(integer_bytes)
160
 
374 t00mlabs 161
 
353 t00mlabs 162
    def get_disk_usage_human(self, path):
163
        """
164
        Get disk usage as a fraction for using with Gtk.Progressbar)
165
        Some bytes borrowed from:
166
        https://github.com/juancarlospaco/anglerfish/blob/master/anglerfish/bytes2human.py
374 t00mlabs 167
        """
353 t00mlabs 168
        total, used, free = self.get_disk_usage(path)
356 t00mlabs 169
        tgb = self.get_gigabytes(total)
170
        ugb = self.get_gigabytes(used)
171
        fgb = self.get_gigabytes(total-used)
353 t00mlabs 172
        humansize = "Using %dGb of %dGb (Free space: %dGb)" % (int(ugb), int(tgb), int(fgb))
173
        return humansize
174
 
340 t00mlabs 175
    def timestamp(self):
176
        """
177
        Missing method docstring (missing-docstring)
178
        """
179
        now = datetime.now()
180
        timestamp = "%4d%02d%02d_%02d%02d%02d" % (now.year, now.month, now.day, now.hour, now.minute, now.second)
181
 
182
        return timestamp
183
 
184
 
185
    def get_datetime(self, timestamp):
186
        """
187
        Missing method docstring (missing-docstring)
188
        """
189
        adate = datetime.strptime(timestamp, "%Y%m%d_%H%M%S")
190
        return adate
191
 
192
 
193
    def get_human_date_from_timestamp(self, timestamp=None):
194
        """
195
        Missing method docstring (missing-docstring)
196
        """
197
        if timestamp is None:
198
            timestamp = self.timestamp()
374 t00mlabs 199
 
340 t00mlabs 200
        adate = self.get_datetime(timestamp)
201
        return "%s" % adate.strftime("%Y/%m/%d %H:%M")
202
 
203
 
204
    def get_excel_date(self, timestamp):
374 t00mlabs 205
        timestamp = timestamp.replace('-', '/')
340 t00mlabs 206
        timestamp = timestamp.replace('T', ' ')
207
        adate = datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S")
208
        excel_date = "%s" % adate.strftime("%d/%m/%Y")
209
        return excel_date
210
 
211
 
212
    def fuzzy_date_from_timestamp(self, timestamp):
213
        """
214
        Missing method docstring (missing-docstring)
215
        """
216
        d1 = self.get_datetime(timestamp)
217
        d2 = datetime.now()
218
        rdate = d2 - d1 # DateTimeDelta
219
        if rdate.days > 0:
220
            if rdate.days <= 31:
221
                return "%d days ago" % int(rdate.days)
222
 
223
            if rdate.days > 31 and rdate.days < 365:
224
                return "%d months ago" % int((rdate.days/31))
225
 
226
            if rdate.days >= 365:
227
                return "%d years ago" % int((rdate.days/365))
228
 
229
        hours = rdate.seconds / 3600
230
        if int(hours) > 0:
231
            return "%d hours ago" % int(hours)
232
 
233
        minutes = rdate.seconds / 60
234
        if int(minutes) > 0:
235
            return "%d minutes ago" % int(minutes)
236
 
237
        if int(rdate.seconds) > 0:
238
            return "%d seconds ago" % int(rdate.seconds)
239
 
240
        if int(rdate.seconds) == 0:
241
            return "Right now"
242
 
243
 
244
    def browse(self, url):
245
        """
246
        Missing method docstring (missing-docstring)
247
        """
248
        if sys.platform in ['linux', 'linux2']:
249
            browser = webbrowser.get('firefox')
250
        elif sys.platform == 'win32':
251
            browser = webbrowser.get('windows-default')
252
 
253
        browser.open_new_tab(url)
254
 
255
 
256
    def which(self, program):
257
        """
258
        Missing method docstring (missing-docstring)
259
        """
260
        if sys.platform == 'win32':
261
            program = program + '.exe'
262
 
263
        def is_exe(fpath):
264
            """
265
            Missing method docstring (missing-docstring)
266
            """
267
            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
268
 
269
        fpath, fname = os.path.split(program)
270
        if fpath:
271
            if is_exe(program):
272
                return program
273
        else:
274
            for path in os.environ["PATH"].split(os.pathsep):
275
                path = path.strip('"')
276
                exe_file = os.path.join(path, program)
277
                if is_exe(exe_file):
278
                    return exe_file
279
 
280
        return None
281
 
282
 
283
    def install_geckodriver(self):
284
        """
285
        Install Gecko Driver
286
        """
287
        GECKODRIVER_LINUX = GPATH['DRIVERS'] + 'geckodriver'
288
        GECKODRIVER_WIN32 = GPATH['DRIVERS'] + 'geckodriver.exe'
289
        GECKO_INSTALL_DIR = LPATH['DRIVERS']
290
 
291
        if sys.platform == 'linux':
292
            shutil.copy(GECKODRIVER_LINUX, GECKO_INSTALL_DIR)
293
        else:
294
            shutil.copy(GECKODRIVER_WIN32, GECKO_INSTALL_DIR)
295
        self.log.debug("Gecko driver installed to %s" % GECKO_INSTALL_DIR)
296
 
297
 
298
    def download(self, prgname, source, target):
299
        """
300
        Missing method docstring (missing-docstring)
301
        """
302
        try:
303
            self.log.debug("Downloading %s from: %s" % (prgname, source))
304
            response = requests.get(source, stream=True)
305
            with open(target, 'wb') as out_file:
306
                shutil.copyfileobj(response.raw, out_file)
307
            del response
308
            self.log.debug("%s downloaded to %s" % (prgname, target))
309
            return True
310
        except Exception as error:
311
            self.log.error(error)
312
            return False
313
 
314
 
315
    def extract(self, filename, target_path, protocol):
316
        """
317
        Missing method docstring (missing-docstring)
318
        """
319
        self.log.debug("Extracting %s to %s using protocol %s" % (filename, target_path, protocol))
320
        if protocol in ['tar.gz', 'bz2']:
321
            try:
322
                tar = tarfile.open(filename, "r:*")
323
                tar.extractall(target_path)
324
                tar.close()
325
                self.log.debug("Extracted successfully")
326
                return True
327
            except Exception as error:
328
                self.log.error(error)
329
                return False
330
        elif protocol == 'zip':
331
            try:
332
                self.unzip(filename, target_path)
333
                self.log.debug("Extracted successfully")
334
                return True
335
            except Exception as error:
336
                self.log.error(error)
337
                return False
338
 
339
    def zip(self, filename, directory):
340
        """
341
        Zip directory and rename to .bco
342
        """
343
        # http://stackoverflow.com/a/25650295
344
        #~ make_archive(archive_name, 'gztar', root_dir)
345
        self.log.debug("Target: %s", filename)
346
        sourcename = os.path.basename(filename)
347
        dot = sourcename.find('.')
348
        if dot == -1:
349
            basename = sourcename
350
        else:
351
            basename = sourcename[:dot]
352
        sourcedir = os.path.dirname(filename)
353
        source = os.path.join(sourcedir, basename)
354
        zipfile = shutil.make_archive(source, 'zip', directory)
355
        target = source + '.bco'
356
        shutil.move(zipfile, target)
357
        return target
358
 
359
 
360
    def unzip(self, target, install_dir):
361
        """
362
        Unzip file to a given dir
363
        """
364
        zip_archive = zipfile.ZipFile(target, "r")
365
        zip_archive.extractall(path=install_dir)
366
        zip_archive.close()
367
 
368
 
369
    def get_firefox_profile_dir(self):
370
        """
371
        Self-explained. Get default Firefox directory
372
        """
373
        if sys.platform in ['linux', 'linux2']:
374
            cmd = "ls -d /home/$USER/.mozilla/firefox/*.default/"
375
            p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE)
376
            FF_PRF_DIR = p.communicate()[0][0:-2]
377
            FF_PRF_DIR_DEFAULT = str(FF_PRF_DIR, 'utf-8')
378
        elif sys.platform == 'win32':
379
            import glob
380
            APPDATA = os.getenv('APPDATA')
381
            FF_PRF_DIR = "%s\\Mozilla\\Firefox\\Profiles\\" % APPDATA
382
            PATTERN = FF_PRF_DIR + "*default*"
383
            FF_PRF_DIR_DEFAULT = glob.glob(PATTERN)[0]
384
 
385
        return FF_PRF_DIR_DEFAULT
386
 
387
 
388
    def feedparser_parse(self, thing):
389
        """
390
        Missing method docstring (missing-docstring)
391
        """
392
        try:
393
            return feedparser.parse(thing)
394
        except TypeError:
395
            if 'drv_libxml2' in feedparser.PREFERRED_XML_PARSERS:
396
                feedparser.PREFERRED_XML_PARSERS.remove('drv_libxml2')
397
                return feedparser.parse(thing)
398
            else:
399
                self.log.error(self.get_traceback())
400
                return None
401
 
402
 
403
    def check(self):
404
        """
405
        Check Basico environment
406
        """
407
        gtk_version = self.uif.check_gtk_version() # Check GTK version
408
        gecko_driver = self.driver.check() # Check Gecko webdrver
409
        run = gtk_version and gecko_driver
410
        if run:
411
            self.log.debug("Basico environment ready!")
412
        else:
413
            self.log.error("Error(s) found checking Basico environment")
414
 
415
        return run
416
 
417
 
418
 
419
 
420
    def clean_html(self, raw_html):
421
        cleanr = re.compile('<.*?>')
422
        cleantext = re.sub(cleanr, '', raw_html)
423
        return cleantext