• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / SpiNNMachine / 5689157980

pending completion
5689157980

push

github

web-flow
Merge pull request #217 from SpiNNakerManchester/version

Version

737 of 822 branches covered (89.66%)

Branch coverage included in aggregate %.

286 of 286 new or added lines in 17 files covered. (100.0%)

2065 of 2173 relevant lines covered (95.03%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.49
/spinn_machine/data/machine_data_view.py
1
# Copyright (c) 2021 The University of Manchester
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     https://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
from spinn_utilities.data import UtilsDataView
1✔
16
from spinn_machine.version.version_factory import version_factory
1✔
17
# pylint: disable=protected-access
18

19

20
class _MachineDataModel(object):
1✔
21
    """
22
    Singleton data model.
23

24
    This class should not be accessed directly please use the DataView and
25
    DataWriter classes.
26
    Accessing or editing the data held here directly is NOT SUPPORTED
27

28
    There may be other DataModel classes which sit next to this one and hold
29
    additional data. The DataView and DataWriter classes will combine these
30
    as needed.
31

32
    What data is held where and how can change without notice.
33
    """
34

35
    __singleton = None
1✔
36

37
    __slots__ = [
1✔
38
        # Data values cached
39
        "_machine",
40
        "_machine_generator",
41
        "_machine_version",
42
        "_user_accessed_machine"
43
    ]
44

45
    def __new__(cls):
1✔
46
        if cls.__singleton:
1✔
47
            return cls.__singleton
1✔
48
        # pylint: disable=protected-access
49
        obj = object.__new__(cls)
1✔
50
        cls.__singleton = obj
1✔
51
        obj._clear()
1✔
52
        return obj
1✔
53

54
    def _clear(self):
1✔
55
        """
56
        Clears out all data
57
        """
58
        self._hard_reset()
1✔
59
        self._machine_generator = None
1✔
60
        self._machine_version = None
1✔
61

62
    def _hard_reset(self):
1✔
63
        """
64
        Clears out all data that should change after a reset and graph change
65

66
        This does NOT clear the machine as it may have been asked for before
67
        """
68
        self._soft_reset()
1✔
69
        self._machine = None
1✔
70
        self._user_accessed_machine = False
1✔
71

72
    def _soft_reset(self):
1✔
73
        """
74
        Clears timing and other data that should changed every reset
75
        """
76
        # Holder for any later additions
77

78

79
class MachineDataView(UtilsDataView):
1✔
80
    """
81
    Adds the extra Methods to the View for Machine level.
82

83
    See :py:class:`~spinn_utilities.data.UtilsDataView` for a more detailed
84
    description.
85

86
    This class is designed to only be used directly within the SpiNNMachine
87
    repository as all methods are available to subclasses
88
    """
89

90
    __data = _MachineDataModel()
1✔
91
    __slots__ = []
1✔
92

93
    # machine methods
94

95
    @classmethod
1✔
96
    def has_machine(cls):
1✔
97
        """
98
        Reports if a machine is currently set or can be mocked.
99

100
        Unlike has_existing_machine for unit tests this will return True even
101
        if a Machine has not yet been created
102

103
        :rtype: bool
104
        """
105
        return (cls.__data._machine is not None or
1✔
106
                cls._is_mocked())
107

108
    @classmethod
1✔
109
    def has_existing_machine(cls):
1✔
110
        """
111
        Reports if a machine is currently already created.
112

113
        Unlike has_machine this method returns false if a machine could be
114
        mocked
115

116
        :rtype: bool
117
        """
118
        return cls.__data._machine
×
119

120
    @classmethod
1✔
121
    def get_machine(cls):
1✔
122
        """
123
        Returns the Machine if it has been set.
124

125
        In Mock mode will create and return a virtual 8 * 8 board
126

127
        :raises ~spinn_utilities.exceptions.SpiNNUtilsException:
128
            If the machine is currently unavailable
129
        :rtype: ~spinn_machine.Machine
130
        """
131
        if cls.is_user_mode():
1✔
132
            if cls.is_soft_reset():
1!
133
                cls.__data._machine = None
×
134
            cls.__data._user_accessed_machine = True
1✔
135
        if cls.__data._machine is None:
1✔
136
            if cls.__data._machine_generator:
1✔
137
                # pylint: disable=not-callable
138
                cls.__data._machine_generator()
1✔
139
                return cls.__data._machine
1✔
140
            raise cls._exception("machine")
1✔
141
        return cls.__data._machine
1✔
142

143
    @classmethod
1✔
144
    def get_chip_at(cls, x, y):
1✔
145
        """
146
        Gets the chip at (`x`, `y`).
147

148
        Almost Semantic sugar for `get_machine().get_chip_at()`
149

150
        The method however does not return `None` but rather raises a KeyError
151
        if the chip is not known
152

153
        :param int x:
154
        :param int y:
155
        :rtype: Chip
156
        :raises ~spinn_utilities.exceptions.SpiNNUtilsException:
157
            If the machine is currently unavailable
158
        :raises KeyError: If the chip does not exist but the machine does
159
        """
160
        return cls.get_machine()._chips[(x, y)]
1✔
161

162
    @classmethod
1✔
163
    def get_nearest_ethernet(cls, x, y):
1✔
164
        """
165
        Gets the nearest Ethernet-enabled chip (`x`, `y`) for the chip at
166
        (`x`, `y`) if it exists.
167

168
        If there is no machine or no chip at (`x`, `y`) this method,
169
        or any other issue will just return (`x`, `y`)
170

171
        .. note::
172
            This method will never request a new machine.
173
            Therefore a call to this method will not trigger a hard reset
174

175
        :param int x: Chip X coordinate
176
        :param int y: Chip Y coordinate
177
        :return: Chip (`x`,`y`)'s nearest_ethernet info
178
            or if that is not available just (`x`, `y`)
179
        :rtype: tuple(int, int)
180
        """
181
        try:
×
182
            chip = cls.__data._machine._chips[(x, y)]
×
183
            return chip.nearest_ethernet_x, chip.nearest_ethernet_y
×
184
        except Exception:  # pylint: disable=broad-except
×
185
            if cls.__data._machine is None:
×
186
                return x, y
×
187
            return x, y
×
188

189
    @classmethod
1✔
190
    def where_is_xy(cls, x, y):
1✔
191
        """
192
        Gets a string saying where chip at x and y is if possible.
193

194
        Almost Semantic sugar for `get_machine().where_is_xy()`
195

196
        The method does not raise an exception rather returns a String of the
197
        exception
198

199
        .. note::
200
            This method will never request a new machine.
201
            Therefore a call to this method will not trigger a hard reset
202

203
        :param int x:
204
        :param int y:
205
        :rtype: str
206
        """
207
        try:
1✔
208
            return cls.__data._machine.where_is_xy(x, y)
1✔
209
        except Exception as ex:  # pylint: disable=broad-except
1✔
210
            if cls.__data._machine is None:
1!
211
                return "No Machine created yet"
1✔
212
            return str(ex)
×
213

214
    @classmethod
1✔
215
    def where_is_chip(cls, chip):
1✔
216
        """
217
        Gets a string saying where chip is if possible.
218

219
        Almost Semantic sugar for `get_machine().where_is_chip()`
220

221
        The method does not raise an exception rather returns a String of the
222
        exception
223

224
        .. note::
225
            This method will never request a new machine.
226
            Therefore a call to this method will not trigger a hard reset
227

228
        :param int x:
229
        :param int y:
230
        :rtype: str
231
        """
232
        try:
1✔
233
            return cls.__data._machine.where_is_chip(chip)
1✔
234
        except Exception as ex:  # pylint: disable=broad-except
×
235
            if cls.__data._machine is None:
×
236
                return "Chip is from a previous machine"
×
237
            return str(ex)
×
238

239
    @classmethod
1✔
240
    def get_machine_version(cls):
1✔
241
        """
242
        Returns the Machine Version if it has or can be set.
243

244
`       May call version_factory to create the version
245

246
        :return: A superclass of AbstractVersion
247
        :rtype:  ~spinn_machine.version.abstract_version.py
248
        :raises SpinnMachineException: If the cfg version is not set correctly
249
        """
250
        if cls.__data._machine_version is None:
1✔
251
            cls.__data._machine_version = version_factory()
1✔
252
        return cls.__data._machine_version
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc