tools.py 5.52 KB
Newer Older
Jiahang Chen's avatar
Jiahang Chen committed
1
"""This module provides a collection of convenience functions."""
C. Albrecht's avatar
WIP    
C. Albrecht committed
2
3

import json
Jiahang Chen's avatar
Jiahang Chen committed
4
import os
Jiahang Chen's avatar
Jiahang Chen committed
5
import xml.etree.ElementTree as ET
C. Albrecht's avatar
WIP    
C. Albrecht committed
6
7

IDENTITY_PROVIDER_URL = "https://idp.s3i.vswf.dev/"
8
9
BUILT_IN = ["from", "str", "dict", "list", "bool", "float", "int", "tuple",
               "def", "return", "for", "if", "class", "try", "except"]
C. Albrecht's avatar
WIP    
C. Albrecht committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class BColors:
    """colors for the console log"""

    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[93m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"


Jiahang Chen's avatar
Jiahang Chen committed
24
def make_sub_thing(name, roles, features=[]):
C. Albrecht's avatar
WIP    
C. Albrecht committed
25
    """
Jiahang Chen's avatar
Jiahang Chen committed
26
27
28
    Creates a dictionary representing this thing in it's current state
    as a subordinate thing. This representation should be used for
    subordinate things in s3i repository entries
C. Albrecht's avatar
WIP    
C. Albrecht committed
29

Jiahang Chen's avatar
Jiahang Chen committed
30
31
32
33
34
35
    :param name: name of the sub thing
    :type name: str
    :param roles: fml40 roles of the sub thing
    :type roles: str
    :param features: fml40 features of the sub thing
    :type features: list
C. Albrecht's avatar
WIP    
C. Albrecht committed
36

Jiahang Chen's avatar
Jiahang Chen committed
37
38
    :returns: JSON of the sub thing
    :rtype: dict
C. Albrecht's avatar
WIP    
C. Albrecht committed
39
40

    """
Jiahang Chen's avatar
Jiahang Chen committed
41
42
43
    sub_thing = {
        "class": "ml40::Thing",
        "name": name,
Jiahang Chen's avatar
Jiahang Chen committed
44
45
        "roles": roles,
        "features": features
Jiahang Chen's avatar
Jiahang Chen committed
46
47
48
49
50
    }

    return sub_thing


Jiahang Chen's avatar
Jiahang Chen committed
51
def make_feature_config(class_name, identifier="", name="", subFeatures=""):
Jiahang Chen's avatar
Jiahang Chen committed
52
    """
Jiahang Chen's avatar
Jiahang Chen committed
53
    Creates a dictionary representing for its ml/fml40 features
Jiahang Chen's avatar
Jiahang Chen committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67

    :param class_name: class name of the fml40 feature
    :type class_name: str
    :param identifier: local id of the fml40 feature
    :type identifier: str
    :param name: name of the fml40 feature
    :type name: str
    :param subFeatures: sub features
    :type subFeatures: dict

    :returns: JSON of the fml40 feature
    :rtype: dict

    """
Jiahang Chen's avatar
Jiahang Chen committed
68
69
70
71
72
73
74
75
76
77
78
79
80
    config_json = {
        "class": class_name
    }
    if identifier:
        config_json["identifier"] = identifier
    if name:
        config_json["name"] = name
    if subFeatures:
        config_json["subFeatures"] = subFeatures

    return config_json


Jiahang Chen's avatar
Jiahang Chen committed
81
def make_thing_config(thing_id, name, roles, features=[], config_path=""):
Jiahang Chen's avatar
Jiahang Chen committed
82
    """
Jiahang Chen's avatar
Jiahang Chen committed
83
    Creates a configuration file (JSON) for a fml40 thing.
Jiahang Chen's avatar
Jiahang Chen committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

    :param thing_id: identifier of the thing
    :type thing_id: str
    :param name: name of the thing
    :type name: str
    :param roles: fml40 roles of the thing
    :type roles: list
    :param features: fml40 features of the thing
    :type features: list
    :param config_path: path where the configuration file should be located
    :type config_path: str

    :returns: name of the configuration file of the thing
    :rtype: str


    """
Jiahang Chen's avatar
Jiahang Chen committed
101
102
103
    if not config_path:
        config_path = os.path.join("__file__", "configs")

Jiahang Chen's avatar
Jiahang Chen committed
104
    config_file = {
Jiahang Chen's avatar
Jiahang Chen committed
105
106
        "thingId": thing_id,
        "policyId": thing_id,
Jiahang Chen's avatar
Jiahang Chen committed
107
108
109
        "attributes": {
            "class": "ml40::Thing",
            "name": name,
Jiahang Chen's avatar
Jiahang Chen committed
110
111
            "roles": roles,
            "features": features,
Jiahang Chen's avatar
Jiahang Chen committed
112
113
        }
    }
Jiahang Chen's avatar
Jiahang Chen committed
114
115
    file_path = os.path.join(config_path, "{}.json".format(name))
    with open(file_path, 'wb') as file:
Jiahang Chen's avatar
Jiahang Chen committed
116
        file.write(json.dumps(config_file).encode('utf-8'))
117
    return "{}.json".format(name)
Jiahang Chen's avatar
Jiahang Chen committed
118
119


Jiahang Chen's avatar
Jiahang Chen committed
120
def load_config(config_filepath):
Jiahang Chen's avatar
Jiahang Chen committed
121
    """
Jiahang Chen's avatar
Jiahang Chen committed
122
    Loads a JSON object from a json formatted file found at config_filepath.
C. Albrecht's avatar
WIP    
C. Albrecht committed
123
124

    :param config_filepath: Path to json formatted file.
Jiahang Chen's avatar
Jiahang Chen committed
125
    :type config_filepath: str
C. Albrecht's avatar
WIP    
C. Albrecht committed
126
127

    """
Jiahang Chen's avatar
Jiahang Chen committed
128
    with open(config_filepath) as config_file:
C. Albrecht's avatar
WIP    
C. Albrecht committed
129
130
131
132
        config = json.load(config_file)
        return config


Jiahang Chen's avatar
Jiahang Chen committed
133
def find_broker_endpoint(dir_obj, thing_id):
C. Albrecht's avatar
WIP    
C. Albrecht committed
134
    """
Jiahang Chen's avatar
Jiahang Chen committed
135
    Finds the S3I-B endpoint of a thing
C. Albrecht's avatar
WIP    
C. Albrecht committed
136

Jiahang Chen's avatar
Jiahang Chen committed
137
138
139
    :param dir_obj: S³I Directory Object
    :type dir_obj: object
    :param thing_id: identifier of the searched thing
C. Albrecht's avatar
WIP    
C. Albrecht committed
140
141

    """
Jiahang Chen's avatar
Jiahang Chen committed
142
143
144
145
146
147
    thing_json = dir_obj.queryThingIDBased(thing_id)
    all_endpoints = thing_json["attributes"].get("allEndpoints", None)
    if all_endpoints:
        for ep in all_endpoints:
            if "s3ib" in ep:
                return ep
C. Albrecht's avatar
WIP    
C. Albrecht committed
148
149


Jiahang Chen's avatar
Jiahang Chen committed
150
def remove_namespace(input_str):
C. Albrecht's avatar
WIP    
C. Albrecht committed
151
    """
Jiahang Chen's avatar
Jiahang Chen committed
152
    Removes the specified namespace like ml40 or fml40
Jiahang Chen's avatar
Jiahang Chen committed
153

Jiahang Chen's avatar
Jiahang Chen committed
154
155
156
157
    :param input_str: input with namespace
    :type input_str: str
    :returns: output without namespace
    :rtype: str
Jiahang Chen's avatar
Jiahang Chen committed
158

Jiahang Chen's avatar
Jiahang Chen committed
159
    """
Jiahang Chen's avatar
Jiahang Chen committed
160
    return input_str.replace("mml40::", "").replace("fml40::", "").replace("ml40::", "")
161
162
163
164
165
166
167
168
169
170
171
172


def check_var_conflict(var):
    """
    check if the input is built-in variable
    :param var: python var
    :return: modified variable, if the input is a input variable.
    """

    if var in BUILT_IN:
        return "_{}".format(var)
    else:
Jiahang Chen's avatar
Jiahang Chen committed
173
174
175
176
177
178
179
180
181
182
183
        return var


class XML:
    def __init__(self, path=None, xml_str=None):
        self.et = ET
        self._namespace = {}

        self._namespace = {
            'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
            'schemaLocation': 'urn:skogforsk:stanford2010 HarvestedProduction_V3p0.xsd',
Jiahang Chen's avatar
Jiahang Chen committed
184
            '': 'urn:skogforsk:stanford2010'
Jiahang Chen's avatar
Jiahang Chen committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
        }

        for key in self._namespace:
            self.et.register_namespace(key, self._namespace[key])

        if path is not None:
            self.tree = self.et.parse(path)
            self.root = self.tree.getroot()

        if xml_str is not None:
            self.root = self.et.fromstring(xml_str)

    def find_nodes(self, path):
        path_list = path.split('/')
        new_path = ""
        for _path in path_list:
            if ":" not in _path:
Jiahang Chen's avatar
Jiahang Chen committed
202
                _path = "{" + self._namespace.get('') + "}" + _path
Jiahang Chen's avatar
Jiahang Chen committed
203
204
205
206
            new_path += _path
            new_path += "/"
        if new_path[-1] == "/":
            new_path = new_path[:-1]
Jiahang Chen's avatar
Jiahang Chen committed
207
208
209
210
        return self.root.findall(new_path, self._namespace)

    def to_string(self, root):
        return self.et.tostring(root, "unicode", "xml")