def startup_parser(data): new_names = Names() new_scan = Scanner(data, new_names, True) new_devices = Devices(new_names) new_network = Network(new_names, new_devices) new_monitors = Monitors(new_names, new_devices, new_network) parse = Parser(new_names, new_devices, new_network, new_monitors, new_scan) return parse
def devices_with_items(): """Return a Devices class instance with three devices in the network.""" new_names = Names() new_devices = Devices(new_names) [AND1_ID, NOR1_ID, SW1_ID] = new_names.lookup(["And1", "Nor1", "Sw1"]) new_devices.make_device(AND1_ID, new_devices.AND, 2) new_devices.make_device(NOR1_ID, new_devices.NOR, 16) new_devices.make_device(SW1_ID, new_devices.SWITCH, 0) return new_devices
def network_with_devices(): """Return a Network class instance with three devices in the network.""" new_names = Names() new_devices = Devices(new_names) new_network = Network(new_names, new_devices) [SW1_ID, SW2_ID, OR1_ID] = new_names.lookup(["Sw1", "Sw2", "Or1"]) # Add devices new_devices.make_device(SW1_ID, new_devices.SWITCH, 0) new_devices.make_device(SW2_ID, new_devices.SWITCH, 0) new_devices.make_device(OR1_ID, new_devices.OR, 2) return new_network
def new_monitors(): """Return a Monitors class instance with monitors set on three outputs.""" new_names = Names() new_devices = Devices(new_names) new_network = Network(new_names, new_devices) new_monitors = Monitors(new_names, new_devices, new_network) [SW1_ID, SW2_ID, OR1_ID, I1, I2] = new_names.lookup(["Sw1", "Sw2", "Or1", "I1", "I2"]) # Add 2 switches and an OR gate new_devices.make_device(SW1_ID, new_devices.SWITCH, 0) new_devices.make_device(SW2_ID, new_devices.SWITCH, 0) new_devices.make_device(OR1_ID, new_devices.OR, 2) # Make connections new_network.make_connection(SW1_ID, None, OR1_ID, I1) new_network.make_connection(SW2_ID, None, OR1_ID, I2) # Set monitors new_monitors.make_monitor(SW1_ID, None) new_monitors.make_monitor(SW2_ID, None) new_monitors.make_monitor(OR1_ID, None) return new_monitors
def CheckText(self, event): self.names = Names() self.devices = Devices(self.names) self.network = Network(self.names, self.devices) self.monitors = Monitors(self.names, self.devices, self.network) self.scanner = Scanner(self.input_text.GetValue(), self.names, True) self.parser = Parser(self.names, self.devices, self.network, self.monitors, self.scanner) status = None # try: status = self.parser.parse_network() # except: # pass if self.scanner.total_error_string == "": self.error_text.Clear() self.error_text.AppendText(_("No errors found")) else: self.error_text.Clear() self.error_text.AppendText(self.scanner.total_error_string) self.error_text.SetStyle(0, -1, wx.TextAttr(wx.RED)) self.middle_panel.Hide() self.right_panel.Hide() self.Layout() return if status == True and len(self.devices.devices_list) > 0: self.error_text.Clear() self.middle_sizer.Clear(True) self.middle_panel.Update() try: self.right_sizer.Remove(1) except: pass self.right_panel.Update() middle_heading = wx.StaticText(self.middle_panel, label=_("Options")) middle_heading = self.style(middle_heading, self.header_font) self.middle_sizer.Add(middle_heading, 0, wx.ALL | wx.ALIGN_CENTER, 10) self.toggle_right_panel = wx.ToggleButton( self.middle_panel, label=_("show circuit (experimental)")) self.toggle_right_panel.Bind(wx.EVT_TOGGLEBUTTON, self.OnRightPanelToggle) self.middle_sizer.Add(self.toggle_right_panel, 0, wx.ALL | wx.ALIGN_RIGHT, 5) device_info = wx.FlexGridSizer(4, 0, 10) # ------------- HEADINGS ------------- # label = wx.StaticText(self.middle_panel, label=_("Name")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Type")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Inputs")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Outputs")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) # ---------------- TABLE --------------- # for device in self.devices.devices_list: name = self.devices.names.get_name_string(device.device_id) # DEVICE NAME label = wx.StaticText(self.middle_panel, label=self.devices.names.get_name_string( device.device_id)) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # DEVICE TYPE label = wx.StaticText(self.middle_panel, label=self.devices.names.get_name_string( device.device_kind)) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # INPUT NAMES s = "" for i in device.inputs: s = s + '{}.{}\n'.format(name, self.names.get_name_string(i)) s = s[:-1] label = wx.StaticText(self.middle_panel, label=s) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # MONITOR OPTIONS # TODO: make them do somwthing if device.device_kind == self.devices.D_TYPE: device.monitor_btn = wx.ToggleButton( self.middle_panel, label="monitor {}.Q".format(name)) device.monitor_btn_bar = wx.ToggleButton( self.middle_panel, label="monitor {}.QBAR".format(name)) device.monitor_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn.SetForegroundColour('white') device.monitor_btn_bar.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn_bar.SetForegroundColour('white') row = wx.BoxSizer(wx.VERTICAL) row.Add( device.monitor_btn, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) row.Add( device.monitor_btn_bar, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) if name + '.Q' in self.monitors.get_signal_names()[0]: device.monitor_btn.SetValue(True) device.monitor_btn.SetBackgroundColour('#3ac10d') else: device.monitor_btn.SetBackgroundColour('#e0473a') if name + '.QBAR' in self.monitors.get_signal_names()[0]: device.monitor_btn_bar.SetValue(True) device.monitor_btn_bar.SetBackgroundColour('#3ac10d') else: device.monitor_btn_bar.SetBackgroundColour('#e0473a') device_info.Add( row, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) else: device.monitor_btn = wx.ToggleButton( self.middle_panel, label="monitor {}".format(name)) device.monitor_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn.SetForegroundColour('white') if name in self.monitors.get_signal_names()[0]: device.monitor_btn.SetValue(True) device.monitor_btn.SetBackgroundColour('#3ac10d') else: device.monitor_btn.SetBackgroundColour('#e0473a') device_info.Add( device.monitor_btn, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) # ----------- SET INITIAL SWITCH STATES ------------ # self.switch_options = wx.FlexGridSizer(2, 0, 30) for device in self.devices.devices_list: if device.device_kind != self.devices.SWITCH: continue name = self.devices.names.get_name_string(device.device_id) label = wx.StaticText(self.middle_panel, 1, label=name) label = self.style(label, self.label_font) self.switch_options.Add(label, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) device.switch_btn = wx.ToggleButton( self.middle_panel, label=_("initial switch state")) device.switch_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.switch_btn.SetForegroundColour('white') if device.switch_state: device.switch_btn.SetValue(True) device.switch_btn.SetBackgroundColour('#3ac10d') else: device.switch_btn.SetBackgroundColour('#e0473a') self.switch_options.Add(device.switch_btn, 1, wx.ALL, 5) self.middle_sizer.Insert(1, self.switch_options, 0, wx.ALL | wx.ALIGN_CENTER, 30) self.middle_sizer.Insert(1, wx.StaticLine(self.middle_panel), 0, wx.EXPAND, 5) self.middle_sizer.Insert(1, device_info, 0, wx.ALL | wx.ALIGN_CENTER, 30) row = wx.BoxSizer(wx.HORIZONTAL) simulate_btn = wx.Button(self.middle_panel, label=_("Simulate in 2D")) simulate_btn.name = '2D' simulate_btn.Bind(wx.EVT_BUTTON, self.newSimulate, simulate_btn) row.Add(simulate_btn, 1, wx.EXPAND, 5) simulate_btn3 = wx.Button(self.middle_panel, label=_("Simulate in 3D")) simulate_btn3.name = '3D' simulate_btn3.Bind(wx.EVT_BUTTON, self.newSimulate, simulate_btn3) row.Add(simulate_btn3, 1, wx.EXPAND, 5) self.middle_sizer.Add(row, 0, wx.EXPAND | wx.ALIGN_CENTER, 30) self.middle_panel.Show() self.canvas = CircuitDiagram(self.right_panel, self.devices, self.network, self.names) self.right_sizer.Clear() self.right_sizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 0) self.Layout()
class Gui(wx.Frame): # main options screen def __init__(self, title): """Initialise widgets and layout.""" super().__init__(parent=None, title=title) print(os.getcwd()) self.SetIcon(wx.Icon('./main_project/.GUI/CUED Software.png')) self.Maximize(True) self.SetBackgroundColour((186, 211, 255)) self.header_font = wx.Font(25, wx.FONTFAMILY_SWISS, wx.NORMAL, wx.FONTWEIGHT_BOLD, False) self.label_font = wx.Font(10, wx.FONTFAMILY_SWISS, wx.NORMAL, wx.NORMAL, False) self.makeLeftSizer() self.makeMiddleSizer() self.makeRightSizer() outer = wx.BoxSizer(wx.VERTICAL) self.main_sizer = wx.BoxSizer(wx.HORIZONTAL) self.main_sizer.Add(self.left_panel, 3, wx.ALL | wx.EXPAND, 20) self.main_sizer.Add(self.middle_panel, 3, wx.ALL | wx.EXPAND, 20) self.main_sizer.Add(self.right_panel, 3, wx.ALL | wx.EXPAND, 20) helpBtn = wx.Button(self, wx.ID_ANY, _("Help")) helpBtn.Bind(wx.EVT_BUTTON, self.open_help) outer.Add(helpBtn, 0, wx.ALL | wx.ALIGN_RIGHT, 0) outer.Add(self.main_sizer, 0, wx.EXPAND | wx.ALL, 0) self.SetSizer(outer) def makeLeftSizer(self): self.left_panel = wx.Panel(self) self.left_panel.SetBackgroundColour((37, 103, 209)) self.load_btn = wx.Button(self.left_panel, wx.ID_ANY, _("Browse Files")) self.check_btn = wx.Button(self.left_panel, wx.ID_ANY, _('Verify Code')) left_heading = wx.StaticText(self.left_panel, -1, label=_("Editor")) left_heading = self.style(left_heading, self.header_font) editor_font = wx.Font(14, wx.MODERN, wx.NORMAL, wx.NORMAL, False, u'Consolas') self.input_text = wx.stc.StyledTextCtrl(self.left_panel, size=(-1, wx.ALL)) self.input_text.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) self.input_text.SetMarginWidth(3, 15) self.input_text.SetUseHorizontalScrollBar(False) self.input_text.StyleSetFont(0, editor_font) self.input_text.AppendText("DEVICES {\n\n}\nCONNECTIONS {\n\n}") self.error_text = wx.TextCtrl( self.left_panel, wx.ID_ANY, size=(-1, wx.ALL), style=wx.TE_MULTILINE | wx.TE_READONLY, value=_("Click 'Verify Code' to check for errors")) self.error_text.SetFont(editor_font) self.error_text.SetStyle(0, -1, wx.TextAttr(wx.RED)) self.left_sizer = wx.BoxSizer(wx.VERTICAL) self.left_sizer.Add(left_heading, 0, wx.ALL | wx.ALIGN_CENTER, 10) row = wx.BoxSizer(wx.HORIZONTAL) row.Add(self.load_btn, 1, wx.ALIGN_LEFT, 5) row.Add(self.check_btn, 1, wx.ALIGN_RIGHT, 5) self.left_sizer.Add(row, 0, wx.ALL | wx.ALIGN_CENTER, 5) self.left_sizer.Add(self.input_text, 6, wx.EXPAND | wx.ALL, 10) self.left_sizer.Add(self.error_text, 1, wx.EXPAND | wx.ALL, 10) self.left_panel.SetSizer(self.left_sizer) self.load_btn.Bind(wx.EVT_BUTTON, self.LoadFile) self.check_btn.Bind(wx.EVT_BUTTON, self.CheckText) def makeMiddleSizer(self): self.middle_panel = wx.lib.scrolledpanel.ScrolledPanel(self) self.middle_panel.SetBackgroundColour((37, 103, 209)) self.middle_panel.SetupScrolling(scroll_x=False) self.middle_sizer = wx.BoxSizer(wx.VERTICAL) self.middle_panel.SetSizer(self.middle_sizer) self.middle_panel.Hide() self.Layout() def makeRightSizer(self): self.right_panel = wx.Panel(self) self.right_panel.SetBackgroundColour('white') self.right_sizer = wx.BoxSizer(wx.VERTICAL) self.right_panel.SetSizer(self.right_sizer) self.right_panel.Hide() self.Layout() def CheckText(self, event): self.names = Names() self.devices = Devices(self.names) self.network = Network(self.names, self.devices) self.monitors = Monitors(self.names, self.devices, self.network) self.scanner = Scanner(self.input_text.GetValue(), self.names, True) self.parser = Parser(self.names, self.devices, self.network, self.monitors, self.scanner) status = None # try: status = self.parser.parse_network() # except: # pass if self.scanner.total_error_string == "": self.error_text.Clear() self.error_text.AppendText(_("No errors found")) else: self.error_text.Clear() self.error_text.AppendText(self.scanner.total_error_string) self.error_text.SetStyle(0, -1, wx.TextAttr(wx.RED)) self.middle_panel.Hide() self.right_panel.Hide() self.Layout() return if status == True and len(self.devices.devices_list) > 0: self.error_text.Clear() self.middle_sizer.Clear(True) self.middle_panel.Update() try: self.right_sizer.Remove(1) except: pass self.right_panel.Update() middle_heading = wx.StaticText(self.middle_panel, label=_("Options")) middle_heading = self.style(middle_heading, self.header_font) self.middle_sizer.Add(middle_heading, 0, wx.ALL | wx.ALIGN_CENTER, 10) self.toggle_right_panel = wx.ToggleButton( self.middle_panel, label=_("show circuit (experimental)")) self.toggle_right_panel.Bind(wx.EVT_TOGGLEBUTTON, self.OnRightPanelToggle) self.middle_sizer.Add(self.toggle_right_panel, 0, wx.ALL | wx.ALIGN_RIGHT, 5) device_info = wx.FlexGridSizer(4, 0, 10) # ------------- HEADINGS ------------- # label = wx.StaticText(self.middle_panel, label=_("Name")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Type")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Inputs")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) label = wx.StaticText(self.middle_panel, label=_("Outputs")) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL, 0) # ---------------- TABLE --------------- # for device in self.devices.devices_list: name = self.devices.names.get_name_string(device.device_id) # DEVICE NAME label = wx.StaticText(self.middle_panel, label=self.devices.names.get_name_string( device.device_id)) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # DEVICE TYPE label = wx.StaticText(self.middle_panel, label=self.devices.names.get_name_string( device.device_kind)) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # INPUT NAMES s = "" for i in device.inputs: s = s + '{}.{}\n'.format(name, self.names.get_name_string(i)) s = s[:-1] label = wx.StaticText(self.middle_panel, label=s) label = self.style(label, self.label_font) device_info.Add(label, 0, wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) # MONITOR OPTIONS # TODO: make them do somwthing if device.device_kind == self.devices.D_TYPE: device.monitor_btn = wx.ToggleButton( self.middle_panel, label="monitor {}.Q".format(name)) device.monitor_btn_bar = wx.ToggleButton( self.middle_panel, label="monitor {}.QBAR".format(name)) device.monitor_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn.SetForegroundColour('white') device.monitor_btn_bar.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn_bar.SetForegroundColour('white') row = wx.BoxSizer(wx.VERTICAL) row.Add( device.monitor_btn, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) row.Add( device.monitor_btn_bar, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) if name + '.Q' in self.monitors.get_signal_names()[0]: device.monitor_btn.SetValue(True) device.monitor_btn.SetBackgroundColour('#3ac10d') else: device.monitor_btn.SetBackgroundColour('#e0473a') if name + '.QBAR' in self.monitors.get_signal_names()[0]: device.monitor_btn_bar.SetValue(True) device.monitor_btn_bar.SetBackgroundColour('#3ac10d') else: device.monitor_btn_bar.SetBackgroundColour('#e0473a') device_info.Add( row, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) else: device.monitor_btn = wx.ToggleButton( self.middle_panel, label="monitor {}".format(name)) device.monitor_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.monitor_btn.SetForegroundColour('white') if name in self.monitors.get_signal_names()[0]: device.monitor_btn.SetValue(True) device.monitor_btn.SetBackgroundColour('#3ac10d') else: device.monitor_btn.SetBackgroundColour('#e0473a') device_info.Add( device.monitor_btn, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 5) # ----------- SET INITIAL SWITCH STATES ------------ # self.switch_options = wx.FlexGridSizer(2, 0, 30) for device in self.devices.devices_list: if device.device_kind != self.devices.SWITCH: continue name = self.devices.names.get_name_string(device.device_id) label = wx.StaticText(self.middle_panel, 1, label=name) label = self.style(label, self.label_font) self.switch_options.Add(label, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) device.switch_btn = wx.ToggleButton( self.middle_panel, label=_("initial switch state")) device.switch_btn.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick) device.switch_btn.SetForegroundColour('white') if device.switch_state: device.switch_btn.SetValue(True) device.switch_btn.SetBackgroundColour('#3ac10d') else: device.switch_btn.SetBackgroundColour('#e0473a') self.switch_options.Add(device.switch_btn, 1, wx.ALL, 5) self.middle_sizer.Insert(1, self.switch_options, 0, wx.ALL | wx.ALIGN_CENTER, 30) self.middle_sizer.Insert(1, wx.StaticLine(self.middle_panel), 0, wx.EXPAND, 5) self.middle_sizer.Insert(1, device_info, 0, wx.ALL | wx.ALIGN_CENTER, 30) row = wx.BoxSizer(wx.HORIZONTAL) simulate_btn = wx.Button(self.middle_panel, label=_("Simulate in 2D")) simulate_btn.name = '2D' simulate_btn.Bind(wx.EVT_BUTTON, self.newSimulate, simulate_btn) row.Add(simulate_btn, 1, wx.EXPAND, 5) simulate_btn3 = wx.Button(self.middle_panel, label=_("Simulate in 3D")) simulate_btn3.name = '3D' simulate_btn3.Bind(wx.EVT_BUTTON, self.newSimulate, simulate_btn3) row.Add(simulate_btn3, 1, wx.EXPAND, 5) self.middle_sizer.Add(row, 0, wx.EXPAND | wx.ALIGN_CENTER, 30) self.middle_panel.Show() self.canvas = CircuitDiagram(self.right_panel, self.devices, self.network, self.names) self.right_sizer.Clear() self.right_sizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 0) self.Layout() def newSimulate(self, event): name = event.GetEventObject().name if name == '3D': self.SimulateWindow = SimulatePage(self, True) elif name == '2D': self.SimulateWindow = SimulatePage(self, False) self.SimulateWindow.Show() self.monitors.reset_monitors() for device in self.devices.devices_list: if hasattr(device, 'monitor_btn'): if device.monitor_btn.GetValue(): if device.device_kind == self.devices.D_TYPE: self.monitors.make_monitor(device.device_id, self.names.query("Q")) else: self.monitors.make_monitor(device.device_id, None) if hasattr(device, 'monitor_btn_bar'): if device.monitor_btn_bar.GetValue(): self.monitors.make_monitor(device.device_id, self.names.query("QBAR")) if hasattr(device, 'switch_btn'): if device.switch_btn.GetValue(): self.devices.set_switch(device.device_id, self.devices.HIGH) else: self.devices.set_switch(device.device_id, self.devices.LOW) self.SimulateWindow.run(2, True) def OnRightPanelToggle(self, event): obj = event.GetEventObject() if obj.GetValue(): self.right_panel.Show() else: self.right_panel.Hide() self.Layout() def OnToggleClick(self, event): obj = event.GetEventObject() if obj.GetValue(): obj.SetBackgroundColour('#3ac10d') else: obj.SetBackgroundColour('#e0473a') def style(self, obj, font, fgcolour='white', bgcolour=None): obj.SetForegroundColour(fgcolour) obj.SetBackgroundColour(bgcolour) obj.SetFont(font) return obj def LoadFile(self, event): # otherwise ask the user what new file to open with wx.FileDialog(self, "Open file", wildcard="TXT files (*.txt)|*.txt", style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: fileDialog.SetSize((120, 80)) if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind # Proceed loading the file chosen by the user pathname = fileDialog.GetPath() try: with open(pathname, 'r') as f: self.input_text.ClearAll() self.input_text.AppendText(f.read()) except IOError: wx.LogError(_("Cannot open file '%s'.") % pathname) def open_help(self, event): filepath = './main_project/.GUI/helpfile.pdf' import subprocess import os import platform if platform.system() == 'Darwin': # macOS subprocess.call(('open', filepath)) elif platform.system() == 'Windows': # Windows filepath = filepath.replace('/', '\\') os.startfile(filepath) else: # linux variants subprocess.call(('xdg-open', filepath)) event.Skip()
def new_network(): """Return a new instance of the Network class.""" new_names = Names() new_devices = Devices(new_names) return Network(new_names, new_devices)
def new_devices(): """Return a new instance of the Devices class.""" new_names = Names() return Devices(new_names)