aboutsummaryrefslogtreecommitdiffstats
path: root/build/plugins/lib/nots/erm_json_lite.py
blob: dee76302a0ae096d38f1806f7a7bb22d9a0e1a14 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import json
from functools import cmp_to_key

from lib.nots.semver import Version, VersionRange


class ErmJsonLite(object):
    """
    Basic implementation to read `erm-packages.json`.

    It doesn't use any models, works with only raw JSON types: lists, dicts, strings
    """

    class ResourceType(object):
        NPM_PACKAGE = "NPM_PACKAGE"
        NODE_JS = "NODE_JS"

    data = None

    @staticmethod
    def get_versions_of(er_resource):
        # type: (dict) -> list[Version]
        """
        Return all versions of the resource in ASC order (from older to latest)
        """
        unsorted = er_resource.get("versions").keys()
        # We have to sort because in python 2 the order of keys in a dict is not guaranteed
        versions = sorted(unsorted, key=cmp_to_key(Version.cmp))

        return [Version.from_str(v) for v in versions]

    @classmethod
    def load(cls, path):
        # type: (str) -> ErmJsonLite
        erm_json = cls()

        with open(path) as f:
            erm_json.data = dict()
            for k, v in json.load(f).items():
                # Ignore comments (when key starts with `_`), used for banner
                if not k.startswith("_"):
                    erm_json.data[k] = v

        return erm_json

    def get_resource(self, resource_name):
        # type: (str) -> dict
        """
        Return resource by his name
        """
        er_resource = self.data.get(resource_name)
        if not er_resource:
            raise Exception("Requested resource {} is not a toolchain item".format(resource_name))

        return er_resource

    def get_sb_resources(self, resource_name, version):
        # type: (str, Version) -> list[dict]
        """
        Return a list of SB resources for ER version
        """
        er_resource = self.get_resource(resource_name)

        return er_resource.get("versions").get(str(version)).get("resources")

    def is_resource_multiplatform(self, resource_name):
        # type: (str) -> bool
        """
        Return True if resource is multiplatform, False otherwise
        """
        er_resource = self.get_resource(resource_name)

        return er_resource.get("multiplatform", False)

    def list_npm_packages(self):
        # type: () -> list[str]
        """
        Returns a list of the names of the npm tools used in the toolchain
        """
        result = []
        for resource_name, resource in self.data.items():
            if resource.get("type") == self.ResourceType.NPM_PACKAGE:
                result.append(resource_name)

        return result

    def select_version_of(self, resource_name, range_str=None):
        # type: (str, str|None) -> Version|None
        er_resource = self.get_resource(resource_name)

        if range_str is None:
            return Version.from_str(er_resource.get("default"))

        version_range = VersionRange.from_str(range_str)

        # assuming the version list is sorted from the lowest to the highest version,
        # we stop the loop as early as possible and hence return the lowest compatible version
        for version in self.get_versions_of(er_resource):
            if version_range.is_satisfied_by(version):
                return version

        return None