Best Python code snippet using slash
Controller.py
Source:Controller.py  
1# import seatease.spectrometers as s  # Emulator to test w/o spectrometer2import seabreeze.spectrometers as s3from datetime import datetime4from tkinter.messagebox import showerror5import matplotlib6import numpy as np7from LogPatient import *8from LoginPage import *9from ResetPW import *10from SignUp import *11from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg12from matplotlib.lines import Line2D13import matplotlib.pyplot as plt14import matplotlib.animation as animation15from matplotlib import style16from azure.storage.blob import BlobClient17import csv18matplotlib.use("TkAgg")19style.use("ggplot")20dev_list = s.list_devices()21spec = s.Spectrometer(dev_list[0])  # Assign detected spectrometer to variable spec22integration_time = 20000  # 20 ms, set default integration time to a reasonable value23spec.integration_time_micros(integration_time)24x = spec.wavelengths()25data = spec.intensities()26xmin = np.around(min(x), decimals=2)27xmax = np.around(max(x), decimals=2)28ymin = np.around(min(data), decimals=2)29ymax = np.around(max(data), decimals=2)30minIntTime = spec.minimum_integration_time_micros31class Controller(tk.Tk):32    def __init__(self, ax, *args, **kwargs):33        tk.Tk.__init__(self, *args, **kwargs)34        tk.Tk.wm_title(self, "Data Recording")35        self.geometry("1000x700")36        container = tk.Frame(self)37        container.pack(side="top", fill="both", expand=True)38        container.grid_rowconfigure(0, weight=1)39        container.grid_columnconfigure(0, weight=1)40        # Dictionary of class names, frames (Ex: HomePage, actual frame)41        self.frames = {"LoginPage": LoginPage(container, self),42                       "LogPatient": LogPatient(container, self),43                       "DataRecording": DataRecording(container, self, ax),44                       "SignUp": SignUp(container, self),45                       "ResetPW": ResetPW(container, self)}46        for frame in self.frames:47            self.frames[frame].grid(row=0, column=0, sticky="nsew")48        # Starting page49        self.show_login_frame()50    # When called, passes the frame or page to be showed on windows51    def show_login_frame(self):52        frame = self.frames["LoginPage"]53        frame.tkraise()54    def show_patientLog_frame(self):55        frame = self.frames["LogPatient"]56        frame.tkraise()57    def show_dataRecording_frame(self):58        frame = self.frames["DataRecording"]59        frame.tkraise()60    def show_signUp_frame(self):61        frame = self.frames["SignUp"]62        frame.tkraise()63    def show_resetPW_frame(self):64        frame = self.frames["ResetPW"]65        frame.tkraise()66class DataRecording(tk.Frame):67    body_part_option_selected = ""68    duration_value = 0.069    session_interrupt = -170    # stopwatch71    running = False72    current_ticking_value = 18000  # This depends on current timezone, may be different in other regions. Starts at 073    ticking_value_max = 0  # initialization, actual value assigned on create_stopwatch() function74    timer_label = ""75    AbMode = 0  # start in raw intensity mode76    def __init__(self, parent, controller, ax):77        global data, x78        global integration_time, spectra_average79        global xmin, xmax, ymin, ymax80        global monitor_wave, monitor_index, monitor81        self.ax = ax82        self.x = x83        self.xmin = xmin84        self.xmax = xmax85        self.ymin = ymin86        self.ymax = ymax87        self.data = data88        self.line = Line2D(self.x, self.data, color='red')89        self.ax.add_line(self.line)90        self.ax.set_ylim(ymin * 0.8, ymax * 1.1)91        self.ax.set_xlim(self.xmin, self.xmax)92        monitor_wave = np.median(x)93        tk.Frame.__init__(self, parent)94        label = ttk.Label(self, text=f"Session Recording", font=LARGE_FONT)95        label.pack(side='top', pady=20)96        # This frame1 packs all the labels on the first column on the UI97        self.frame1 = tk.Frame(self)98        self.frame1.pack(side='left', anchor=tk.N)99        # This frame1 packs all the labels on the second column on the UI100        self.frame2 = tk.Frame(self)101        self.frame2.pack(side='left', anchor=tk.N)102        # This frame1 packs all the labels on the third column on the UI103        self.frame3 = tk.Frame(self)104        self.frame3.pack(side='left', anchor=tk.N)105        # ID design106        id_label = tk.Label(self.frame1, text="Patient ID:", font=SMALL_FONT)107        id_label.pack(side='top', pady=4)108        id_val = tk.Label(self.frame2, text=LogPatient.patient_id, font=SMALL_FONT)109        id_val.pack(side='top', pady=4)110        filler_label = tk.Label(self.frame3, text="")111        filler_label.pack(side='top')112        # BMI design113        bmi_label = tk.Label(self.frame1, text="BMI:", font=SMALL_FONT)114        bmi_label.pack(side='top', pady=4)115        bmi_val = tk.Label(self.frame2, text="auto", font=SMALL_FONT)116        bmi_val.pack(side='top', pady=4)117        filler_label = tk.Label(self.frame3, text="")118        filler_label.pack(side='top', pady=6)119        # Integration time design120        duration_label = tk.Label(self.frame1, text="Integration Time", font=SMALL_FONT)121        duration_label.pack(side='top', pady=4)122        self.duration_entry = tk.Entry(self.frame2, width='7', justify='right')123        self.duration_entry.pack(side='top', pady=4, anchor=tk.N)124        seconds_label = tk.Label(self.frame3, text="Seconds", height='2', font=SMALL_FONT)125        seconds_label.pack(side='top', pady=4)126        self.duration_entry.bind('<Return>', self.validate_integration_time)127        # Number of spectra design128        num_spectra_label = tk.Label(self.frame1, text="Number of Spectra Returned", font=SMALL_FONT)129        num_spectra_label.pack(side='top', pady=4)130        num_spectra_entry = tk.Entry(self.frame2, width='7', justify='right')131        num_spectra_entry.pack(side='top', pady=10)132        # Amount of spectra to average design133        spec_avg_label = tk.Label(self.frame1, text='Amount of Spectra to Average ', width='20', wraplength='150',134                                  font=SMALL_FONT)135        spec_avg_label.pack(side='top', pady=4)136        self.spec_avg_entry = tk.Entry(self.frame2, width='7', justify='right')137        self.spec_avg_entry.pack(side='top', pady=20)138        self.spec_avg_entry.bind('<Return>', self.validate_spec_avg)139        # Minimum wavelength label and entry field140        xmin_label = tk.Label(self.frame1, text='Minimum wavelength', font=SMALL_FONT)141        xmin_label.pack(side='top', pady=2)142        self.xmin_entry = tk.Entry(self.frame2, width='7', justify='right')143        self.xmin_entry.pack(side='top', pady=15)144        self.xmin_entry.insert(0, xmin)  # AUTO INPUTS VALUE145        self.xmin_entry.bind('<Return>', self.validate_xmin)146        # Maximum wavelength label and entry field147        xmax_label = tk.Label(self.frame1, text='Maximum wavelength', height='2', font=SMALL_FONT)148        xmax_label.pack(side='top', pady=2)149        self.entryxmax = tk.Entry(self.frame2, width='7', justify='right')150        self.entryxmax.pack(side='top', pady=5)151        self.entryxmax.insert(0, xmax)  # AUTO INPUTS VALUE152        self.entryxmax.bind('<Return>', self.validate_xmax)153        body_part_label = tk.Label(self.frame1, text="Body Location:", height='2', font=SMALL_FONT)154        body_part_label.pack(side='top', pady=4)155        self.body_part_option_selected = tk.StringVar()156        self.body_part_option_selected.set(hm.BodyParts[0])  # Initial Value157        body_part_options = ttk.OptionMenu(self.frame2, self.body_part_option_selected, *hm.BodyParts)158        body_part_options.pack(side='top', pady=15)159        btn_start_stop = ttk.Button(self.frame1, text="Start", command=lambda: start_stop_process())160        btn_start_stop.pack(side='top', pady=10)161        btn_save = ttk.Button(self.frame2, text="Save", command=lambda: save_recording())162        btn_save.pack(side='top', pady=10)163        btn_pause_resume = ttk.Button(self.frame1, text="Pause", command=lambda: pause_resume_process())164        btn_pause_resume.pack(side='top', pady=10)165        diff_patient_button = ttk.Button(self.frame2, text="Next Patient",166                                         command=lambda: controller.show_patientLog_frame())167        diff_patient_button.pack(side='top', pady=10)168        quit_button = tk.Button(self.frame1, text="Quit")169        quit_button.pack(side='bottom', pady=10)170        quit_button.bind('<ButtonRelease-1>', self.quit_app)171        button_reset_y = tk.Button(self.frame1, text='Reset Y axis scale')172        button_reset_y.pack(side='bottom', pady=10)173        button_reset_y.bind('<ButtonRelease-1>', self.reset_y)174        log_out_button = tk.Button(self.frame1, text="Log out", command=lambda: controller.show_login_frame())175        log_out_button.pack(side='bottom', pady=10)176        check_box_label = tk.Checkbutton(self.frame1, text="Interrupted session", command=lambda: box_toggled())177        check_box_label.pack(side='bottom', pady=10)178        # Disable pause while the clock is not started179        hm.disable_fields(btn_pause_resume)180        # Labels for the graph181        ax.set_xlabel('Wavelength (nm)')182        ax.set_ylabel('Counts')183        # Creates the design for the graph184        canvas = FigureCanvasTkAgg(fig, self)185        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)186        monitor_index = np.searchsorted(x, monitor_wave, side='left')187        monitor = np.round(self.data[monitor_index], decimals=3)188        self.text = self.ax.text(0.9, 0.9, monitor, transform=ax.transAxes, fontsize=14)189        #self.ax.axvline(x=monitor_wave, lw=2, color='blue', alpha=0.5)                 # Blue line in on the graph190        # This method changes a value when checkBox is checked meaning a session was interrupted191        def box_toggled():192            self.session_interrupt *= -1193        def save_csv_to_cloud(file_path):194            """ Upload csv file to Azure """195            blob = BlobClient.from_connection_string(conn_str="Connection String Place Holder",196                                                     container_name="Container Name Place Holder",197                                                     blob_name=file_path)198            with open(file_path, "rb") as up:199                blob.upload_blob(up)200        def save_recording():201            if self.session_interrupt == -1:202                print("Normal session")203                file_name = str(LogPatient.patient_id) + "_" + str(self.body_part_option_selected.get()) + ".csv"204                print(file_name)205                save_csv_to_cloud(file_name)206            else:207                # TODO: Message box will probably have to be a customized pop-up. You can't add an entry text field here208                result = tk.messagebox.askyesno("Interrupted session", "You have marked this session as interrupted.\n"209                                                                       "Data will be saved in different database")210                if result:  # If user confirmed session was interrupted and he/she agrees with message211                    # TODO: Data in different database212                    print("Result:")213                    print(result)214            return215        def pause_resume_process():216            if hm.is_pause_button(btn_pause_resume):217                pause_process()218            else:219                # check if no errors when re-entering fields220                if check_fields():221                    resume_process()222            return223        def resume_process():224            btn_pause_resume["text"] = "Pause"225            start_stopwatch(self.timer_label)226            hm.disable_fields(body_part_options, self.duration_entry)227            # TODO228            # Connect to save again values with different body part in DB229            print(self.duration_value)230            print(self.body_part_option_selected.get())231            return232        def pause_process():233            # TODO234            # Do we want to change the duration and body part once user pauses? *** BUG ***235            btn_pause_resume["text"] = "Resume"236            self.running = False237            hm.enable_fields(body_part_options, self.duration_entry)238            return239        def start_stop_process():240            if check_fields():  # no errors241                if hm.is_start_button(btn_start_stop):242                    start_process()243                else:244                    stop_process()245            return246        def start_process():247            hm.disable_fields(btn_save, log_out_button, diff_patient_button, body_part_options, self.duration_entry)248            hm.enable_fields(btn_pause_resume)249            btn_start_stop["text"] = "Stop"250            create_stopwatch()251            start_stopwatch(self.timer_label)252            return253        def stop_process():254            hm.disable_fields(btn_pause_resume)255            btn_pause_resume["text"] = "Pause"  # if stop the recording, we need to reset this button (bug)256            btn_start_stop["text"] = "Start"257            hm.enable_fields(btn_save, log_out_button, diff_patient_button, body_part_options, self.duration_entry)258            self.running = False259            self.timer_label.destroy()260            return261        # checks for any errors, prints them and returns False, otherwise no errors and returns True262        def check_fields():263            if hm.check_fields_inputs(durationEntry=self.duration_entry,264                                      bodyPartOption=self.body_part_option_selected.get()):265                self.duration_value = float(self.duration_entry.get())266                return True267            else:268                return False269        # region Stopwatch270        def create_stopwatch():271            self.timer_label = tk.Label(self.frame1, text="Stopwatch!", fg="black", font="Verdana 15 bold")272            self.timer_label.pack(pady=10)273            self.current_ticking_value = 18000  # we need to reset the timer after 1st recording274            # Cannot assign ticking_value_max until we know the duration_value and after being checked275            self.ticking_value_max = self.current_ticking_value + self.duration_value276            return277        def start_stopwatch(timer_label):278            self.running = True279            counter_label(timer_label)280            return281        def counter_label(timer_label):282            def count():283                if self.running and self.current_ticking_value <= self.ticking_value_max:  # if from 0 to limit284                    # To manage the initial delay.285                    if self.current_ticking_value == 18000:286                        display = "Starting..."287                    else:288                        tt = datetime.fromtimestamp(self.current_ticking_value)289                        string = tt.strftime("%H:%M:%S")290                        display = string291                    timer_label['text'] = display  # Or label.config(text=display)292                    timer_label.after(1000, count)293                    self.current_ticking_value += 1294                elif not self.running and self.current_ticking_value <= self.ticking_value_max:  # if paused295                    timer_label['text'] = "Paused..."296                else:297                    timer_label['text'] = "Finished!"298                    hm.disable_fields(btn_pause_resume)299                    btn_pause_resume["text"] = "Pause"300            # Triggering the start of the counter.301            count()302    def quit_app(root, event):303        """ Quits the program """304        root.destroy()305        exit()306    def reset_y(self, event):307        data = spec.intensities(correct_nonlinearity=False)308        ymin = min(data)309        ymax = max(data)310        ax.set_ylim(ymin * 0.9, ymax * 1.1)311    def set_entry_config(self):312        """ This function handles new inputs on the text fields and it send values to spectrometer """313        global integration_time  # , spectra_average314        spec.integration_time_micros(integration_time)315        # spec.scans_to_average(spectra_average)316        # write new configuration to dialog317        self.duration_entry.delete(0, "end")318        self.duration_entry.insert(0, integration_time / 1000)  # write ms, but integration_time is microseconds319    def validate_integration_time(self, event):320        """ Update integration time and validates from 4ms to 65000 """321        global integration_time322        # typically OO spectrometers cant read faster than 4 ms323        int_time_temp = self.duration_entry.get()324        if int_time_temp.isdigit():325            if int(int_time_temp) > 65000:326                msg = "The integration time must be 65000 ms or smaller.  You set " + int_time_temp327                self.set_entry_config()328            elif int(int_time_temp) < 4:329                msg = "The integration time must be greater than 4 ms.  You set " + int_time_temp330                self.set_entry_config()331            else:332                integration_time = int(int_time_temp) * 1000  # convert ms to microseconds333                self.set_entry_config()334        else:335            msg = "Integration time must be an integer between 4 and 65000 ms.  You set " + str(int_time_temp)336            self.set_entry_config()337    def validate_spec_avg(self, event):338        # averaging needs to be implemented here in code339        global spectra_average340        spectra_average = self.spec_avg_entry.get()341        if spectra_average.isdigit():342            spec.scans_to_average(int(spectra_average))343        else:344            msg = "spectra_average must be an integer.  You tried " + str(spectra_average) + ".  Setting value to 1."345            spectra_average = 1346            self.spec_avg_entry.delete(0, "end")347            self.spec_avg_entry.insert(0, spectra_average)348    def validate_xmax(self, event):349        """ Validates max wavelength to show in graph """350        global xmax351        xmax_temp = self.entryxmax.get()352        try:353            float(xmax_temp)354            xmax_temp = float(self.entryxmax.get())355            if xmax_temp > xmin:356                xmax = xmax_temp357                self.entryxmax.delete(0, 'end')358                self.entryxmax.insert(0, xmax)  # set text in box359                self.ax.set_xlim(xmin, xmax)360            else:361                msg = "Maximum wavelength must be larger than minimum wavelength.  You entered " + str(362                    xmax_temp) + " nm."363                self.entryxmax.delete(0, 'end')364                self.entryxmax.insert(0, xmax)  # set text in box365        except:366            self.entryxmax.delete(0, 'end')367            self.entryxmax.insert(0, xmax)  # set text in box to unchanged value368    def validate_xmin(self, event):369        """ Validates min wavelength to show in graph """370        global xmin371        xmin_temp = self.xmin_entry.get()372        try:373            float(xmin_temp)374            xmin_temp = float(self.xmin_entry.get())375            if xmin_temp < xmax:376                xmin = xmin_temp377                self.xmin_entry.delete(0, 'end')378                self.xmin_entry.insert(0, xmin)  # set text in box379                self.ax.set_xlim(xmin, xmax)380            else:381                msg = "Minimum wavelength must be smaller than maximum wavelength.  You entered " + str(382                    xmin_temp) + " nm."383                self.xmin_entry.delete(0, 'end')384                self.xmin_entry.insert(0, xmin)  # set text in box385        except:386            self.xmin_entry.delete(0, 'end')387            self.xmin_entry.insert(0, xmin)  # set text in box to unchanged value388    def update(self, data):389        """ This function manages the update of the390        spectral data in the graph. It issues a read request to the spectrometer,391        then conditionally processes the received data """392        file_name = str(LogPatient.patient_id) + "_" + str(self.body_part_option_selected.get()) + ".csv"393        not2save = str(LogPatient.patient_id) + "_Select an option.csv"394        if file_name != not2save:395            with open(file_name, "w", newline='') as towrite:396                lineWriter = csv.writer(towrite, quotechar='|', delimiter='\n', quoting=csv.QUOTE_NONE)397                lineWriter.writerow(self.data)398        self.data = spec.intensities()399        self.data = np.array(self.data, dtype=float)400        self.line.set_data(self.x, self.data)401        monitor = np.round(self.data[monitor_index], decimals=3)402        self.text.set_text(monitor)403        return self.line,404    # endregion405fig, ax = plt.subplots()406app = Controller(ax)407ani = animation.FuncAnimation(fig, app.frames["DataRecording"].update, interval=10, blit=False)...test_interruptions.py
Source:test_interruptions.py  
...144    results = suite.run(expect_interruption=True)145    assert results.session.results.global_result.is_interrupted()146    assert checkpoint.called147@pytest.fixture148def session_interrupt():149    callback = Checkpoint()150    slash.hooks.session_interrupt.register(callback) # pylint: disable=no-member151    return callback152@pytest.fixture153def test_interrupt_callback():154    callback = Checkpoint()155    slash.hooks.test_interrupt.register(callback) # pylint: disable=no-member156    return callback157@pytest.fixture158def interrupted_suite(suite, interrupted_index):159    for index, test in enumerate(suite):160        if index == interrupted_index:161            test.append_line('raise KeyboardInterrupt()')162            test.expect_interruption()...test_plugin.py
Source:test_plugin.py  
1import subprocess2import pytest3from gi.repository import Gtk4from wiring import Graph5from tomate.pomodoro import Bus, Config, Events6from tomate.ui.testing import Q7SECTION_NAME = "exec_plugin"8@pytest.fixture9def check_output(mocker, monkeypatch):10    import exec_plugin11    check_output = mocker.Mock(spec=subprocess.check_output)12    monkeypatch.setattr(exec_plugin.subprocess, "check_output", check_output)13    return check_output14@pytest.fixture15def bus() -> Bus:16    return Bus()17@pytest.fixture18def graph() -> Graph:19    g = Graph()20    g.register_instance(Graph, g)21    return g22@pytest.fixture23def config(bus, tmpdir):24    instance = Config(bus)25    tmp_path = tmpdir.mkdir("tomate").join("tomate.config")26    instance.config_path = lambda: tmp_path.strpath27    return instance28@pytest.fixture29def plugin(bus, config, graph):30    graph.providers.clear()31    graph.register_instance("tomate.config", config)32    graph.register_instance("tomate.bus", bus)33    import exec_plugin34    instance = exec_plugin.ExecPlugin()35    instance.configure(bus, graph)36    return instance37@pytest.mark.parametrize(38    "event, option",39    [40        (Events.SESSION_START, "start_command"),41        (Events.SESSION_INTERRUPT, "stop_command"),42        (Events.SESSION_END, "finish_command"),43    ],44)45def test_execute_command_when_event_is_trigger(event, option, bus, check_output, config, plugin):46    plugin.activate()47    bus.send(event)48    command = config.get(SECTION_NAME, option)49    check_output.assert_called_once_with(command, shell=True, stderr=subprocess.STDOUT)50@pytest.mark.parametrize(51    "event, option",52    [53        (Events.SESSION_START, "start_command"),54        (Events.SESSION_INTERRUPT, "stop_command"),55        (Events.SESSION_END, "finish_command"),56    ],57)58def test_does_not_execute_commands_when_they_are_not_configured(event, option, bus, check_output, config, plugin):59    config.remove(SECTION_NAME, option)60    plugin.activate()61    assert bus.send(event) == [False]62    check_output.assert_not_called()63def test_execute_command_fail(bus, config, plugin):64    config.set(SECTION_NAME, "start_command", "fail")65    plugin.activate()66    assert bus.send(Events.SESSION_START) == [False]67class TestSettingsWindow:68    @pytest.mark.parametrize(69        "option,command",70        [71            ("start_command", "echo start"),72            ("stop_command", "echo stop"),73            ("finish_command", "echo finish"),74        ],75    )76    def test_with_custom_commands(self, option, command, plugin):77        dialog = plugin.settings_window(Gtk.Window())78        switch = Q.select(dialog.widget, Q.props("name", f"{option}_switch"))79        assert switch.props.active is True80        entry = Q.select(dialog.widget, Q.props("name", f"{option}_entry"))81        assert entry.props.text == command82    @pytest.mark.parametrize("option", ["start_command", "stop_command", "finish_command"])83    def test_without_custom_commands(self, option, config, plugin):84        config.remove_section(SECTION_NAME)85        config.save()86        assert config.has_section(SECTION_NAME) is False87        dialog = plugin.settings_window(Gtk.Window())88        switch = Q.select(dialog.widget, Q.props("name", f"{option}_switch"))89        assert switch.props.active is False90        entry = Q.select(dialog.widget, Q.props("name", f"{option}_entry"))91        assert entry.props.text == ""92    @pytest.mark.parametrize("option", ["start_command", "stop_command", "finish_command"])93    def test_disable_command(self, option, config, plugin):94        dialog = plugin.settings_window(Gtk.Window())95        switch = Q.select(dialog.widget, Q.props("name", f"{option}_switch"))96        switch.props.active = False97        entry = Q.select(dialog.widget, Q.props("name", f"{option}_entry"))98        assert entry.props.sensitive is False99        assert entry.props.text == ""100        dialog.widget.emit("response", 0)101        assert dialog.widget.props.window is None102        config.load()103        assert config.has_option(SECTION_NAME, option) is False104    @pytest.mark.parametrize("option", ["start_command", "stop_command", "finish_command"])105    def test_configure_command(self, option, config, plugin):106        config.remove(SECTION_NAME, option)107        dialog = plugin.settings_window(Gtk.Window())108        switch = Q.select(dialog.widget, Q.props("name", f"{option}_switch"))109        switch.props.active = True110        entry = Q.select(dialog.widget, Q.props("name", f"{option}_entry"))111        assert entry.props.sensitive is True112        entry.props.text = "echo changed"113        dialog.widget.emit("response", 0)114        assert dialog.widget.props.window is None115        config.load()...indicator_plugin.py
Source:indicator_plugin.py  
1import logging2import gi3gi.require_version("AppIndicator3", "0.1")4from wiring import Graph5from gi.repository import AppIndicator36import tomate.pomodoro.plugin as plugin7from tomate.pomodoro import Events, on, Bus, suppress_errors, TimerPayload8from tomate.ui import Systray9logger = logging.getLogger(__name__)10class IndicatorPlugin(plugin.Plugin):11    @suppress_errors12    def __init__(self):13        super().__init__()14        self.menu = None15        self.config = None16        self.session = None17        self.indicator = None18    def configure(self, bus: Bus, graph: Graph) -> None:19        super().configure(bus, graph)20        self.menu = graph.get("tomate.ui.systray.menu")21        self.config = graph.get("tomate.config")22        self.session = graph.get("tomate.session")23        self.indicator = self.create_widget()24    @suppress_errors25    def activate(self):26        logger.debug("action=active")27        super().activate()28        self.menu.connect(self.bus)29        self.graph.register_instance(Systray, self)30        if self.session.is_running():31            self.show()32        else:33            self.hide()34    @suppress_errors35    def deactivate(self):36        logger.debug("action=deactivate")37        super().deactivate()38        self.menu.disconnect(self.bus)39        self.graph.unregister_provider(Systray)40        self.hide()41    @suppress_errors42    @on(Events.TIMER_UPDATE)43    def update_icon(self, payload: TimerPayload):44        logger.debug("action=update-icon payload=%s", payload)45        icon_name = self.icon_name(payload.elapsed_percent)46        if icon_name != self.indicator.get_icon():47            self.indicator.set_icon(icon_name)48    @suppress_errors49    @on(Events.SESSION_START)50    def show(self, **__):51        logger.debug("action=show")52        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)53    @suppress_errors54    @on(Events.SESSION_END, Events.SESSION_INTERRUPT)55    def hide(self, **__):56        logger.debug("action=hide")57        self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)58        self.indicator.set_icon("tomate-idle")59    @staticmethod60    def icon_name(percent):61        return "tomate-{:02.0f}".format(percent)62    def create_widget(self):63        indicator = AppIndicator3.Indicator.new(64            "tomate", "tomate-idle", AppIndicator3.IndicatorCategory.APPLICATION_STATUS65        )66        indicator.set_icon_theme_path(self.first_icon_theme_path())67        indicator.set_menu(self.menu.widget)68        return indicator69    def first_icon_theme_path(self):...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
