Completed
Push — master ( 5dce03...efda8a )
by Ionel Cristian
01:05
created

src.pytest_benchmark.Storage   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 83
Duplicated Lines 0 %
Metric Value
dl 0
loc 83
rs 10
wmc 26

7 Methods

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