Statistiques
| Branche: | Tag: | Révision :

dockonsurf / modules / utilities.py @ cf980c86

Historique | Voir | Annoter | Télécharger (3,59 ko)

1 af3e2441 Carles Marti
import logging
2 78fcb188 Carles Martí
3 af3e2441 Carles Marti
logger = logging.getLogger('DockOnSurf')
4 af3e2441 Carles Marti
5 af3e2441 Carles Marti
6 f8c4eafe Carles
def tail(f, lines=20):
7 4e82c425 Carles Martí
    """Returns the specified last number of lines of a file.
8 4e82c425 Carles Martí

9 4e82c425 Carles Martí
    @param f: The file to retrieve the last lines from.
10 4e82c425 Carles Martí
    @param lines: The number of lines to be retrieved.
11 4e82c425 Carles Martí
    @return str: The last number of lines
12 4e82c425 Carles Martí
    """
13 f8c4eafe Carles
    total_lines_wanted = lines
14 f8c4eafe Carles
15 f8c4eafe Carles
    block_size = 1024
16 f8c4eafe Carles
    f.seek(0, 2)
17 f8c4eafe Carles
    block_end_byte = f.tell()
18 f8c4eafe Carles
    lines_to_go = total_lines_wanted
19 f8c4eafe Carles
    block_number = -1
20 f8c4eafe Carles
    blocks = []
21 f8c4eafe Carles
    while lines_to_go > 0 and block_end_byte > 0:
22 f8c4eafe Carles
        if block_end_byte - block_size > 0:
23 f8c4eafe Carles
            f.seek(block_number * block_size, 2)
24 f8c4eafe Carles
            blocks.append(f.read(block_size))
25 f8c4eafe Carles
        else:
26 f8c4eafe Carles
            f.seek(0, 0)
27 f8c4eafe Carles
            blocks.append(f.read(block_end_byte))
28 f8c4eafe Carles
        lines_found = blocks[-1].count(b'\n')
29 f8c4eafe Carles
        lines_to_go -= lines_found
30 f8c4eafe Carles
        block_end_byte -= block_size
31 f8c4eafe Carles
        block_number -= 1
32 f8c4eafe Carles
    all_read_text = b''.join(reversed(blocks))
33 f8c4eafe Carles
    return b'\n'.join(all_read_text.splitlines()[-total_lines_wanted:]).decode()
34 69d17e8b Carles
35 69d17e8b Carles
36 69d17e8b Carles
def check_bak(file_name):
37 69d17e8b Carles
    """Checks if a file already exists and backs it up if so.
38 4e82c425 Carles Martí

39 69d17e8b Carles
    @param file_name: file to be checked if exists
40 69d17e8b Carles
    """
41 69d17e8b Carles
    import os
42 69d17e8b Carles
    new_name = file_name
43 69d17e8b Carles
    bak_num = 0
44 69d17e8b Carles
    while os.path.isdir(new_name) or os.path.isfile(new_name):
45 69d17e8b Carles
        bak_num += 1
46 69d17e8b Carles
        new_name = new_name.split(".bak")[0] + f".bak{bak_num}"
47 69d17e8b Carles
    if bak_num > 0:
48 69d17e8b Carles
        os.rename(file_name, new_name)
49 69d17e8b Carles
        logger.warning(f"'{file_name}' already present. Backed it up to "
50 695dcff8 Carles Marti
                       f"{new_name}.")
51 69d17e8b Carles
52 69d17e8b Carles
53 69d17e8b Carles
def try_command(command, expct_error_types: list, *args, **kwargs):
54 69d17e8b Carles
    """Try to run a command and record exceptions (expected and not) on a log.
55 69d17e8b Carles

56 69d17e8b Carles
    @param command: method or function, the command to be executed.
57 42fed021 Carles Marti
    @param expct_error_types: list of tuples, every inner tuple is supposed to
58 69d17e8b Carles
    contain an exception type (eg. ValueError, TypeError, etc.) to be caught and
59 69d17e8b Carles
    a message to print in the log and on the screen explaining the exception.
60 69d17e8b Carles
    Error types that are not allow to be called with a custom message as only
61 69d17e8b Carles
    error argument are not supported.
62 69d17e8b Carles
    The outer tuple encloses all couples of error types and their relative
63 69d17e8b Carles
    messages.
64 69d17e8b Carles
    *args and **kwargs: arguments and keyword-arguments of the command to be
65 69d17e8b Carles
    executed.
66 69d17e8b Carles
    When trying to run 'command' with its args and kwargs, if an exception
67 69d17e8b Carles
    present on the 'error_types' occurs, its relative error message is recorded
68 69d17e8b Carles
    on the log and a same type exception is raised with the custom message.
69 69d17e8b Carles
    """
70 af3e2441 Carles Marti
    unexp_error = "An unexpected error occurred"
71 69d17e8b Carles
72 69d17e8b Carles
    err = False
73 69d17e8b Carles
    try:
74 69d17e8b Carles
        return_val = command(*args, **kwargs)
75 69d17e8b Carles
    except Exception as e:
76 69d17e8b Carles
        for expct_err in expct_error_types:
77 69d17e8b Carles
            if isinstance(e, expct_err[0]):
78 69d17e8b Carles
                logger.error(expct_err[1])
79 69d17e8b Carles
                err = expct_err[0](expct_err[1])
80 69d17e8b Carles
                break
81 69d17e8b Carles
        else:
82 69d17e8b Carles
            logger.exception(unexp_error)
83 69d17e8b Carles
            err = e
84 69d17e8b Carles
    else:
85 69d17e8b Carles
        err = False
86 69d17e8b Carles
        return return_val
87 69d17e8b Carles
    finally:
88 69d17e8b Carles
        if isinstance(err, BaseException):
89 78fcb188 Carles Martí
            raise err
90 dbef6e98 Carles Martí
91 dbef6e98 Carles Martí
92 dbef6e98 Carles Martí
def _human_key(key):
93 4e82c425 Carles Martí
    """Function used as sorting strategy where numbers are sorted human-wise.
94 4e82c425 Carles Martí

95 4e82c425 Carles Martí
    @param key:
96 4e82c425 Carles Martí
    @return:
97 4e82c425 Carles Martí
    """
98 dbef6e98 Carles Martí
    import re
99 dbef6e98 Carles Martí
    parts = re.split('(\d*\.\d+|\d+)', key)
100 dbef6e98 Carles Martí
    return tuple((e.swapcase() if i % 2 == 0 else float(e))
101 dbef6e98 Carles Martí
                 for i, e in enumerate(parts))
102 f07523a6 Carles Martí
103 f07523a6 Carles Martí
104 f07523a6 Carles Martí
def is_binary(file):
105 4e82c425 Carles Martí
    """Checks if a file is a text file or a binary one.
106 4e82c425 Carles Martí

107 4e82c425 Carles Martí
    @param file:
108 4e82c425 Carles Martí
    @return:
109 4e82c425 Carles Martí
    """
110 f07523a6 Carles Martí
    try:
111 f07523a6 Carles Martí
        with open(file, "r") as fh:
112 f07523a6 Carles Martí
            fh.read(50)
113 f07523a6 Carles Martí
    except UnicodeDecodeError:
114 f07523a6 Carles Martí
        return True
115 f07523a6 Carles Martí
    else:
116 f07523a6 Carles Martí
        return False