utils.py 2.29 KB
Newer Older
Matthieu Boileau's avatar
Matthieu Boileau committed
1
2
3
import shutil
from pathlib import Path
from zipfile import ZipFile
Matthieu Boileau's avatar
Matthieu Boileau committed
4
5
import inspect
import re
Matthieu Boileau's avatar
Matthieu Boileau committed
6
7
8
9
10
11
12
13
14
15

IGNORED = '__pycache__'


def update_material(src: Path, dst: Path):
    """Remove dst tree then update with src"""
    shutil.rmtree(dst, ignore_errors=True)
    shutil.copytree(src, dst, ignore=shutil.ignore_patterns(IGNORED))


Matthieu Boileau's avatar
Matthieu Boileau committed
16
def get_file_list(path: Path, relative: bool = True, ignore: list = None):
Matthieu Boileau's avatar
Matthieu Boileau committed
17
    """Return a list of file paths relative to path"""
Matthieu Boileau's avatar
Matthieu Boileau committed
18
    ignored = set([IGNORED]) | {ignore}
Matthieu Boileau's avatar
Matthieu Boileau committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

    def get_path(obj):
        """return a relative or absolute path"""
        return obj.relative_to(path) if relative else obj

    return [get_path(obj) for obj in path.glob('**/*')
            if (obj.is_file() and ignored.isdisjoint(obj.parts))]


def clean_tree(target):
    """Clean tree ignoring errors"""
    shutil.rmtree(target, ignore_errors=True)


def update_dict(current: dict, new: dict):
    """Update current multi-level dict with new dict"""
    for k, v in new.items():
Matthieu Boileau's avatar
Matthieu Boileau committed
36
        if k in current and type(current[k]) is dict and type(v) is dict:
Matthieu Boileau's avatar
Matthieu Boileau committed
37
            # Update current entry by descending into sub dict
Matthieu Boileau's avatar
Matthieu Boileau committed
38
39
40
41
42
43
            update_dict(current[k], v)
        else:
            # Add new entry or update with new value
            current[k] = v


Matthieu Boileau's avatar
Matthieu Boileau committed
44
45
46
47
48
49
50
51
52
53
54
55
56
def zip_files(zip_file_name: Path, paths_to_zip: list,
              ref_to_arc: tuple = None):
    """
    Archive files_to_zip in zip file

    :param paths_to_zip: a list of files to be archived
    :param zip_file_name: the archive filename
    :param ref_to_arc: a ('refpath', 'arcdir') tuple
    """
    if ref_to_arc:
        refpath = ref_to_arc[0]
        arcdir = ref_to_arc[1]

Matthieu Boileau's avatar
Matthieu Boileau committed
57
58
59
    with ZipFile(zip_file_name, 'w') as zf:
        for path in paths_to_zip:
            # Convert refpath/file in arcdir/file if asked
Matthieu Boileau's avatar
Matthieu Boileau committed
60
61
            arcpath = arcdir / path.relative_to(refpath) \
                      if ref_to_arc else None
Matthieu Boileau's avatar
Matthieu Boileau committed
62
63
64
            zf.write(path, arcname=arcpath)


Matthieu Boileau's avatar
Matthieu Boileau committed
65
66
67
68
69
70
71
72
73
74
75
76
def get_functions(namespace, pattern: str) -> list:
    """
    Return the list of functions in namespace that match the regex pattern
    """
    all_functions = inspect.getmembers(namespace, inspect.isfunction)
    p = re.compile(pattern)
    functions = []
    for function, dummy in all_functions:
        m = p.match(function)
        if m:
            functions.append(m.group(1))
    return functions