Completed
Push — master ( 7b504c...b6f606 )
by Ionel Cristian
01:16
created

Storage.get()   A

Complexity

Conditions 3

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
1
import json
2
import os
3
from itertools import chain
4
5
from pathlib import Path
6
7
from .utils import commonpath
8
from .utils import short_filename
9
10
11
class Storage(object):
12
    def __init__(self, path, logger, default_machine_id=None):
13
        self.path = Path(path)
14
        self.default_machine_id = default_machine_id
15
        if not self.path.exists():
16
            self.path.mkdir(parents=True)
17
        self.path = self.path.resolve()
18
        self.logger = logger
19
        self._cache = {}
20
21
    def __str__(self):
22
        return str(self.path)
23
24
    @property
25
    def location(self):
26
        return str(self.path.relative_to(os.getcwd()))
27
28
    def get(self, name):
29
        path = self.path.joinpath(self.default_machine_id) if self.default_machine_id else self.path
30
        if not path.exists():
31
            path.mkdir(parents=True)
32
        return path.joinpath(name)
33
34
    def query(self, *globs_or_files):
35
        files = []
36
        globs = []
37
        if not globs_or_files:
38
            globs_or_files = "*",
39
40
        for globish in globs_or_files:
41
            candidate = Path(globish)
42
            try:
43
                is_file = candidate.is_file()
44
            except OSError:
45
                is_file = False
46
            if is_file:
47
                files.append(candidate)
48
                continue
49
50
            parts = candidate.parts
51
            if len(parts) > 2:
52
                raise ValueError("{0!r} isn't an existing file or acceptable glob. "
53
                                 "Expected 'platform-glob/filename-glob' or 'filename-glob'.".format(globish))
54
            elif len(parts) == 2:
55
                platform_glob, filename_glob = parts
56
            else:
57
                platform_glob = self.default_machine_id or "*"
58
                filename_glob, = parts or ['']
59
60
            filename_glob = filename_glob.rstrip("*") + "*.json"
61
            globs.append((platform_glob, filename_glob))
62
63
        return sorted(chain(
64
            files,
65
            (
66
                file
67
                for platform_glob, filename_glob in globs
68
                for path in self.path.glob(platform_glob)
69
                for file in path.glob(filename_glob)
70
            ), (
71
                file for file in self.path.glob(filename_glob)
72
            )
73
        ), key=lambda file: (file.name, file.parent))
74
75
    def load(self, *globs_or_files):
76
        for file in self.query(*globs_or_files):
77
            if file in self._cache:
78
                data = self._cache[file]
79
            else:
80
                with file.open("rU") as fh:
81
                    try:
82
                        data = json.load(fh)
83
                    except Exception as exc:
84
                        self.logger.warn("BENCHMARK-C5",
85
                                         "Failed to load {0}: {1}".format(file, exc), fslocation=self.location)
86
                        continue
87
                self._cache[file] = data
88
89
            yield file.relative_to(self.path), data
90
91
    def load_benchmarks(self, *globs_or_files):
92
        sources = [
93
            (short_filename(path), path, data)
94
            for path, data in self.load(*globs_or_files)
95
        ]
96
        common = len(commonpath([src for src, _, _ in sources])) if sources else 0
97
        for source, path, data in sources:
98
            source = source[common:].lstrip(r'\/')
99
100
            for bench in data["benchmarks"]:
101
                bench.update(bench.pop("stats"))
102
                bench['path'] = str(path)
103
                bench['source'] = source
104
                yield bench
105