GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( d27176...79f779 )
by Daniel
01:00
created

Device.import_stream()   D

Complexity

Conditions 8

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
c 1
b 0
f 0
dl 0
loc 47
rs 4.3478
1
from __future__ import absolute_import
2
import json
3
import os
4
5
from ._connection import DatabaseConnection
6
from ._connectorobject import ConnectorObject
7
8
9
class Device(ConnectorObject):
10
11
    def create(self, public=False, **kwargs):
12
        """Creates the device. Attempts to create private devices by default,
13
        but if public is set to true, creates public devices.
14
15
        You can also set other default properties by passing in the relevant information.
16
        For example, setting a device with the given nickname and description::
17
18
            dev.create(nickname="mydevice", description="This is an example")
19
20
        Furthermore, ConnectorDB supports creation of a device's streams immediately,
21
        which can considerably speed up device setup::
22
23
            dev.create(streams={
24
                "stream1": {"schema": '{\"type\":\"number\"}'}
25
            })
26
27
        Note that the schema must be encoded as a string when creating in this format.
28 View Code Duplication
        """
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
29
        kwargs["public"] = public
30
        self.metadata = self.db.create(self.path, kwargs).json()
31
32
    def streams(self):
33
        """Returns the list of streams that belong to the device"""
34
        result = self.db.read(self.path, {"q": "ls"})
35
36
        if result is None or result.json() is None:
37
            return []
38
        streams = []
39
        for s in result.json():
40
            strm = self[s["name"]]
41
            strm.metadata = s
42
            streams.append(strm)
43
        return streams
44
45
    def __getitem__(self, stream_name):
46
        """Gets the child stream by name"""
47
        return Stream(self.db, self.path + "/" + stream_name)
48
49
    def __repr__(self):
50
        """Returns a string representation of the device"""
51
        return "[Device:%s]" % (self.path, )
52
53
    def export(self, directory):
54
        """Exports the device to the given directory. The directory can't exist. 
55
        You can later import this device by running import_device on a user.
56
        """
57
        if os.path.exists(directory):
58
            raise FileExistsError(
59
                "The device export directory already exists")
60
61
        os.mkdir(directory)
62
63
        # Write the device's info
64
        with open(os.path.join(directory, "device.json"), "w") as f:
65
            json.dump(self.data, f)
66
67
        # Now export the streams one by one
68
        for s in self.streams():
69
            s.export(os.path.join(directory, s.name))
70
71
    def import_stream(self, directory):
72
        """Imports a stream from the given directory. You export the Stream
73
        by using stream.export()"""
74
75
        # read the stream's info
76
        with open(os.path.join(directory, "stream.json"), "r") as f:
77
            sdata = json.load(f)
78
79
        s = self[sdata["name"]]
80
        if s.exists():
81
            raise ValueError("The stream " + s.name + " already exists")
82
83
        # Create the stream empty first, so we can insert all the data without
84
        # worrying about schema violations or downlinks
85
        s.create()
86
87
        # Now, in order to insert data into this stream, we must be logged in as
88
        # the owning device
89
        ddb = DatabaseConnection(self.apikey, url=self.db.baseurl)
90
        d = Device(ddb, self.path)
91
92
        # Set up the owning device
93
        sown = d[s.name]
94
95
        # read the stream's info
96
        with open(os.path.join(directory, "data.json"), "r") as f:
97
            data = json.load(f)
98
            # In some cases, older versions of ConnectorDB had a bug where if
99
            # the server crashed during a batch update, timestamps would not be consistent. 
100
            # To work around this issue when exporting from older versions,
101
            # we first sort the dataset, just in case.
102
            data.sort(key=lambda d: d["t"])
103
            
104
            sown.insert_array(data)
105
106
        # Now we MIGHT be able to recover the downlink data,
107
        # only if we are not logged in as the device that the stream is being inserted into
108
        # So we check. When downlink is true, data is inserted into the
109
        # downlink stream
110
        if (sdata["downlink"] and self.db.path != self.path):
111
            s.downlink = True
112
            with open(os.path.join(directory, "downlink.json"), "r") as f:
113
                s.insert_array(json.load(f))
114
115
        # And finally, update the device
116
        del sdata["name"]
117
        s.set(sdata)
118
119
    # -----------------------------------------------------------------------
120
    # Following are getters and setters of the device's properties
121
122
    @property
123
    def apikey(self):
124
        """gets the device's api key. Returns None if apikey not accessible."""
125
        if "apikey" in self.data:
126
            return self.data["apikey"]
127
        return None
128
129
    def reset_apikey(self):
130
        """invalidates the device's current api key, and generates a new one"""
131
        self.set({"apikey": ""})
132
        return self.metadata["apikey"]
133
134
    @property
135
    def public(self):
136
        """gets whether the device is public
137
        (this means different things based on connectordb permissions setup - connectordb.com
138
        has this be whether the device is publically visible. Devices are individually public/private.)
139
        """
140
        if "public" in self.data:
141
            return self.data["public"]
142
        return None
143
144
    @public.setter
145
    def public(self, new_public):
146
        """Attempts to set whether the device is public"""
147
        self.set({"public": new_public})
148
149
    @property
150
    def role(self):
151
        """Gets the role of the device. This is the permissions level that the device has. It might
152
        not be accessible depending on the permissions setup of ConnectorDB. Returns None if not accessible"""
153
        if "role" in self.data:
154
            return self.data["role"]
155
        return None
156
157
    @role.setter
158
    def role(self, new_role):
159
        """ Attempts to set the device's role"""
160
        self.set({"role": new_role})
161
162
    @property
163
    def enabled(self):
164
        """ gets whether the device is enabled. This allows a device to notify ConnectorDB when
165
        it is active and when it is not running"""
166
        if "enabled" in self.data:
167
            return self.data["enabled"]
168
        return None
169
170
    @enabled.setter
171
    def enabled(self, new_enabled):
172
        """Sets the enabled state of the device"""
173
        self.set({"enabled": new_enabled})
174
175
    @property
176
    def user(self):
177
        """user returns the user which owns the given device"""
178
        return User(self.db, self.path.split("/")[0])
179
180
181
# The import has to go on the bottom because py3 imports are annoying
182
# about circular dependencies
183
from ._user import User
184
from ._stream import Stream
185