コード例 #1
0
ファイル: main_window.py プロジェクト: SwatKat1977/secureshed
    def __init__(self, config):
        window_width = 800
        window_height = 600
        title = f"Secure Shed Power Console (Core {VERSION})"
        frame_size = (window_width, window_height)
        super().__init__(None, title=title, size=frame_size)

        self._config = config
        self._curr_page = self.PageSelection.CentralControllerPanel

        self._status_bar = None
        self._toolbar = None

        self._build_status_bar()
        self._build_toolbar()

        # Create Sizer for layout
        self._sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self._sizer)

        # Central Controller Panel
        self._central_controller_panel = CentralControllerPanel(self, config)
        self._sizer.Add(self._central_controller_panel, 1, wx.GROW)

        # Keypad Controller Panel
        self._keypad_controller_panel = KeypadControllerPanel(self, config)
        self._keypad_controller_panel.Hide()

        self._worker_thread = WorkerThread(self._keypad_controller_panel,
                                           self._central_controller_panel)
        self._worker_thread.start()

        self.Bind(wx.EVT_CLOSE, self._on_close)
コード例 #2
0
 def __init__(self, parentThread, layer, idx):
     WorkerThread.__init__(self, parentThread)
     self.layer = layer
     self.idx = idx
     self.matrix = None
     self.error = None
     self.python_version = (8 * struct.calcsize("P"))
コード例 #3
0
def main():
    # global address, client, root_port, processes, outgoing_conns

    # print(sys.argv)
    pid = int(sys.argv[1])
    # my_pid = pid
    num_processes = int(sys.argv[2])
    own_port = int(sys.argv[3])

    print(f"Got pid:{pid}, num_processes:{num_processes}, my port:{own_port}")

    # Timeouts

    coordinator_timeout_vote_req = TimeoutThread('coordinator-vote-req')
    coordinator_timeout_vote_req.start()
    print("timeout_thead started")

    m_handler = MasterHandler(pid, globals.address, own_port)
    globals.outgoing_conns[0] = m_handler

    # All incoming connections
    handler = WorkerThread(globals.address, globals.root_port + pid)
    handler.start()
    print("worker_thead started")

    globals.client = Client(pid, num_processes, send_many,
                            coordinator_timeout_vote_req)
    print("Client has been inited")
    globals.client.load_state()
    m_handler.start()
    print("master_thead started")

    coordinator_timeout_vote_req.restart()
コード例 #4
0
 def __init__(self, parentThread, layer, idx, max_zone=None, filler=0):
     WorkerThread.__init__(self, parentThread)
     self.layer = layer
     self.idx = idx
     self.max_zone = max_zone
     self.matrix = None
     self.error = None
     self.filler = filler
コード例 #5
0
 def __init__(self, parentThread, graph, result):
     WorkerThread.__init__(self, parentThread)
     self.graph = graph
     self.result = result
     self.skim_matrices = np.zeros(
         (result.zones, result.zones, result.num_skims), np.float64)
     #self.cores = cores
     self.error = None
     self.evol_bar = 0  #evol_bar
コード例 #6
0
 def init(self):
     self.src_dir = "/Users/thiruvarasans/Projects/OpenCV/face_filter/src/test/src_images"
     self.training_images_path = "/Users/thiruvarasans/Projects/OpenCV/face_filter/src/test/training_images"
     self.dest_dir = "/Users/thiruvarasans/Desktop"
     self.queue = []
     self.testImg = None
     self._windowIsClosing = 0
     self._workerThread = WorkerThread()
     self._workerThread.start()
     return self
コード例 #7
0
 def __init__(self, parentThread, layer, id_field, matrix, dl_type):
     WorkerThread.__init__(self, parentThread)
     self.layer = layer
     self.id_field = id_field
     self.matrix = matrix
     self.dl_type = dl_type
     self.error = None
     if error:
         self.error = 'Scipy and/or Numpy not installed'
     self.procedure = "ASSIGNMENT"
コード例 #8
0
class MyWindow(QMainWindow):
    progressSignal = QtCore.pyqtSignal(int, name='Progress')

    def __init__(self):
        super(MyWindow, self).__init__()
        self.progressSignal.connect(self.updateProgressSlot)
        self.initUI()
        self.__workerThread = WorkerThread(self.progressSignal,
                                           self.progressText)

    def initUI(self):
        loadUi('user_interface.ui', self)
        self.lineEditOpenPassword.setEchoMode(QLineEdit.Password)
        self.lineEditEditPassword.setEchoMode(QLineEdit.Password)
        self.progressBar = QProgressBar(self)
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)
        self.progressText = QLabel('就绪')
        self.statusBar().addWidget(self.progressText)
        self.statusBar().addPermanentWidget(self.progressBar)
        self.pushButtonSelectFiles.clicked.connect(self.selectFiles)
        self.pushButtonStart.clicked.connect(self.startWork)
        self.pushButtonQuit.clicked.connect(self.quit)

    def selectFiles(self):
        self.progressText.setText("选择文件")
        files, ok = QFileDialog.getOpenFileNames(self, "文件选择", os.getcwd(),
                                                 "Excel Files (*.xls *.xlsx)")
        self.__workerThread.setFiles(files)

    def startWork(self):
        # 保证线程相关参数已经就绪
        if not self.__workerThread.isReady():
            QMessageBox.warning(self, "文件错误", "您尚未选择文件!")
            return

        # 避免同一个线程start多次
        if self.__workerThread.isRunning():
            QMessageBox.warning(self, "正在运行", "处理正在进行中,请等待当前处理结束")
            return

        self.__workerThread.setPassWord(self.lineEditOpenPassword.text(),
                                        self.lineEditEditPassword.text())
        self.__workerThread.start()
        self.progressText.setText("正在处理...")

    def updateProgressSlot(self, progress):
        self.progressBar.setValue(progress)
        if progress >= 100:
            self.progressText.setText("处理完成")

    # 关闭前的清理工作
    def quit(self):
        self.__workerThread.exit()  # 退出子线程
        exit()
コード例 #9
0
def trackObjectsThreaded(frame, frameCopy, positions):
    """Creates thread and lock objects to reliably
	track the pucks parallelized"""
    threadList = []
    threadLock = threading.Lock()

    for p in pucks:
        thread = WorkerThread(p, frame, frameCopy, positions, threadLock)
        thread.start()
        threadList.append(thread)

    for t in threadList:
        t.join()
コード例 #10
0
 def __init__(self, parentThread, netlayer, linkid, ablength, bidirectional,
              directionfield, balength, skims, selected_only, featcount):
     WorkerThread.__init__(self, parentThread)
     self.netlayer = netlayer
     self.linkid = linkid
     self.ablength = ablength
     self.balength = balength
     self.bidirectional = bidirectional
     self.directionfield = directionfield
     self.skims = skims
     self.selected_only = selected_only
     self.features = None
     self.featcount = featcount
     self.error = None
コード例 #11
0
    def __init__(self, parentThread, flayer, tlayer, ffield, tfield, fmatch,
                 tmatch, operation):
        WorkerThread.__init__(self, parentThread)
        self.flayer = flayer
        self.tlayer = tlayer
        self.ffield = ffield
        self.tfield = tfield
        self.fmatch = fmatch
        self.tmatch = tmatch
        self.operation = operation
        self.error = None

        self.sequence_of_searches = [
            1, 5, 10, 20
        ]  # The second element of this list is the number of nearest
コード例 #12
0
    def testWorkerThreadExecutesJob(self):
        work_data = [1.111111] * 5
        test_job = Job(0, 0, work_data)
        job_queue = Queue()
        job_queue.put(test_job)
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)

        worker_thread.run()

        while worker_thread.is_alive():
            pass

        assert math.fabs(test_job.work_data[0] - 1.111111 * 1001) < 1
        assert math.fabs(test_job.work_data[-1] - 1.111111 * 1001) < 1
コード例 #13
0
    def __init__(self,
                 parentThread,
                 line_layer,
                 new_line_layer,
                 node_layer=False,
                 node_ids=False,
                 new_node_layer=False,
                 node_start=0):

        WorkerThread.__init__(self, parentThread)
        self.line_layer = line_layer
        self.node_layer = node_layer
        self.node_ids = node_ids
        self.new_node_layer = new_node_layer
        self.new_line_layer = new_line_layer
        self.node_start = node_start
        self.error = None
コード例 #14
0
 def __init__(self, parentThread, node_layer_name, link_layer_name,
              centroid_layer_name, node_ids, centroids_ids, max_length,
              max_connectors, new_line_layer_name, new_node_layer_name,
              selection_only):
     WorkerThread.__init__(self, parentThread)
     self.link_layer_name = link_layer_name
     self.node_layer_name = node_layer_name
     self.centroid_layer_name = centroid_layer_name
     self.node_ids = node_ids
     self.centroids_ids = centroids_ids
     if max_length is None:
         max_length = 1000000000000
     self.max_length = max_length
     self.max_connectors = max_connectors
     self.new_line_layer_name = new_line_layer_name
     self.new_node_layer_name = new_node_layer_name
     self.selection_only = selection_only
     self.error = None
コード例 #15
0
    def __init__(self,
                 parentThread,
                 matrix,
                 graph,
                 results,
                 method,
                 skims=None,
                 critical=None):
        WorkerThread.__init__(self, parentThread)

        self.matrix = matrix
        self.graph = graph
        self.results = results
        self.method = method
        self.skims = skims
        self.critical = critical
        self.error = None
        self.all_threads = {}
        self.performed = 0
        self.report = []
コード例 #16
0
    def testWorkerThreadExecutesSequentialJobs(self):
        work_data_1 = [1.111111] * 5
        work_data_2 = [0] * 5
        test_jobs = [Job(0, 0, work_data_1), Job(0, 0, work_data_2)]
        job_queue = Queue()
        job_queue.put(test_jobs[0])
        job_queue.put(test_jobs[1])
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)

        try:
            worker_thread.run()
        except:
            pass

        while worker_thread.is_alive():
            pass

        self.assertEqual(int(test_jobs[0].work_data[0]), 1112)
        self.assertEqual(int(test_jobs[1].work_data[0]), 1111)
コード例 #17
0
    def testHardwareMonitorCpuUsageIncreasesWithWorkload(self):
        work_data = [1.111111] * 10000
        test_job = Job(0, 0, work_data)
        job_queue = Queue()
        job_queue.put(test_job)
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)
        monitor = HardwareMonitor(worker_thread)

        monitor.start()
        time.sleep(0.5)
        clean_cpu_usage = monitor.get_cpu_usage()

        worker_thread.run()

        while worker_thread.is_alive():
            pass
        dirty_cpu_usage = monitor.get_cpu_usage()
        monitor.stop()

        assert dirty_cpu_usage > clean_cpu_usage
コード例 #18
0
    def testHardwareMonitorCpuUsageDecreasesWithThrottling(self):
        work_data_1 = [1.111111] * 10000
        work_data_2 = [1.111111] * 10000
        test_jobs = [Job(0, 0, work_data_1), Job(0, 0, work_data_2)]
        job_queue = Queue()
        job_queue.put(test_jobs[0])
        job_queue.put(test_jobs[1])
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)
        monitor = HardwareMonitor(worker_thread)

        monitor.start()
        try:
            worker_thread.run()
        except:
            pass
        while worker_thread.is_alive():
            pass
        full_cpu_usage = monitor.get_cpu_usage()
        monitor.stop()

        work_data_1 = [1.111111] * 10000
        work_data_2 = [1.111111] * 10000
        test_jobs = [Job(0, 0, work_data_1), Job(0, 0, work_data_2)]
        job_queue = Queue()
        job_queue.put(test_jobs[0])
        job_queue.put(test_jobs[1])
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)
        worker_thread.throttling = 20

        monitor.start()
        try:
            worker_thread.run()
        except:
            pass
        while worker_thread.is_alive():
            pass

        throttled_cpu_usage = monitor.get_cpu_usage()
        monitor.stop()

        assert throttled_cpu_usage < full_cpu_usage
コード例 #19
0
    def testWorkerThreadThrottleIncreasesExecutionTime(self):
        work_data_1 = [1.111111] * 100
        work_data_2 = [1.111111] * 100
        test_jobs = [Job(0, 0, work_data_1), Job(0, 0, work_data_2)]
        job_queue = Queue()
        job_queue.put(test_jobs[0])
        job_queue.put(test_jobs[1])
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)

        start_time = time.time()
        try:
            worker_thread.run()
        except:
            pass

        while worker_thread.is_alive():
            pass

        unthrottled_execution_time = time.time() - start_time

        work_data_1 = [1.111111] * 100
        work_data_2 = [1.111111] * 100
        test_jobs = [Job(0, 0, work_data_1), Job(0, 0, work_data_2)]
        job_queue = Queue()
        job_queue.put(test_jobs[0])
        job_queue.put(test_jobs[1])
        launcher = MockLauncher()
        worker_thread = WorkerThread(job_queue, launcher)
        worker_thread.throttling = 50

        start_time = time.time()
        try:
            worker_thread.run()
        except:
            pass

        while worker_thread.is_alive():
            pass

        throttled_execution_time = time.time() - start_time

        assert unthrottled_execution_time < throttled_execution_time
コード例 #20
0
def main():
    nfuncs = range(len(funcs))

    print('***SINGLE THREAD')
    s = time.time()
    for i in nfuncs:
        print(funcs[i](n))
    print('TAKES %s' % (time.time() - s))

    print("*** MULTIPLE THREAD")
    threads = []
    for i in nfuncs:
        t = WorkerThread(funcs[i], (n, ), funcs[i].__name__)
        threads.append(t)

    s = time.time()
    for t in threads:
        t.start()

    for t in threads:
        t.join()
        print(t.get_result())
    print('TAKES %s' % (time.time() - s))
コード例 #21
0
 def __init__(self, parentThread, layer, idx):
     WorkerThread.__init__(self, parentThread)
     self.layer = layer
     self.idx = idx
     self.matrix = None
     self.error = None
コード例 #22
0
class FaceFilterXibController(NSWindowController):
    filetypes = ('avi', 'mkv', 'mp4')
    srcTextField = objc.IBOutlet()
    destTextField = objc.IBOutlet()
    arrayController = objc.IBOutlet()
    imageView = objc.IBOutlet()
    tableView = objc.IBOutlet()
    results = []
    _workerThread = None
    dest_dir = ""
    src_dir = ""
    queue = []
    _windowIsClosing = 0
    _workerThread = None
    testImg = None

    def init(self):
        self.src_dir = "/Users/thiruvarasans/Projects/OpenCV/face_filter/src/test/src_images"
        self.training_images_path = "/Users/thiruvarasans/Projects/OpenCV/face_filter/src/test/training_images"
        self.dest_dir = "/Users/thiruvarasans/Desktop"
        self.queue = []
        self.testImg = None
        self._windowIsClosing = 0
        self._workerThread = WorkerThread()
        self._workerThread.start()
        return self

    def windowDidLoad(self):
        NSWindowController.windowDidLoad(self)
        # res = self.performSelectorOnMainThread_withObject_waitUntilDone_("updateDisplay:", 1, 0)
        self.init()
        self.updateDisplay_()

    def awakeFromNib(self):
        if self.tableView:
            self.tableView.setTarget_(self)
            self.tableView.setDoubleAction_("showImage:")
        pass

    def windowWillClose_(self, aNotification):
        """
        Clean up when the document window is closed.
        """
        # We must stop the worker thread and wait until it actually finishes before
        # we can allow the window to close. Weird stuff happens if we simply let the
        # thread run. When this thread is idle (blocking in queue.get()) there is
        # no problem and we can almost instantly close the window. If it's actually
        # in the middle of working it may take a couple of seconds, as we can't
        # _force_ the thread to stop: we have to ask it to to stop itself.
        self._windowIsClosing = 1  # try to stop the thread a.s.a.p.
        self._workerThread.stop()  # signal the thread that there is no more work to do
        self._workerThread.join()  # wait until it finishes
        self.autorelease()

    @objc.IBAction
    def openSrcDirectory_(self, sender):
        panel = NSOpenPanel.openPanel()
        panel.setCanChooseDirectories_(YES)
        panel.setAllowsMultipleSelection_(NO)

        ret_value = panel.runModalForTypes_(self.filetypes)

        if ret_value and len(panel.filenames()) > 0:
            self.src_dir = panel.filenames()[0]
            NSLog("Selected source directory %s" % self.src_dir)
            self.updateDisplay_()

    @objc.IBAction
    def openDestDirectory_(self, sender):
        panel = NSOpenPanel.openPanel()
        panel.setCanChooseDirectories_(YES)
        panel.setAllowsMultipleSelection_(NO)

        ret_value = panel.runModalForTypes_(self.filetypes)

        if ret_value and len(panel.filenames()) > 0:
            self.dest_dir = panel.filenames()[0]
            NSLog("Selected ouput directory %s" % self.dest_dir)
            self.updateDisplay()

    def updateDisplay_(self, a=None):
        self.srcTextField.setStringValue_(self.src_dir)
        self.destTextField.setStringValue_(self.dest_dir)
        self.results = [NSDictionary.dictionaryWithDictionary_({'img_path': x['img_path'], 'name': os.path.basename(x['img_path']), 'label': x['label'], 'confidence': x['confidence']}) for x in self.queue]
        self.arrayController.rearrangeObjects()
        if self.testImg != None:
            self.imageView.setImage_(self.testImg)
        else:
            self.imageView.setImage_(None)
        return a

    @objc.IBAction
    def startScan_(self, sender):
        self.training_images_path = os.path.normpath(os.path.join(self.src_dir, "../training_images"))
        if not self.is_valid():
            return

        self._workerThread.scheduleWork(self.doScan)

    def doScan(self):
        if self._windowIsClosing:
            return
        self.testImg = None
        self.updateDisplay_()

        rec = FaceRec(self.training_images_path, self.src_dir)
        filtered_images = rec.filter()
        self.queue = [{'img_path': img_path, 'label': label, 'confidence': confidence} for img_path,label,confidence in filtered_images]
        self.performSelectorOnMainThread_withObject_waitUntilDone_("updateDisplay:", 1, 0)

    def is_valid(self):
        if len(self.src_dir) == 0 \
                or len(self.dest_dir) == 0 \
                or len(self.training_images_path) == 0 \
                or not os.path.exists(self.training_images_path) \
                or not os.path.exists(self.src_dir) \
                or not os.path.exists(self.dest_dir):
            NSLog("Invalid folder selection!")
            return False
        return True

    def showImage_(self,sender):
        # NSLog("doubleClick! %d, %d", sender.clickedColumn(), sender.clickedRow())
        rowIndex = sender.clickedRow()
        if rowIndex == -1:
            return

        row = self.arrayController.arrangedObjects()[rowIndex]
        source_image = row['img_path']
        self.testImg = NSImage.alloc().initWithContentsOfFile_(source_image)
        self.updateDisplay_()
コード例 #23
0
api_key_secret = "BBB"
access_token = "CCC"
access_token_secret = "DDD"

if __name__ == '__main__':
    if api_key == "AAA" or api_key_secret == "BBB" or access_token == "CCC" or access_token_secret == "DDD":
        print("Please enter valid twitter api keys and access tokens")
        sys.exit()
    account = input(
        "Please enter twitter account name you want to monitor(exclude @, i.e. @BillGates, you should enter BillGates): "
    )
    if not account:
        print("Please enter valid account and start application again")
        sys.exit()
    new_command = None
    worker = WorkerThread(account, api_key, api_key_secret, access_token,
                          access_token_secret)
    while new_command != 'quit':
        new_command = input("please enter run, dump or quit: ")
        if new_command == 'run':
            try:
                worker.start()
            except:
                print(f"Error: unable to start thread.")
        elif new_command == 'dump':
            print(f"Currently collected tweets - {total_tweets}")
        elif new_command == 'quit':
            worker.stop()
            print("Quit application.")
        else:
            print("Invalid command, please enter run, dump or quit.")
コード例 #24
0
ファイル: main_window.py プロジェクト: SwatKat1977/secureshed
class MainWindow(wx.Frame):
    # pylint: disable=too-few-public-methods
    # pylint: disable=too-many-instance-attributes

    ## Enumeration for current page selected.
    class PageSelection(enum.Enum):
        CentralControllerPanel = 0
        KeypadControllerPanel = 1

    ## MainWindow class constructor.
    #  @param self The object pointer.
    #  @param config Instance of a configuration object.
    def __init__(self, config):
        window_width = 800
        window_height = 600
        title = f"Secure Shed Power Console (Core {VERSION})"
        frame_size = (window_width, window_height)
        super().__init__(None, title=title, size=frame_size)

        self._config = config
        self._curr_page = self.PageSelection.CentralControllerPanel

        self._status_bar = None
        self._toolbar = None

        self._build_status_bar()
        self._build_toolbar()

        # Create Sizer for layout
        self._sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self._sizer)

        # Central Controller Panel
        self._central_controller_panel = CentralControllerPanel(self, config)
        self._sizer.Add(self._central_controller_panel, 1, wx.GROW)

        # Keypad Controller Panel
        self._keypad_controller_panel = KeypadControllerPanel(self, config)
        self._keypad_controller_panel.Hide()

        self._worker_thread = WorkerThread(self._keypad_controller_panel,
                                           self._central_controller_panel)
        self._worker_thread.start()

        self.Bind(wx.EVT_CLOSE, self._on_close)

    def update_keypad_status(self, new_state_str):
        keypad_status = f"Keypad: {new_state_str}"
        self._status_bar.SetStatusText(keypad_status, 0)

    #  @param self The object pointer.
    def _build_status_bar(self):
        self._status_bar = self.CreateStatusBar()
        self._status_bar.SetFieldsCount(2)

        keypad_status = "Keypad: DISCONNECTED"
        self._status_bar.SetStatusText(keypad_status, 0)

        controller_status = "Controller: DISCONNECTED"
        self._status_bar.SetStatusText(controller_status, 1)

    #  @param self The object pointer.
    def _build_toolbar(self):
        self._toolbar = self.CreateToolBar(wx.TB_HORIZONTAL)
        self._toolbar.SetToolBitmapSize(wx.Size(48, 48))

        keypad_ctrl_icon = wx.Bitmap(KEYPAD_CTRL_TOOLBAR_IMG,
                                     wx.BITMAP_TYPE_PNG)
        btn_keypad = self._toolbar.AddTool(ID_TOOLBAR_KEYPAD_CTRL,
                                           "Keypad Controller",
                                           keypad_ctrl_icon)

        central_ctrl_icon = wx.Bitmap(CENTRAL_CTRL_TOOLBAR_IMG,
                                      wx.BITMAP_TYPE_PNG)
        btn_central = self._toolbar.AddTool(ID_TOOLBAR_CENTRAL_CTRL,
                                            "Central Controller",
                                            central_ctrl_icon)

        # Bind toolbar events
        self.Bind(wx.EVT_TOOL, self._on_central_controller_click, btn_central)
        self.Bind(wx.EVT_TOOL, self._on_keypad_controller_click, btn_keypad)

        self._toolbar.Realize()

    #  @param self The object pointer.
    #  @param event Unused.
    def _on_central_controller_click(self, event):

        #  If current page is same as what is selected then do nothing.
        if self._curr_page == self.PageSelection.CentralControllerPanel:
            return

        # Detach current page.
        self._sizer.Detach(0)

        # If the current page is 'Keypad' then hide it.
        if self._curr_page == self.PageSelection.KeypadControllerPanel:
            self._keypad_controller_panel.Hide()

        # Add the Test Plan panel to the sizer control.
        self._sizer.Prepend(self._central_controller_panel, 1, wx.GROW)

        # Set the Central Controller Panel to be displayed.
        self._central_controller_panel.Show()

        # Set the current activate page
        self._curr_page = self.PageSelection.CentralControllerPanel

        # Update the sizer control and refresh.
        self._sizer.Layout()
        self._central_controller_panel.Refresh()

    #  @param self The object pointer.
    #  @param event Unused.
    def _on_keypad_controller_click(self, event):

        #  If current page is same as what is selected then do nothing.
        if self._curr_page == self.PageSelection.KeypadControllerPanel:
            return

        # Detach current page.
        self._sizer.Detach(0)

        # If the current page is 'Central Controller' then hide it.
        if self._curr_page == self.PageSelection.CentralControllerPanel:
            self._central_controller_panel.Hide()

        # Add the Keypad Controller panel to the sizer control.
        self._sizer.Prepend(self._keypad_controller_panel, 1, wx.GROW)

        # Set the Keypad Controller Panel to be displayed.
        self._keypad_controller_panel.Show()

        # Set the current activate page
        self._curr_page = self.PageSelection.KeypadControllerPanel

        # Update the sizer control and refresh.
        self._sizer.Layout()
        self._keypad_controller_panel.Refresh()

    # Event when the main dialog is closed.  Ensure that the update timer is
    # stopped.
    #  @param self The object pointer.
    #  @param event Required, but not used.
    def _on_close(self, event):
        self._worker_thread.request_shutdown()

        while not self._worker_thread.shutdown_completed:
            time.sleep(1)

        self.Destroy()
コード例 #25
0
ファイル: jgui.py プロジェクト: fmcphail/jaide
    def go(self, event):
        """ Purpose: This function is called when the user clicks on the 'Run Script' button. It inserts output 
                     letting the user know the script has started, spawns a subprocess running a WorkerThread instance.
                     It also builds and presents the user with the jaide.py commmand,  and modifies the different buttons
                      availability, now that the script has started.

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
        """
        # This checks the input validation and only continues if we return true. 
        if self.input_validation():
            # puts cursor at end of text field
            self.output_area.mark_set(tk.INSERT, tk.END)
            self.write_to_output_area("\n****** Process Starting ******\n")

            # Gets username/password/ip from appropriate StringVars
            username = self.username_entry.get().strip()
            password = self.password_entry.get().strip()
            ip = self.ip_entry.get()
            timeout = self.timeout_entry.get()
            if self.wtf_checkbox.get() == 1:  # test if write to file is checked.
                wtf = self.wtf_entry.get() 
            else:
                wtf = ""

            # Looks up the selected option from dropdown against the conversion dictionary to get the right Jaide function to call
            function = self.option_conversion[self.option_value.get()]

            # start building the jaide command to let the user know how they can use the CLI tool to do the same thing.
            jaide_command = 'python jaide.py -u ' + username + ' -i ' + ip
            options = {
                    "Operational Command(s)" : ' -c ',
                    "Interface Errors" : ' -e ',
                    "Health Check" : ' --health ',
                    "Device Info" : ' --info ',
                    "Set Command(s)" : ' -s ',
                    "SCP Files" : ' --scp ',
                    "Shell Command(s)" : ' --shell '
                }
            jaide_command += options[self.option_value.get()]  # add the argument flag for the item they've chosen in the optionMenu

            # Logic to pass appropriate variables to WorkerThread for subsequent Jaide call
            # SCP passes a dictionary which WorkerThread has logic to pull from. Done this way because the args in Jaide.copy_file are poorly ordered for handling otherwise
            if self.option_value.get() == "SCP Files":
                argsToPass = {
                        "scp_source" : self.option_entry.get(),
                        "scp_dest" : self.scp_destination_entry.get(),
                        "direction" : self.scp_direction_value.get(),
                        "write" : True,
                        "callback" : None,
                        "multi" : True
                    }
                jaide_command += self.scp_direction_value.get() + ' ' + self.option_entry.get() + ' ' + self.scp_destination_entry.get()
            # List of args that can be easily unpacked by jaide.do_netconf
            elif self.option_value.get() == 'Set Command(s)':
                jaide_command += '\"' + self.option_entry.get() + '\"'
                if self.commit_confirmed_button.get():  # Commit Confirmed
                    jaide_command += ' --confirmed ' + str(self.commit_confirmed_min_entry.get())
                    argsToPass = [self.option_entry.get(), False, True, self.commit_confirmed_min_entry.get(), False]
                elif self.commit_check_button.get():  # Commit Check
                    jaide_command += ' --check '
                    argsToPass = [self.option_entry.get(), True, True, False, False]
                elif self.commit_blank.get():  # Commit Blank. 
                    jaide_command = jaide_command.split('-s')[0] + '--blank '
                    argsToPass = [self.option_entry.get(), False, True, False, True]
                else:  # Neither confirm, check or blank, just regular commit. 
                    argsToPass = [self.option_entry.get(), False, True, False, False]
            
            elif self.option_value.get() == 'Shell Command(s)':
                jaide_command += '\"' + self.option_entry.get() + '\"'
                argsToPass = [self.option_entry.get().strip(), True, timeout]

            # The only other option left in yes_options is "Operational Command(s)". 
            elif self.option_value.get() in self.yes_options:
                jaide_command += '\"' + self.option_entry.get() + '\"'
                argsToPass = [self.option_entry.get().strip(), False, timeout]
            
            # If the function does not need any additional arguments
            elif self.option_value.get() in self.no_options:            
                argsToPass = None
            
            # If we could not figure out what we're doing, error out instead of making bogus calls to doJaide()
            # This really should never be a possibility, as long as we've coded the other parts of this if statement to catch everything.
            else:
                self.write_to_output_area("We've hit an error parsing the command you entered. Our code must be terrible.")
                return

            # print the CLI command to the user so they know how about jaide.py
            self.write_to_output_area('The following command can be used to do this same thing on the command line:\n%s' % jaide_command)
            if "|" in jaide_command:
                self.write_to_output_area('Your CLI command will have pipes, \'|\', be wary of your environment and necessary escaping.\nCheck the working-with-pipes.html file in the examples folder for more information.')
            self.write_to_output_area('\n')  # add an extra line to separate the CLI suggestion from the rest of the output. 
            
            # Create the WorkerThread class to run the Jaide functions.
            self.thread = WorkerThread(
                    argsToPass=argsToPass,
                    timeout=timeout,
                    command=function,
                    stdout_queue=self.stdout_queue,
                    ip=ip,
                    username=username,
                    password=password,
                    write_to_file=wtf
                )
            self.thread.daemon = True
            self.thread.start()

            # Change the state of the buttons now that the script is running, so the user can save the output, kill the script, etc. 
            self.go_button.configure(state="disabled")
            self.clear_button.configure(state="disabled")
            self.stop_button.configure(state="normal")
            self.save_button.configure(state="disabled")
            self.get_output()
コード例 #26
0
ファイル: jgui.py プロジェクト: fmcphail/jaide
class JaideGUI(tk.Tk):
    """ The JaideGUI class inherits the properties of the Tkinter.Tk class. This class encapsulates the entire methodology for 
        creating the visual representation seen by the user. Some functionality is enhanced with the use of other classes that 
        are imported and used, including WorkerThread (for running the jaide.py script and handling output gathering) and 
        AutoScrollbar (for putting scrollbars on the output_area text entry widget. 
    """
    def __init__(self, parent):
        """ Purpose: This is the initialization function for creating and showing the GUI. 
        """
        tk.Tk.__init__(self, parent)
        self.parent = parent

        self.grid()
        self.wm_title("Jaide GUI")
        self.focus_force()

        ### Argument and option lists for user input
        # arguments that require extra input
        self.yes_options = ["Operational Command(s)", "Set Command(s)", "Shell Command(s)", "SCP Files"]
        # arguments that don't require extra input
        self.no_options = ["Interface Errors", "Health Check", "Device Info"]
        # List of argument options
        self.options_list = ["Operational Command(s)", "Set Command(s)", "Shell Command(s)", "SCP Files", "------", "Device Info", "Health Check", "Interface Errors"]
        
        # Dictionary converting option_menu's displayed options with jaide's actual argument flags
        self.option_conversion = {
                "Device Info" : jaide.dev_info,
                "Health Check" : jaide.health_check,
                "Interface Errors" : jaide.int_errors,
                "Operational Command(s)" : jaide.multi_cmd, 
                "SCP Files" : jaide.copy_file,
                "Set Command(s)" : jaide.make_commit,
                "Shell Command(s)" : jaide.multi_cmd
            }
        # Dictionary for retrieving the help text based on the command name.
        self.help_conversion = {
                "Device Info" : "Quick Help: Device Info pulls some baseline information from the device(s), including Hostname, Model, Junos Version, and Chassis Serial Number.",
                "Health Check" : "Quick Help: Health Check runs multiple commands to get routing-engine CPU/memory info, busy processes, temperatues, and alarms. The output will likely show the mgd process using high CPU, this is normal due to the execution of the script logging in and running the commands.",
                "Interface Errors" : "Quick Help: Interface Errors will tell you of any input or output errors on active interfaces.",
                "Operational Command(s)" : "Quick Help: Run one or more operational command(s) against the device(s). This can be any non-interactive command(s) that can be run from operational mode. This includes show, request, traceroute, op scripts, etc.", 
                "SCP Files" : "Quick Help: SCP file(s) or folder(s) to or from one or more devices. Specify a source and destination file or folder. If Pulling, the source is the remote file/folder, and the destination is the local folder you are putting them. If Pushing, the source is the local file/folder, and the destination would the folder to put them on the remote device. Note, the '~' home directory link can not be used! ",
                "Set Command(s)" : "Quick Help: A single or multiple set commands that will be sent and committed to the device(s). There are three optional commit modifiers, which can be used to do a commit check, commit confirmed, or blank commit. More information in the help files.",
                "Shell Command(s)" : "Quick Help: Send one or more shell commands to the device(s). Be wary when sending shell commands, you can make instant changes or potentially harm the networking device. Care should be taken."
            }
        
        # stdout_queue is the output queue that the WorkerThread class will put output to.
        self.stdout_queue = Queue.Queue()
        # thread will be the WorkerThread instantiation.
        self.thread = ""
        # frames_shown boolean for keeping track if the upper options of the GUI are shown or not. 
        self.frames_shown = True

        ### CREATE THE TOP MENUBAR OPTIONS
        self.menubar = tk.Menu(self)
        # tearoff=0 is to prohibit windows users from being able to pop out the menus. 
        self.menu_file = tk.Menu(self.menubar, tearoff=0)
        self.menu_help = tk.Menu(self.menubar, tearoff=0)

        self.menubar.add_cascade(menu=self.menu_file, label="File")
        self.menubar.add_cascade(menu=self.menu_help, label="Help ")  # Added space after Help to prevent OSX from putting spotlight in

        # Create the File menu and appropriate keyboard shortcuts.
        self.menu_file.add_command(label="Save Template", command=lambda: self.save_template(None), accelerator='Ctrl-S')
        self.bind_all("<Control-s>", self.save_template)
        self.menu_file.add_command(label="Open Template", command=lambda: self.open_template(None), accelerator='Ctrl-O')
        self.bind_all("<Control-o>", self.open_template)
        self.menu_file.add_separator()
        self.menu_file.add_command(label="Clear Fields", command=lambda: self.clear_fields(None), accelerator='Ctrl-F')
        self.bind_all("<Control-f>", self.clear_fields)
        self.menu_file.add_command(label="Clear Output", command=lambda: self.clear_output(None), accelerator='Ctrl-W')
        self.bind_all("<Control-w>", self.clear_output)
        self.menu_file.add_command(label="Run Script", command=lambda: self.go(None), accelerator='Ctrl-R')
        self.bind_all("<Control-r>", self.go)
        self.menu_file.add_separator()
        self.menu_file.add_command(label="Quit", command=lambda: self.quit(None), accelerator='Ctrl-Q')
        self.bind_all("<Control-q>", self.quit)

        # Create the Help menu
        self.menu_help.add_command(label="About", command=self.show_about)
        self.menu_help.add_command(label="Help Text", command=self.show_help)
        self.menu_help.add_command(label="Examples", command=self.show_examples)

        # Add the menubar in.
        self.config(menu=self.menubar)

        ############################################
        # GUI frames, and all user entry widgets   #
        ############################################
        ### FRAME INITIALIZATION]
        
        # IP+Cred+Sep Frame
        # Had to do this because Grid was treating all of the frames & separators as 1x1 units
        # so without combining creds & ip in a single container frame the IP side was subject to resizing
        # based on the other frames
        self.ip_cred_frame = tk.Frame(self)

        # IP frame
        self.ip_frame = tk.Frame(self.ip_cred_frame)
        # Credentials frame
        self.creds_frame = tk.Frame(self.ip_cred_frame)
        # write to file frame
        self.wtf_frame = tk.Frame(self)
        # Options frame
        self.options_frame = tk.Frame(self)
        # Help frame
        self.help_frame = tk.Frame(self)
        # go button frame
        self.buttons_frame = tk.Frame(self)
        # output area frame
        self.output_frame = tk.Frame(self, bd=3, relief="groove")

        ##### Target device Section
        # string of actual IP or the file containing list of IPs
        self.ip_label = tk.Label(self.ip_frame, text="IP(s) / Host(s):")
        # Entry for IP or IP list
        self.ip_entry = JaideEntry(self.ip_frame)
        # Button to open file of list of IPs
        self.ip_button = tk.Button(self.ip_frame, text="Select File", command=lambda: self.open_file(self.ip_entry), takefocus=0)
        # compiled regex for testing IP address(es)
        self.ip_test = re.compile(r'^(((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(,|(,\ ))?)+$')

        #### CONNECTION TIMEOUT
        self.timeout_label = tk.Label(self.ip_frame, text="Timeout:")
        self.timeout_entry = JaideEntry(self.ip_frame, instance_type=int, contents=300)

        ##### USERNAME
        # label for Username
        self.username_label = tk.Label(self.creds_frame, text="Username: "******"Password: "******"*")

        ### WRITE TO FILE
        # Entry for Write to File
        self.wtf_entry = JaideEntry(self.wtf_frame)
        # Write to File button
        self.wtf_button = tk.Button(self.wtf_frame, text="Select File", command=self.open_wtf, takefocus=0)
        # Write to file checkbox
        self.wtf_checkbox = JaideCheckbox(self.wtf_frame, text="Write to file", command=self.check_wtf, takefocus=0)

        ### OPTIONS
        # stores which option from options_list is selected
        self.option_value = tk.StringVar()
        # sets defaulted option to first one
        self.option_value.set(self.options_list[0])
        # Actual dropdown list widget. Uses PMW because tk base doesn't allow an action to be bound to an option_menu.
        self.option_menu = Pmw.OptionMenu(self.options_frame, command=self.opt_select, menubutton_textvariable=self.option_value, items=self.options_list)
        # Prevents option_menu from taking focus while tabbing
        self.option_menu.component('menubutton').config(takefocus=0)
        # Entry field for argument modifier.
        self.option_entry = JaideEntry(self.options_frame)

        ### SCP OPTIONS
        # variable to track what is chosen in the scp_direction_menu menu
        self.scp_direction_value = tk.StringVar()
        self.scp_direction_value.set("Push")
        # scp direction menu to choose push or pull
        self.scp_direction_menu = tk.OptionMenu(self.options_frame, self.scp_direction_value, 'Push', 'Pull')
        # File load button for SCP source
        self.scp_source_button = tk.Button(self.options_frame, text="Local Source", command=lambda: self.open_file(self.option_entry), takefocus=0)
        # second file load button for SCPing
        self.scp_destination_button = tk.Button(self.options_frame, text="Local Destination", command=lambda: self.open_file(self.scp_destination_entry), takefocus=0)
        # second entry field for SCPing
        self.scp_destination_entry = JaideEntry(self.options_frame)
        
        # set_list_button is used to find a file containing a list of set commands.
        self.set_list_button = tk.Button(self.options_frame, text="Select File", command=lambda: self.open_file(self.option_entry), takefocus=0)
        
        ### COMMIT CHECK, COMMIT CONFIRMED, and COMMIT BLANK options.
        # commit check checkbox
        self.commit_check_button = JaideCheckbox(self.options_frame, text="Commit Check Only", command=lambda: self.commit_option_update('check'), takefocus=0)
        # commit confirmed checkbox and minutes entry label / field. 
        self.commit_confirmed_button = JaideCheckbox(self.options_frame, text="Commit Confirmed", command=lambda: self.commit_option_update('confirmed'), takefocus=0)
        self.commit_confirmed_min_label = tk.Label(self.options_frame, text="Minutes: ", takefocus=0) 
        # The commit confirmed minutes selector, which is a scale between 1 and 60. 
        self.commit_confirmed_min_entry = tk.Scale(self.options_frame, from_=1, to=60, orient='horizontal', takefocus=0)
        # Commit blank option
        self.commit_blank = JaideCheckbox(self.options_frame, text="Blank Commit", command=lambda: self.commit_option_update('blank'), takefocus=0)
        # These are used to keep rows 1 and 2 of options_frame from being empty and thus hidden
        self.spacer_label = tk.Label(self.options_frame, takefocus=0)

        # Help label sits next in the target device section
        self.help_value = tk.StringVar("")
        self.help_label = tk.Label(self.help_frame, textvariable=self.help_value, justify="left", anchor="nw", wraplength=750)

        ### Buttons
        self.go_button = tk.Button(self.buttons_frame, command=lambda: self.go(None), text="Run Script", takefocus=0)
        self.stop_button = tk.Button(self.buttons_frame, text="Stop Script", command=self.stop_script, state="disabled", takefocus=0)
        self.clear_button = tk.Button(self.buttons_frame, command=lambda: self.clear_output(None), text="Clear Output", state="disabled", takefocus=0)
        self.save_button = tk.Button(self.buttons_frame, command=self.save_output, text="Save Output", state="disabled", takefocus=0)
        self.toggle_frames_button = tk.Button(self.buttons_frame, command=self.toggle_frames, text="Toggle Options", takefocus=0)

        ### SCRIPT OUTPUT AREA
        self.output_area = tk.Text(self.output_frame, wrap=tk.NONE)
        self.xscrollbar = AutoScrollbar(self.output_frame, command=self.output_area.xview, orient=tk.HORIZONTAL, takefocus=0)
        self.yscrollbar = AutoScrollbar(self.output_frame, command=self.output_area.yview, takefocus=0)
        self.output_area.config(yscrollcommand=self.yscrollbar.set, xscrollcommand=self.xscrollbar.set, takefocus=0)

        # Separators
        self.sep1 = ttk.Separator(self.ip_cred_frame)
        self.sep2 = ttk.Separator(self)
        self.sep3 = ttk.Separator(self)
        self.sep4 = ttk.Separator(self)
        self.sep5 = ttk.Separator(self)

        #############################################
        # Put the objects we've created on the grid #
        # for the user to see.                      #
        #############################################
        ### INITIALIZE THE LAYOUT
        self.show_frames()
        self.rowconfigure(9, weight=1)
        self.columnconfigure(0, weight=1)
        self.output_frame.rowconfigure(0, weight=1)
        self.output_frame.columnconfigure(0, weight=1)

        ### GRIDDING FOR ALL WIDGETS VISIBLE AT FIRST LOAD.
        # Section 0 - Target Device(s) - ip_frame
        self.ip_frame.grid(column=0, row=0, sticky="NW")
        self.ip_label.grid(column=0, row=0, sticky="NW")
        self.ip_entry.grid(column=1, row=0, sticky="NW")
        self.ip_button.grid(column=2, row=0, sticky="NW")
        self.timeout_label.grid(column=0, row=1, sticky="NW")
        self.timeout_entry.grid(column=1, row=1, sticky="NW")
        self.sep1.grid(column=1, row=0, sticky="NS", padx=(18, 18))

        # Section 1 - Authentication - creds_frame
        self.creds_frame.grid(column=2, row=0, sticky="NW")
        self.username_label.grid(column=0, row=0, sticky="NW")
        self.username_entry.grid(column=1, row=0, sticky="NW")
        self.password_label.grid(column=0, row=1, sticky="NW")
        self.password_entry.grid(column=1, row=1, sticky="NW")

        # This is the help label in the frame below the options frame.
        self.help_label.grid(column=0, row=0, sticky="NWES")
        
        # Section 2 - Write to File - wtf_frame
        self.wtf_checkbox.grid(column=0, row=0, sticky="NSW")
                
        # Section 3 - Command Options - options_frame
        self.option_menu.grid(column=0, row=0, sticky="EW")
        self.spacer_label.grid(column=0, row=1, sticky="NW")
        
        # Section 4 - Action Buttons - buttons_frame
        self.go_button.grid(column=0, row=0, sticky="NW", padx=2)
        self.stop_button.grid(column=1, row=0, sticky="NW", padx=2)
        self.clear_button.grid(column=2, row=0, sticky="NW", padx=2)
        self.save_button.grid(column=3, row=0, sticky="NW", padx=2)
        self.toggle_frames_button.grid(column=4, row=0, sticky="NW", padx=2)

        # Section 5 - Output Area - output_frame
        self.output_area.grid(column=0, row=0, sticky="SWNE")
        self.output_area.columnconfigure(0, weight=100)
        self.xscrollbar.grid(column=0, row=1, sticky="SWNE")
        self.yscrollbar.grid(column=1, row=0, sticky="SWNE")
        
        # Set the window to a given size. This prevents autoscrollbar 'fluttering' behaviour, 
        # and stabilizes how the Toggle Output button behaves.
        self.geometry('800x800')

        # Sets the tab order correctly
        self.ip_frame.lift()
        self.creds_frame.lift()
        self.wtf_frame.lift()
        self.options_frame.lift()
        
        # Run the opt_select method to ensure the proper fields are shown. 
        self.opt_select(None)
        

    def go(self, event):
        """ Purpose: This function is called when the user clicks on the 'Run Script' button. It inserts output 
                     letting the user know the script has started, spawns a subprocess running a WorkerThread instance.
                     It also builds and presents the user with the jaide.py commmand,  and modifies the different buttons
                      availability, now that the script has started.

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
        """
        # This checks the input validation and only continues if we return true. 
        if self.input_validation():
            # puts cursor at end of text field
            self.output_area.mark_set(tk.INSERT, tk.END)
            self.write_to_output_area("\n****** Process Starting ******\n")

            # Gets username/password/ip from appropriate StringVars
            username = self.username_entry.get().strip()
            password = self.password_entry.get().strip()
            ip = self.ip_entry.get()
            timeout = self.timeout_entry.get()
            if self.wtf_checkbox.get() == 1:  # test if write to file is checked.
                wtf = self.wtf_entry.get() 
            else:
                wtf = ""

            # Looks up the selected option from dropdown against the conversion dictionary to get the right Jaide function to call
            function = self.option_conversion[self.option_value.get()]

            # start building the jaide command to let the user know how they can use the CLI tool to do the same thing.
            jaide_command = 'python jaide.py -u ' + username + ' -i ' + ip
            options = {
                    "Operational Command(s)" : ' -c ',
                    "Interface Errors" : ' -e ',
                    "Health Check" : ' --health ',
                    "Device Info" : ' --info ',
                    "Set Command(s)" : ' -s ',
                    "SCP Files" : ' --scp ',
                    "Shell Command(s)" : ' --shell '
                }
            jaide_command += options[self.option_value.get()]  # add the argument flag for the item they've chosen in the optionMenu

            # Logic to pass appropriate variables to WorkerThread for subsequent Jaide call
            # SCP passes a dictionary which WorkerThread has logic to pull from. Done this way because the args in Jaide.copy_file are poorly ordered for handling otherwise
            if self.option_value.get() == "SCP Files":
                argsToPass = {
                        "scp_source" : self.option_entry.get(),
                        "scp_dest" : self.scp_destination_entry.get(),
                        "direction" : self.scp_direction_value.get(),
                        "write" : True,
                        "callback" : None,
                        "multi" : True
                    }
                jaide_command += self.scp_direction_value.get() + ' ' + self.option_entry.get() + ' ' + self.scp_destination_entry.get()
            # List of args that can be easily unpacked by jaide.do_netconf
            elif self.option_value.get() == 'Set Command(s)':
                jaide_command += '\"' + self.option_entry.get() + '\"'
                if self.commit_confirmed_button.get():  # Commit Confirmed
                    jaide_command += ' --confirmed ' + str(self.commit_confirmed_min_entry.get())
                    argsToPass = [self.option_entry.get(), False, True, self.commit_confirmed_min_entry.get(), False]
                elif self.commit_check_button.get():  # Commit Check
                    jaide_command += ' --check '
                    argsToPass = [self.option_entry.get(), True, True, False, False]
                elif self.commit_blank.get():  # Commit Blank. 
                    jaide_command = jaide_command.split('-s')[0] + '--blank '
                    argsToPass = [self.option_entry.get(), False, True, False, True]
                else:  # Neither confirm, check or blank, just regular commit. 
                    argsToPass = [self.option_entry.get(), False, True, False, False]
            
            elif self.option_value.get() == 'Shell Command(s)':
                jaide_command += '\"' + self.option_entry.get() + '\"'
                argsToPass = [self.option_entry.get().strip(), True, timeout]

            # The only other option left in yes_options is "Operational Command(s)". 
            elif self.option_value.get() in self.yes_options:
                jaide_command += '\"' + self.option_entry.get() + '\"'
                argsToPass = [self.option_entry.get().strip(), False, timeout]
            
            # If the function does not need any additional arguments
            elif self.option_value.get() in self.no_options:            
                argsToPass = None
            
            # If we could not figure out what we're doing, error out instead of making bogus calls to doJaide()
            # This really should never be a possibility, as long as we've coded the other parts of this if statement to catch everything.
            else:
                self.write_to_output_area("We've hit an error parsing the command you entered. Our code must be terrible.")
                return

            # print the CLI command to the user so they know how about jaide.py
            self.write_to_output_area('The following command can be used to do this same thing on the command line:\n%s' % jaide_command)
            if "|" in jaide_command:
                self.write_to_output_area('Your CLI command will have pipes, \'|\', be wary of your environment and necessary escaping.\nCheck the working-with-pipes.html file in the examples folder for more information.')
            self.write_to_output_area('\n')  # add an extra line to separate the CLI suggestion from the rest of the output. 
            
            # Create the WorkerThread class to run the Jaide functions.
            self.thread = WorkerThread(
                    argsToPass=argsToPass,
                    timeout=timeout,
                    command=function,
                    stdout_queue=self.stdout_queue,
                    ip=ip,
                    username=username,
                    password=password,
                    write_to_file=wtf
                )
            self.thread.daemon = True
            self.thread.start()

            # Change the state of the buttons now that the script is running, so the user can save the output, kill the script, etc. 
            self.go_button.configure(state="disabled")
            self.clear_button.configure(state="disabled")
            self.stop_button.configure(state="normal")
            self.save_button.configure(state="disabled")
            self.get_output()


    def get_output(self):
        """ Purpose: This function listens to the sub process generated by the 'Run Script' button, and 
                     dumps the output to the output_area using the function write_to_output_area. If the process
                     is no longer alive, it changes the activation of buttons, and lets the user know that the script 
                     is done. 
        """
        try:  # pull from the stdout_queue, and write it to the output_area
            self.write_to_output_area(self.stdout_queue.get_nowait())
        except Queue.Empty:  # Nothing in the queue, but the thread could be still alive, try again next time around.
            pass
        if not self.thread.isAlive():  # The WorkerThread subprocess has completed, and we need to wrap up.
            while not self.stdout_queue.empty():
                self.write_to_output_area(self.stdout_queue.get_nowait())
            self.go_button.configure(state="normal")
            self.clear_button.configure(state="normal")
            self.stop_button.configure(state="disabled")
            self.save_button.configure(state="normal")
            self.write_to_output_area("\n****** Process Completed ******\n")
            self.thread.join()
            return
        self.after(100, self.get_output)  # recursively call this function every 100ms, writing any new output. 


    def input_validation(self):
        """ Purpose: This function is used to validate the inputs of the user when they press the 'Run Script' button.
                     It will return a boolean with True for passing the checks, and False if we failed the validation.
        """
        # IP address entry must be a valid IPv4 address if we're running against a single IP
        if not re.match(self.ip_test, self.ip_entry.get().strip()) and not os.path.isfile(self.ip_entry.get().strip()):
            tkMessageBox.showinfo("IP Entry", "Either an invalid IP address was entered, an invalid comma separated list of IPs, or the IP Address list file not found.")
        # Making sure the user typed something into the IP field. 
        elif self.ip_entry.get() == "":  
            tkMessageBox.showinfo("IP Entry", "Please enter an IP address or IP address list file.")
        # Ensure there is a value typed into the username and password fields.
        elif self.username_entry.get() == "" or self.password_entry.get() == "":
            tkMessageBox.showinfo("Credentials", "Please enter a username and password.")
        # If the write to file box is checked, they must have something typed in for an output file. 
        elif self.wtf_entry.get() == "" and self.wtf_checkbox.get(): 
            tkMessageBox.showinfo("Write to File", "When writing to a file, a filename must be specified.")
        # Ensure that if an option is chosen that requires extra input that they have something in the entry widget. 
        elif self.option_value.get() in self.yes_options and self.option_entry.get() == "" and self.commit_blank.get() == 0:
            tkMessageBox.showinfo("Option Input", "You chose an option that requires extra input, and didn't specify any additional information. " +
                "For example, when selecting \"Operational Command(s)\", a command string must be typed into the entry box.")
        else:  
            # Make sure the timeout value is a number. 
            try:
                isinstance(self.timeout_entry.get(), int)
            except ValueError:
                tkMessageBox.showinfo("Timeout", "A timeout value must be an integer, in seconds.")
            else:  # If all else fails, they passed.
                return True


    def show_about(self):
        """ Purpose: This will show the about text for the application.
        """
        aboutInfo = tk.Toplevel()
        aboutInfoLabel = tk.Label(aboutInfo, text="The Jaide GUI Application is a GUI wrapper for the jaide.py script.\n"
            "Version 1.0.0\n\rContributors:\n Geoff Rhodes (https://github.com/geoffrhodes) and Nathan Printz (https://github.com/nprintz)\n\rMore information about Jaide and the Jaide"
            " GUI can be found at https://github.com/NetworkAutomation/jaide\n\rThe compiled versions for Windows or Mac can be found at:"
            "\nhttps://github.com/NetworkAutomation/jaide/releases/latest", padx=50, pady=50)
        aboutInfoLabel.pack()


    def show_help(self):
        """ Purpose: This is called when the user selects the 'Help Text' menubar option. It opens the README.html file
                     in their default browser. If the file doesn't exist it opens the github readme page instead.
        """
        # Grab the directory where the script is running.
        readme = module_path()
        # Determine our OS, attach the README.html file to the path, and open that file.
        if sys.platform.startswith('darwin'):
            readme += "/README.html"
            if os.path.isfile(readme):
                subprocess.call(('open', readme))
            else:
                try:
                    webbrowser.open('https://github.com/nprintz/jaide')
                except webbrowser.Error:
                    pass
        elif os.name == 'nt':
            readme += "\\README.html"
            if os.path.isfile(readme):
                os.startfile(readme)  # this works on windows, not sure why pylint shows an error. 
            else: 
                try:
                    webbrowser.open('https://github.com/nprintz/jaide')
                except webbrowser.Error:
                    pass
        elif os.name == 'posix':
            readme += "/README.html"
            if os.path.isfile(readme):
                subprocess.call(('xdg-open', readme))
            else: 
                try:
                    webbrowser.open('https://github.com/nprintz/jaide')
                except webbrowser.Error:
                    pass


    def show_examples(self):
        """ Purpose: This method opens the example folder for the user, or open the github page for the example folder. 
        """
        # Grab the directory that the script is running from. 
        examples = module_path()
        # Determin our OS, attach the README.html file to the path, and open that file.
        if sys.platform.startswith('darwin'):
            examples += "/examples/"
            if os.path.isdir(examples):
                subprocess.call(('open', examples))
            else:
                try:
                    webbrowser.open('https://github.com/nprintz/jaide/examples')
                except webbrowser.Error:
                    pass
        elif os.name == 'nt':
            examples += "\\examples\\"
            if os.path.isdir(examples):
                os.startfile(examples)  # this works on windows, not sure why pylint shows an error. 
            else: 
                try:
                    webbrowser.open('https://github.com/nprintz/jaide/examples')
                except webbrowser.Error:
                    pass
        elif os.name == 'posix':
            examples += "/examples/"
            if os.path.isdir(examples):
                subprocess.call(('xdg-open', examples))
            else: 
                try:
                    webbrowser.open('https://github.com/nprintz/jaide/examples')
                except webbrowser.Error:
                    pass


    def write_to_output_area(self, output):
        """ Purpose: This method will insert the passed string 'output' at the end of the output_area, and will 
                     also scroll the viewable area to the bottom.
            Passed Arguments:
                output  -   String of the output to dump to the output_area
        """
        if output is not None:
            if isinstance(output, basestring):
                if output[-1:] is not "\n":
                    output = output + "\n"
                # SCP was putting None to the output queue and this throws an error with insert
                self.output_area.insert(tk.END, output)
                self.output_area.see(tk.END)


    def save_template(self, event):
        """ Purpose: asks for a file name and writes all variable information to it.
                     Passwords are obfuscated with Base64 encoding, but this is
                     by no means considered secure.

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
         """
        returnFile = tkFileDialog.asksaveasfilename()
        if returnFile:
            try:
                output_file = open(returnFile, 'wb')
            except IOError as e:
                self.write_to_output_area("Couldn't open file to save. Error: \n" + str(e))
            else:
                # Write every field to the template file. 
                output_file.write("IP:~:" + self.ip_entry.get() + "\n")
                output_file.write("Timeout:~:" + str(self.timeout_entry.get()) + "\n")
                output_file.write("Username:~:" + self.username_entry.get() + "\n")
                output_file.write("Password:~:" + base64.b64encode(self.password_entry.get()) + "\n")
                output_file.write("WriteToFileBool:~:" + str(self.wtf_checkbox.get()) + "\n")
                output_file.write("WriteToFileLoc:~:" + self.wtf_entry.get() + "\n")
                output_file.write("Option:~:" + self.option_value.get() + "\n")
                output_file.write("FirstArgument:~:" + self.option_entry.get() + "\n")
                output_file.write("SCPDest:~:" + self.scp_destination_entry.get() + "\n")
                output_file.write("SCPDirection:~:" + self.scp_direction_value.get() + "\n")
                output_file.write("CommitCheck:~:" + str(self.commit_check_button.get()) + "\n")
                output_file.write("CommitConfirmed:~:" + str(self.commit_confirmed_button.get()) + "\n")
                output_file.write("CommitConfirmedMin:~:" + str(self.commit_confirmed_min_entry.get()) + "\n")
                output_file.write("CommitBlank:~:" + str(self.commit_blank.get()) + "\n")
                output_file.close()


    def open_template(self, event):
        """ Purpose: Loads variable info from file and populates it in to GUI 

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
        """
        returnFile = tkFileDialog.askopenfilename()
        if returnFile:
            try:
                input_file = open(returnFile, "rb")
            except IOError as e:
                self.write_to_output_area("Couldn't open file to import. Error: \n" + str(e))
            else:
                input_vars = input_file.readlines()
                input_file.close()
                # Read the template file and set the fields accordingly. 
                self.ip_entry.set(input_vars[0].split(':~:')[1].rstrip())
                self.timeout_entry.set(input_vars[1].split(':~:')[1].rstrip())
                self.username_entry.set(input_vars[2].split(':~:')[1].rstrip())
                self.password_entry.set(base64.b64decode(input_vars[3].split(':~:')[1].rstrip()))
                self.wtf_checkbox.set(input_vars[4].split(':~:')[1].rstrip())
                self.wtf_entry.set(input_vars[5].split(':~:')[1].rstrip())
                self.option_value.set(input_vars[6].split(':~:')[1].rstrip())
                # Once we've set the option menu value, we need to display any appropriate field before continuing
                self.opt_select(None)
                # Now that the menu option is set, the other fields will be visible to populate.
                self.option_entry.set(input_vars[7].split(':~:')[1].rstrip())
                self.scp_destination_entry.set(input_vars[8].split(':~:')[1].rstrip())
                self.scp_direction_value.set(input_vars[9].split(':~:')[1].rstrip())
                self.commit_check_button.set(input_vars[10].split(':~:')[1].rstrip())
                self.commit_confirmed_button.set(input_vars[11].split(':~:')[1].rstrip())
                self.commit_confirmed_min_entry.set(input_vars[12].split(':~:')[1].rstrip())
                self.commit_blank.set(input_vars[13].split(':~:')[1].rstrip())
                # check wtf, commit check, and commit confirmed to see if they are checked. 
                self.check_wtf()
                self.commit_option_update('confirmed')
                self.commit_option_update('check')
                self.commit_option_update('blank')


    def stop_script(self):
        """ Purpose: Called to kill the subprocess 'jaide' which is actually running the jaide.py script. 
                     This is called when the user clicks on the Stop Script button.
        """
        self.thread.kill_proc()
        self.write_to_output_area("\n****** Attempting to stop process ******\n")



    def opt_select(self, none):
        """ Purpose: This is used to show and hide options as different items are selected from the drop down accordingly.
        """
        # First thing we do is forget all placement and deselect options, then we'll update according to what they chose afterwards.
        self.commit_check_button.grid_forget()
        self.commit_check_button.deselect()
        self.commit_confirmed_button.deselect()
        self.commit_confirmed_button.grid_forget()
        self.commit_confirmed_min_label.grid_forget()
        self.commit_confirmed_min_entry.grid_forget()
        self.commit_blank.grid_forget()
        self.option_entry.grid_forget()
        self.set_list_button.grid_forget()
        self.scp_source_button.grid_forget()
        self.scp_destination_entry.grid_forget()
        self.scp_destination_button.grid_forget()
        self.scp_direction_menu.grid_forget()    
        self.spacer_label.grid_forget()

        if self.option_value.get() == "------":
            self.option_value.set("Device Info")

        # SCP
        if self.option_value.get() == "SCP Files":
            self.scp_direction_menu.grid(column=1, columnspan=2, row=0, sticky="NW")
            self.option_entry.grid(column=0, row=1, sticky="NW")
            self.scp_source_button.grid(column=1, row=1, sticky="NW", padx=2)
            self.scp_destination_entry.grid(column=2, row=1, sticky="NW")
            self.scp_destination_button.grid(column=3, row=1, sticky="NW", padx=2)

        # Any option that requires a single text arg
        elif self.option_value.get() in self.yes_options:
            self.option_entry.grid(column=1, columnspan=2, row=0, sticky="NW")
            
            # If we are getting a list of set command, show file open button and commit check / confirmed boxes
            if self.option_value.get() == "Set Command(s)":
                self.set_list_button.grid(column=3, row=0, sticky="NW", padx=2)
                self.commit_check_button.grid(column=0, row=1, sticky="NW")
                self.commit_confirmed_button.grid(column=2, row=1, sticky="NW")
                self.commit_blank.grid(column=1, row=1, sticky="NW")
            else:
                self.spacer_label.grid(column=1, columnspan=2, row=1, sticky="NW")

            if self.option_value.get() == "Operational Command(s)":
                self.set_list_button.grid(column=3, row=0, sticky="NW", padx=2)
        else:
            # No option
            self.spacer_label.grid(column=1, columnspan=2, row=1, sticky="NW")

        # Update the help text for the new command
        self.help_value.set(self.help_conversion[self.option_value.get()])
        time.sleep(.05)  # sleep needed to avoid artifacts when updating the frames
        # Update the UI after we've made our changes
        self.update()


    def open_file(self, entry_object):
        """ Purpose: This method is used to prompt the user to find a file on their local machine that already exists. Once
                     they've selected a file, we will put the full filepath to that file in the text entry object that was 
                     passed to this method. If the user does not specify a file (ie. presses the 'cancel' button on the 
                     dialog box), then we will not update the entry field, we do nothing. 
            Parameters:
                entry_object - Tkinter.Entry object - This is the actual displayed Tkinter Entry object where the filepath 
                               that the user specifies will be dumped to. 
        """
        # ask the user for a local file, and if they give us one, replace the passed entry field. 
        returnFile = tkFileDialog.askopenfilename()
        if returnFile:
            # Deletes whatever is in the field currently
            entry_object.delete(0, tk.END)
            # Puts the selected file (w/ full path) in to field
            entry_object.insert(0, returnFile)
    

    def open_wtf(self):
        """ Purpose: This will delete whatever is in the wtf_entry field, and prompt the user with a find file dialog box.
                     Once they've found the file, it will insert that filepath into wtf_entry. This function is only called 
                     when the 'Select File' button next to wtf_entry is clicked. 
        """
        # Retrieve a filename from the user
        returnFile = tkFileDialog.asksaveasfilename()
        if returnFile:
            # removes everything in wtf_entry
            self.wtf_entry.delete(0, tk.END)
            # puts full path of selected file to save as in wtf_entry
            self.wtf_entry.insert(0, returnFile)


    def check_wtf(self):
        """ Purpose: This function is called whenever the user clicks on the checkbox for writing output to a file. It will take the 
                     appropriate action based on whether the box was checked previously or not. If it is now checked, it 
                     will add the wtf_entry and wtf_button options for specifying a file to write the output to. If it is 
                     now unchecked, it will remove these two objects.                      
        """
        # if WTF checkbox is checked,  enable the Entry and file load button
        if self.wtf_checkbox.get() == 1:
            self.wtf_entry.grid(column=1, row=0)
            self.wtf_button.grid(column=2, row=0, sticky="NW", padx=2)
        # if WTF checkbox is not checked,  re-disable the entry options
        if self.wtf_checkbox.get() == 0:
            self.wtf_entry.grid_forget()
            self.wtf_button.grid_forget()


    def commit_option_update(self, check_type):
        """ Purpose: This function is called when any of the commit option check boxes are clicked. Depending on which one we click, we 
                     deselect the other two, and forget or create the grid for the commit confirmed minutes entry as necessary. 
            Parameters:
                check_type  -  string  -  a string identifier stating which commit option is being clicked. We are expecting one of three 
                                          options: 'blank', 'check', or 'confirmed'.
        """
        if check_type == 'blank' and self.commit_blank.get():
            self.commit_confirmed_button.deselect()
            self.commit_check_button.deselect()
            self.commit_confirmed_min_entry.grid_forget()
            self.commit_confirmed_min_label.grid_forget()
        elif check_type == 'check' and self.commit_check_button.get():
            self.commit_confirmed_button.deselect()
            self.commit_blank.deselect()
            self.commit_confirmed_min_entry.grid_forget()
            self.commit_confirmed_min_label.grid_forget()
        elif check_type == 'confirmed' and self.commit_confirmed_button.get():
            self.commit_check_button.deselect()
            self.commit_blank.deselect()
            self.commit_confirmed_min_label.grid(column=3, row=1, sticky="NW")
            self.commit_confirmed_min_entry.grid(column=4, row=1, sticky="NW")
        elif check_type == 'confirmed' and not self.commit_confirmed_button.get():
            self.commit_confirmed_min_entry.grid_forget()
            self.commit_confirmed_min_label.grid_forget()


    def clear_output(self, event):
        """ Purpose: This function is called by the 'clear output' button and is used to remove all text from the output window. 

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
        """
        self.output_area.delete(1.0, tk.END)


    def save_output(self):
        """ Purpose: This function is called by the 'save output' button and is used to open a save file dialog box, and write
                     the text within the output_area window to that file. """
        returnFile = tkFileDialog.asksaveasfilename()
        # If no file is chosen, do not try to open it.
        if returnFile is not "":
            outFile = open(returnFile, 'w+b')  # 'w' will open for overwriting, 'b' is for windows compatibility
            outFile.write(self.output_area.get(1.0, tk.END))
            outFile.close()


    def quit(self, event):
        """ Purpose: Quit the application, called on selecting File > Quit, or by pressing Ctrl-Q. 

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 
        """
        sys.exit(0)


    def clear_fields(self, event):
        """ Purpose: Clear all input fields. Called by hitting Ctrl-C or clicking the appropriate menu option in the file menu.

            Parameters:
                event - Tkinter.event object - Any command that tkinter binds a keyboard shortcut to will receive the
                        argument event. It is a description of the keyboard shortcut that generated the event. 'None' can be passed
                        for method calls outside of a keyboard shortcut. 
        """
        self.ip_entry.delete(0, tk.END)
        self.timeout_entry.delete(0, tk.END)
        self.timeout_entry.insert(0, '300')
        self.username_entry.delete(0, tk.END)
        self.password_entry.delete(0, tk.END)
        self.wtf_entry.delete(0, tk.END)
        self.wtf_checkbox.deselect()
        self.option_entry.delete(0, tk.END)
        self.option_entry.delete(0, tk.END)
        self.scp_destination_entry.delete(0, tk.END)
        self.commit_check_button.deselect()
        self.commit_confirmed_button.deselect()
        self.commit_blank.deselect()


    def show_frames(self):
        """ Purpose: This function grids all frames and separators. It is called by the Toggle Options button, and used by
                     __init__() to create the frames on starting the program. 
        """

        self.ip_cred_frame.grid(row=0, column=0, sticky="NW", padx=(25, 25), pady=(25, 0))
        
        self.sep2.grid(row=1, column=0, sticky="WE", pady=8, padx=8)

        self.wtf_frame.grid(row=2, column=0, sticky="NW", padx=(25, 0))
        self.sep3.grid(row=3, column=0, sticky="WE", pady=8, padx=8)
        
        self.options_frame.grid(row=4, column=0, sticky="NW", padx=(25, 0))

        self.sep4.grid(row=5, column=0, sticky="WE", pady=12, padx=12)

        self.help_frame.grid(row=6, column=0, sticky="NW", padx=(25, 0))

        self.sep5.grid(row=7, column=0, sticky="WE", pady=12, padx=12)
        
        self.buttons_frame.grid(row=8, column=0, sticky="NW", padx=(25, 25), pady=(0, 10))
        self.output_frame.grid(row=9, column=0, padx=(25, 25), sticky="SWNE", pady=(0, 25))
        
        self.update()


    def toggle_frames(self):
        """ This function is called by toggle_frames_button to toggle whether non-output frames are shown. """
        if self.frames_shown:
            self.ip_cred_frame.grid_forget()
            self.wtf_frame.grid_forget()
            self.help_frame.grid_forget()

            self.sep2.grid_forget()
            self.sep3.grid_forget()
            self.sep4.grid_forget()

            self.update()
            self.frames_shown = False
        else:
            self.show_frames()
            self.frames_shown = True
コード例 #27
0
 def __init__(self):
     super(MyWindow, self).__init__()
     self.progressSignal.connect(self.updateProgressSlot)
     self.initUI()
     self.__workerThread = WorkerThread(self.progressSignal,
                                        self.progressText)
コード例 #28
0
 def __init__(self, parentThread, seed, rows, columns):
     WorkerThread.__init__(self, parentThread)
     self.ipf = Ipf(seed, rows, columns)
     self.error = None
コード例 #29
0
 def __init__(self, parentThread, impedance, rows, columns, model):
     WorkerThread.__init__(self, parentThread)
     self.gravity = GravityApplication(rows, columns, impedance, model)
     self.error = None
コード例 #30
0
 def __init__(self, parentThread, observed, impedance, function):
     WorkerThread.__init__(self, parentThread)
     self.gravity = GravityCalibration(observed, impedance, function)
     self.error = None