From 4f59bfcc831a2e38d8f4753a2af1a3b5e4ebf49d Mon Sep 17 00:00:00 2001 From: DaveL17 Date: Wed, 27 Dec 2023 08:12:35 -0600 Subject: [PATCH] Changes to prepare for Indigo 2023.2 and code refinements. --- LICENSE | 2 +- _changelog.md | 8 +- _to_do_list.md | 4 +- matplotlib.indigoPlugin/Contents/Info.plist | 6 +- .../Server Plugin/DLFramework/DLFramework.py | 89 ++++----- .../Contents/Server Plugin/Devices.xml | 2 +- .../Contents/Server Plugin/chart_bar_flow.py | 2 +- .../Contents/Server Plugin/chart_bar_stock.py | 1 - .../Contents/Server Plugin/chart_line.py | 8 +- .../Contents/Server Plugin/chart_tools.py | 16 +- .../Server Plugin/chart_weather_composite.py | 6 +- .../Server Plugin/chart_weather_forecast.py | 5 +- .../Contents/Server Plugin/maintenance.py | 20 +- .../Contents/Server Plugin/plugin.py | 189 +++++++++--------- .../Contents/Server Plugin/plugin_defaults.py | 2 +- .../Contents/Server Plugin/validate.py | 55 ++++- 16 files changed, 221 insertions(+), 194 deletions(-) diff --git a/LICENSE b/LICENSE index ab8e978..b91215d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 DaveL17 +Copyright (c) 2023 DaveL17 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/_changelog.md b/_changelog.md index a26049a..e520327 100644 --- a/_changelog.md +++ b/_changelog.md @@ -1,3 +1,7 @@ +#### v2023.0.1 +- Changes to prepare for Indigo `v2023.2`. +- Code enhancements. + #### v2022.1.7 - Fixes bug where `Matplotlib Paramters Device` incorrectly labelled in error state. - Fixes bug `PluginAction' object has no attribute 'PROPS'`. @@ -436,7 +440,7 @@ #### v0.7.54 - Fixes float error in the duration value for CSV refreshes. -- Moves dev prop maintenance routine to deviceStartComm. +- Moves dev prop maintenance routine to device_start_comm. #### v0.7.53 - Adds tests to alert the user that they're saving charts to the wrong location (when the Indigo version is updated.) @@ -559,7 +563,7 @@ settings are retained. #### v0.7.24 -- Synchronize self.pluginPrefs in closedPrefsConfigUi(). +- Synchronize self.pluginPrefs in closed_prefs_config_ui(). #### v0.7.23 - Adds choice to set bar width to make it simpler for first time device creation. If the value is set to zero, the diff --git a/_to_do_list.md b/_to_do_list.md index e8c378c..9237a7f 100644 --- a/_to_do_list.md +++ b/_to_do_list.md @@ -1,5 +1,6 @@ ### TODO -- +- Vertical bar stock charts don't allow for setting annotation precision for bar 5. Others? see https://forums.indigodomo.com/viewtopic.php?f=219&t=27024 +- Do we still have to use x-axis label OR legend (but not both?) see https://forums.indigodomo.com/viewtopic.php?f=219&t=27024 #### NEW - Combination device (line/bar to replicate weather devices). @@ -11,6 +12,7 @@ [See example](https://matplotlib.org/3.1.1/gallery/ticks_and_spines/multiple_yaxis_with_spines.html) - Create new STEP chart type as step is no longer a supported line style. [See example](https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.axes.Axes.step.html?highlight=steps%20post) +- Add secondary X-axis tick labels to relevant charts. See https://forums.indigodomo.com/viewtopic.php?f=219&t=27024 #### Refinements - Try to address annotation collisions. diff --git a/matplotlib.indigoPlugin/Contents/Info.plist b/matplotlib.indigoPlugin/Contents/Info.plist index ff966d1..0d686ac 100755 --- a/matplotlib.indigoPlugin/Contents/Info.plist +++ b/matplotlib.indigoPlugin/Contents/Info.plist @@ -3,13 +3,9 @@ PluginVersion - 2022.1.7 + 2023.0.1 ServerApiVersion 3.0 - IwsApiVersion - 1.0.0 - LoadPriority - 105 CFBundleDisplayName Matplotlib CFBundleName diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/DLFramework/DLFramework.py b/matplotlib.indigoPlugin/Contents/Server Plugin/DLFramework/DLFramework.py index 01ea2bc..2e64a6a 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/DLFramework/DLFramework.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/DLFramework/DLFramework.py @@ -24,7 +24,7 @@ __copyright__ = "Copyright 2017-2022 DaveL17" __license__ = "MIT" __title__ = "DLFramework" -__version__ = "0.1.04" +__version__ = "0.1.05" # supported operators for eval expressions OPERATORS = { @@ -63,17 +63,14 @@ def __init__(self, plugin): self.pluginPrefs = plugin.pluginPrefs log_format = '%(asctime)s.%(msecs)03d\t%(levelname)-10s\t%(name)s.%(funcName)-28s %(msg)s' - self.plugin.plugin_file_handler.setFormatter( - logging.Formatter(fmt=log_format, datefmt='%Y-%m-%d %H:%M:%S') - ) + self.plugin.plugin_file_handler.setFormatter(logging.Formatter(fmt=log_format, datefmt='%Y-%m-%d %H:%M:%S')) # ============================================================================= def pluginEnvironment(self): # noqa """ - The pluginEnvironment method prints selected information about the pluginEnvironment that - the plugin is running in. It pulls some of this information from the calling plugin and - some from the server pluginEnvironment. It uses the legacy "indigo.server.log" method to - write to the log. + The pluginEnvironment method prints selected information about the pluginEnvironment that the plugin is running + in. It pulls some of this information from the calling plugin and some from the server pluginEnvironment. It + uses the legacy "indigo.server.log" method to write to the log. :return: """ @@ -98,10 +95,10 @@ def pluginEnvironment(self): # noqa # ============================================================================= def pluginEnvironmentLogger(self): # noqa """ - The pluginEnvironmentLogger method prints selected information about the pluginEnvironment - that the plugin is running in. It pulls some of this information from the calling plugin - and some from the server pluginEnvironment. This method differs from the pluginEnvironment() - method in that it leverages Indigo's logging hooks using the Python Logger framework. + The pluginEnvironmentLogger method prints selected information about the pluginEnvironment that the plugin is + running in. It pulls some of this information from the calling plugin and some from the server + pluginEnvironment. This method differs from the pluginEnvironment() method in that it leverages Indigo's + logging hooks using the Python Logger framework. :return: """ @@ -128,13 +125,11 @@ def pluginErrorHandler(self, sub_error): # noqa """ Centralized handling of traceback messages - Centralized handling of traceback messages formatted for pretty display in the plugin log - file. If sent here, they will not be displayed in the Indigo Events log. Use the following - syntax to send exceptions here:: + Centralized handling of traceback messages formatted for pretty display in the plugin log file. If sent here, + they will not be displayed in the Indigo Events log. Use the following syntax to send exceptions here: self.pluginErrorHandler(traceback.format_exc()) - :param traceback object sub_error: :return: """ @@ -150,10 +145,9 @@ def pluginErrorHandler(self, sub_error): # noqa # ============================================================================= def convertDebugLevel(self, debug_val): # noqa """ - The convertDebugLevel method is used to standardize the various implementations of debug - level settings across plugins. Its main purpose is to convert an old string-based setting - to account for older plugin versions. Over time, this method will become obsolete and - should be deprecated. + The convertDebugLevel method is used to standardize the various implementations of debug level settings across + plugins. Its main purpose is to convert an old string-based setting to account for older plugin versions. Over + time, this method will become obsolete and should be deprecated. :param str debug_val: :return: @@ -188,8 +182,8 @@ def deviceList(dev_filter=None): # noqa @staticmethod def deviceListEnabled(dev_filter=None): # noqa """ - Returns a list of tuples containing Indigo devices for use in config dialogs (etc.) Returns - enabled devices only. + Returns a list of tuples containing Indigo devices for use in config dialogs (etc.) Returns enabled devices + only. :param str dev_filter: :return: [(ID, "Name"), (ID, "Name")] @@ -237,8 +231,7 @@ def deviceAndVariableList(): # noqa @staticmethod def deviceAndVariableListClean(): # noqa """ - Returns a list of tuples containing Indigo devices and variables for use in config dialogs - (etc.) + Returns a list of tuples containing Indigo devices and variables for use in config dialogs (etc.) :return: [(ID, "(D) Name"), (ID, "(V) Name")] """ @@ -255,8 +248,8 @@ def deviceAndVariableListClean(): # noqa @staticmethod def launchWebPage(launch_url): # noqa """ - The launchWebPage method is used to direct a call to the registered default browser and - open the page referenced by the parameter 'URL'. + The launchWebPage method is used to direct a call to the registered default browser and open the page + referenced by the parameter 'URL'. :param str launch_url: :return: @@ -267,8 +260,8 @@ def launchWebPage(launch_url): # noqa @staticmethod def generatorStateOrValue(dev_id): # noqa """ - The generator_state_or_value() method returns a list to populate the relevant device - states or variable value to populate a menu control. + The generator_state_or_value() method returns a list to populate the relevant device states or variable value + to populate a menu control. :param int dev_id: :return: @@ -302,8 +295,7 @@ def audit_server_version(self, min_ver): """ Audit Indigo Version - Compare current Indigo version to the minimum version required to successfully run the - plugin. + Compare current Indigo version to the minimum version required to successfully run the plugin. :param int min_ver: @@ -312,9 +304,7 @@ def audit_server_version(self, min_ver): ver = self.plugin.versStrToTuple(indigo.server.version) if ver[0] < min_ver: - self.plugin.stopPlugin( - f"This plugin requires Indigo version {min_ver} or above.", isError=True - ) + self.plugin.stopPlugin(f"This plugin requires Indigo version {min_ver} or above.", isError=True) self.plugin.logger.debug("Indigo server version OK.") @@ -323,8 +313,8 @@ def audit_os_version(self, min_ver): """ Audit Operating System Version - Compare current OS version to the minimum version required to successfully run the plugin. - Thanks to FlyingDiver for improved audit code. + Compare current OS version to the minimum version required to successfully run the plugin. Thanks to + FlyingDiver for improved audit code. :param float min_ver: :return: @@ -335,9 +325,7 @@ def audit_os_version(self, min_ver): current_ver = tuple(map(int, (str(mac_os).split(".")))) # current version. i.e., (11, 4) if current_ver < min_ver: - self.plugin.stopPlugin( - f"The plugin requires macOS version {min_ver} or above.", isError=True - ) + self.plugin.stopPlugin(f"The plugin requires macOS version {min_ver} or above.", isError=True) else: self.plugin.logger.debug("macOS version OK.") @@ -362,8 +350,8 @@ def __init__(self, plugin): # ============================================================================= def dateFormat(self): # noqa """ - The dateFormat method takes the user configuration preference for date and time display and - converts them to a valid datetime() format specifier. + The dateFormat method takes the user configuration preference for date and time display and converts them to a + valid datetime() format specifier. :return: """ @@ -378,8 +366,8 @@ def dateFormat(self): # noqa # ============================================================================= def timeFormat(self): # noqa """ - The timeFormat method takes the user configuration preference for date and time display and - converts them to a valid datetime() format specifier. + The timeFormat method takes the user configuration preference for date and time display and converts them to a + valid datetime() format specifier. :return: """ @@ -391,8 +379,7 @@ def timeFormat(self): # noqa # ============================================================================= class evalExpr: # noqa """ - The evalExpr method evaluates mathematical expressions that are passed as strings and returns a - numerical result. + The evalExpr method evaluates mathematical expressions that are passed as strings and returns a numerical result. This code is licensed under an MIT-compatible license. credit: jfs @ https://stackoverflow.com/a/9558001/2827397 @@ -434,8 +421,8 @@ def __eval(self, node): :return: """ - # See https://stackoverflow.com/q/71353183/2827397 (and the accompanying answer) for an - # explanation of the code inspection warnings thrown by this method. + # See https://stackoverflow.com/q/71353183/2827397 (and the accompanying answer) for an explanation of the code + # inspection warnings thrown by this method. try: if isinstance(node, ast.Num): # value = node.n @@ -452,11 +439,13 @@ def __eval(self, node): class DummyClass: - - def Dave(self, at1="foo", at2=0): + """ + Dummy class used for testing. + """ + @staticmethod + def dave(at1="foo", at2=0): """ - This docstring is loosely formatted to `PEP 287` with a nod towards PyCharm reStructured - Text rendering. + This docstring is loosely formatted to `PEP 287` with a nod towards PyCharm reStructured Text rendering. :param str at1: This is a string attribute. :param int at2: This is an integer attribute. diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/Devices.xml b/matplotlib.indigoPlugin/Contents/Server Plugin/Devices.xml index cf6f8e6..f3f3fad 100755 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/Devices.xml +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/Devices.xml @@ -1123,7 +1123,7 @@ diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_flow.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_flow.py index f26bd15..953cec2 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_flow.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_flow.py @@ -61,7 +61,7 @@ def __init__(): f"in the device configuration menu." ) - # Plot the bars. If 'suppressBar{thing} is True, we skip it. + # Plot the bars. If 'suppressBar{thing}' is True, we skip it. if P_DICT[f'bar{thing}Source'] not in ("", "None") and not suppress_bar: # If the bar color is the same as the background color, alert the user. diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_stock.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_stock.py index e0e8cd3..84d036b 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_stock.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_bar_stock.py @@ -117,7 +117,6 @@ def __init__(): # If annotations desired, plot those too. annotate = P_DICT[f'bar{b_num}Annotate'] precision = int(PROPS.get(f'bar{b_num}AnnotationPrecision', "0")) - # if bar[f'annotate_{b_num}'] and not suppress_bar: if annotate and bar[f'annotate_{b_num}'] and not suppress_bar: ax.annotate( # ANNOTATION_VALUE[b_num - 1], diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_line.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_line.py index e5b50be..04fed0b 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_line.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_line.py @@ -183,10 +183,10 @@ def __init__(): if P_DICT['transparent_charts'] and P_DICT['transparent_filled']: ax.add_patch( patches.Rectangle( - (0, 0), 1, 1, - transform=ax.transAxes, - facecolor=P_DICT['faceColor'], - zorder=1 + (0, 0), 1, 1, + transform=ax.transAxes, + facecolor=P_DICT['faceColor'], + zorder=1 ) ) diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_tools.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_tools.py index 60037fe..0cf280e 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_tools.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_tools.py @@ -50,7 +50,7 @@ def __init__(): # ============================================================================= -def convert_the_data(final_data, data_source, logger): +def convert_the_data(final_data: list, data_source: str, logger: dict): """ Convert data into form that matplotlib can understand @@ -59,9 +59,9 @@ def convert_the_data(final_data, data_source, logger): example, the WUnderground plugin will present '-99.0' when WUnderground is not able to deliver a rational value. Therefore, we convert '-99.0' to NaN values. ----- - :param logger: :param list final_data: the data to be charted :param str data_source: + :param dict logger: """ LOG['Debug'].append(f"[{payload['props']['name']}] " @@ -212,9 +212,9 @@ def format_axis(ax_obj): ax_cells = ax_props['children'] for cell in ax_cells: cell.set_facecolor(payload['p_dict']['faceColor']) - cell._text.set_color(payload['p_dict']['fontColor']) - cell._text.set_fontname(payload['p_dict']['fontMain']) - cell._text.set_fontsize(int(payload['props']['fontSize'])) + cell._text.set_color(payload['p_dict']['fontColor']) # noqa + cell._text.set_fontname(payload['p_dict']['fontMain']) # noqa + cell._text.set_fontsize(int(payload['props']['fontSize'])) # noqa cell.set_linewidth(int(plt.rcParams['lines.linewidth'])) # This may not be supportable without including fonts with the plugin. @@ -680,11 +680,11 @@ def format_best_fit_line_segments(ax, dates_to_plot, line, p_dict, logger): fit lines are not appropriate for all chart types). ----- :param class 'matplotlib.axes.AxesSubplot' ax: - :return numpy.ndarray dates_to_plot: + :param numpy.ndarray dates_to_plot: :param int line: :param dict p_dict: plotting parameters - :return ax: :param dict logger: + :return ax: """ LOG['Debug'].append(f"[{payload['props']['name']}] Formatting best fit line segments.") @@ -922,7 +922,7 @@ def get_data(data_source, logger): # ============================================================================= -def hide_anomalies(data, props=True, logger=[]): +def hide_anomalies(data: tuple=None, props: dict=None, logger: dict=None): """Detect outliers in data and replace them with 'NaN'. Credit: https://gist.github.com/wmlba/89bc2f4556b8ee397ca7a5017b497657#file-outlier_std-py diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_composite.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_composite.py index 85a81e8..909bd79 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_composite.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_composite.py @@ -58,12 +58,15 @@ def __init__(): ... - def format_subplot(s_plot, title="Title"): + def format_subplot(s_plot, title: str="Title"): """ Title Placeholder Note that we have to set these for each subplot as it's rendered or else the settings will only be applied to the last subplot rendered. + + :param s_plot: + :param str title: """ s_plot.set_title(title, **K_DICT['k_title_font']) # The subplot title chart_tools.format_axis_x_ticks(ax=s_plot, p_dict=P_DICT, k_dict=K_DICT, logger=LOG) @@ -159,7 +162,6 @@ def transparent_chart_fill(s): figsize=(WIDTH / DPI, HEIGHT * num_axes / DPI) ) - chart_tools.format_title(p_dict=P_DICT, k_dict=K_DICT, loc=(0.5, 0.99)) try: diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_forecast.py b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_forecast.py index 7817b86..01167d7 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_forecast.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/chart_weather_forecast.py @@ -344,7 +344,7 @@ def __init__(): P_DICT[f'y_obs{line}'], color=P_DICT[f'line{line}Color'], linestyle=P_DICT[f'line{line}Style'], - marker=P_DICT[f'line{line}Marker'],\ + marker=P_DICT[f'line{line}Marker'], markerfacecolor=P_DICT[f'line{line}MarkerColor'], zorder=(10 - line), **K_DICT['k_line'] @@ -364,8 +364,7 @@ def __init__(): **K_DICT['k_annotation'] ) - # Take a snapshot of the data for some computations below (P_DICT['data_array'] can be modified - # elsewhere. + # Take a snapshot of the data for some computations below (P_DICT['data_array']) can be modified elsewhere. just_the_data = deepcopy(P_DICT['data_array']) chart_tools.format_axis_x_ticks(ax=ax2, p_dict=P_DICT, k_dict=K_DICT, logger=LOG) diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/maintenance.py b/matplotlib.indigoPlugin/Contents/Server Plugin/maintenance.py index 2280cb9..478dff6 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/maintenance.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/maintenance.py @@ -11,7 +11,7 @@ # Third-party Modules try: - import indigo + import indigo # noqa except ImportError: ... @@ -22,20 +22,20 @@ __copyright__ = "Copyright 2017-2019 DaveL17" __license__ = "MIT" __title__ = "maintenance" -__version__ = "0.1.02" +__version__ = "0.1.03" class Maintain: """ - Title Placeholder + Various plugin maintenance utilities - Body placeholder + Maintain is a container for code that makes specific to consolidate methods used throughout all Indigo + plugins with the com.fogbert.indigoPlugin.xxxx bundle identifier. It can be customized for each plugin. """ def __init__(self, plugin): """ - Title Placeholder + Constructor - Body placeholder :param plugin: """ self.plugin = plugin @@ -48,14 +48,14 @@ def __init__(self, plugin): # my_logger.threaddebug("Initializing maintenance framework.") self.my_logger.debug("Initializing maintenance framework.x") - def clean_prefs(self, dev_name, prefs): + def clean_prefs(self, dev_name: str, prefs: dict): """ Remove legacy keys from non-chart device prefs None of the keys listed here should be present in device types using this method to clean their prefs. If they exist, delete them. ----- - :param unicode dev_name: + :param str dev_name: :param dict prefs: :return: """ @@ -365,12 +365,12 @@ def clean_prefs(self, dev_name, prefs): return prefs - def clean_props(self, dev): + def clean_props(self, dev: indigo.Device): """ Remove legacy keys from device prefs ----- - + :param indigo.Device dev: :return: """ props = dev.pluginProps diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/plugin.py b/matplotlib.indigoPlugin/Contents/Server Plugin/plugin.py index f92c32f..0d18383 100755 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/plugin.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/plugin.py @@ -65,7 +65,7 @@ __license__ = Dave.__license__ __build__ = Dave.__build__ __title__ = "Matplotlib Plugin for Indigo" -__version__ = "2022.1.7" +__version__ = "2023.0.1" # ============================================================================= @@ -75,7 +75,7 @@ class Plugin(indigo.PluginBase): :param indigo.PluginBase: """ - def __init__(self, plugin_id="", plugin_display_name="", plugin_version="", plugin_prefs=None): + def __init__(self, plugin_id: str="", plugin_display_name: str="", plugin_version: str="", plugin_prefs: indigo.Dict=None): # noqa """ Plugin initialization @@ -148,7 +148,7 @@ def __del__(self): # ============================================================================= # ============================== Indigo Methods =============================== # ============================================================================= - def closedDeviceConfigUi(self, values_dict=None, user_cancelled=False, type_id="", dev_id=0): # noqa + def closed_device_config_ui(self, values_dict: indigo.Dict=None, user_cancelled: bool=False, type_id: str= "", dev_id: int=0): # noqa """ Title Placeholder @@ -174,7 +174,7 @@ def closedDeviceConfigUi(self, values_dict=None, user_cancelled=False, type_id=" return True # ============================================================================= - def closedPrefsConfigUi(self, values_dict=None, user_cancelled=False): # noqa + def closed_prefs_config_ui(self, values_dict: indigo.Dict=None, user_cancelled: bool=False): # noqa """ Standard Indigo method called when plugin preferences dialog is closed. @@ -214,7 +214,7 @@ def closedPrefsConfigUi(self, values_dict=None, user_cancelled=False): # noqa return values_dict # ============================================================================= - def deviceStartComm(self, dev=None): # noqa + def device_start_comm(self, dev: indigo.Device=None): # noqa """ Title Placeholder @@ -233,7 +233,7 @@ def deviceStartComm(self, dev=None): # noqa # ============================================================================= @staticmethod - def deviceStopComm(dev=None): # noqa + def device_stop_comm(dev: indigo.Device=None): # noqa """ Title Placeholder @@ -246,7 +246,7 @@ def deviceStopComm(dev=None): # noqa dev.updateStateImageOnServer(indigo.kStateImageSel.SensorOff) # ============================================================================= - def getActionConfigUiValues(self, values_dict=None, type_id="", dev_id=0): # noqa + def getActionConfigUiValues(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Title Placeholder @@ -270,7 +270,7 @@ def getActionConfigUiValues(self, values_dict=None, type_id="", dev_id=0): # no return result # ============================================================================= - def getDeviceConfigUiValues(self, values_dict=None, type_id="", dev_id=0): # noqa + def getDeviceConfigUiValues(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Title Placeholder @@ -494,7 +494,7 @@ def getDeviceConfigUiValues(self, values_dict=None, type_id="", dev_id=0): # no return True, values_dict # ============================================================================= - def getDeviceStateList(self, dev=None): # noqa + def getDeviceStateList(self, dev: indigo.Device=None): # noqa """ Title Placeholder @@ -519,13 +519,13 @@ def getDeviceStateList(self, dev=None): # noqa return state_list # ============================================================================= - def getMenuActionConfigUiValues(self, menu_id=""): # noqa + def getMenuActionConfigUiValues(self, menu_id: str=""): # noqa """ Title Placeholder Body placeholder - :param int menu_id: + :param str menu_id: :return: """ settings = indigo.Dict() @@ -621,7 +621,7 @@ def runConcurrentThread(self): # noqa # ============================================================================= @staticmethod - def sendDevicePing(dev_id=0, suppress_logging=False): # noqa + def sendDevicePing(dev_id: int=0, suppress_logging: bool=False): # noqa """ Title Placeholder @@ -672,7 +672,7 @@ def shutdown(self): self.pluginIsShuttingDown = True # ============================================================================= - def validatePrefsConfigUi(self, values_dict=None): # noqa + def validatePrefsConfigUi(self, values_dict: indigo.Dict=None): # noqa """ Title Placeholder @@ -736,7 +736,7 @@ def validatePrefsConfigUi(self, values_dict=None): # noqa return True, values_dict # ============================================================================= - def validateDeviceConfigUi(self, values_dict=None, type_id="", dev_id=0): # noqa + def validateDeviceConfigUi(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Title Placeholder @@ -1174,7 +1174,7 @@ def validateDeviceConfigUi(self, values_dict=None, type_id="", dev_id=0): # noq return True, values_dict, error_msg_dict # ============================================================================= - def validateMenuConfigUi(self, values_dict=None, type_id="", dev_id=0): # noqa + def validateMenuConfigUi(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Title Placeholder @@ -1191,7 +1191,7 @@ def validateMenuConfigUi(self, values_dict=None, type_id="", dev_id=0): # noqa return True, values_dict # ============================================================================= - def __log_dicts(self, dev=None): + def __log_dicts(self, dev: indigo.Device=None): """ Write parameters dicts to log under verbose logging @@ -1202,7 +1202,7 @@ def __log_dicts(self, dev=None): self.logger.threaddebug(f"[{dev.name:<19}] Props: {dict(dev.pluginProps)}") # ============================================================================= - def dummyCallback(self, values_dict=None, type_id="", target_id=0): # noqa + def dummyCallback(self, values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Dummy callback method to force dialog refreshes @@ -1232,7 +1232,7 @@ def action_refresh_the_charts(self, plugin_action): # noqa self.logger.info(f"{' Redraw All Charts Action Complete ':=^80}") # ============================================================================= - def advancedSettingsExecuted(self, values_dict=None, menu_id=0): # noqa + def advancedSettingsExecuted(self, values_dict: indigo.Dict=None, menu_id: int=0): # noqa """ Save advanced settings menu items to plugin props for storage @@ -1252,7 +1252,7 @@ def advancedSettingsExecuted(self, values_dict=None, menu_id=0): # noqa return True # ============================================================================= - def advancedSettingsMenu(self, values_dict=None, type_id="", dev_id=0): # noqa + def advancedSettingsMenu(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Write advanced settings menu selections to the log @@ -1323,9 +1323,9 @@ def audit_device_props(self): will be _added_ to the device (checkboxes will be coerced to boolean based on the defaultValue attribute if specified; unspecified, the value will be set to False.) and (2) where the current pluginProps contains keys that are not in the config, they will be _removed_ from the device. The method will return True if it has run - error free; False on exception. Note that this method should _not_ be called from deviceStartComm() as it will + error free; False on exception. Note that this method should _not_ be called from device_start_comm() as it will cause an infinite loop--the call to dev.replacePluginPropsOnServer() from this method automatically calls - deviceStartComm(). It is recommended that the method be called from plugin's startup() method. + device_start_comm(). It is recommended that the method be called from plugin's startup() method. :return: """ @@ -1398,7 +1398,7 @@ def audit_device_props(self): return False # ============================================================================= - def audit_dict_color(self, _dict_): + def audit_dict_color(self, _dict_: dict): """ Title Placeholder @@ -1512,7 +1512,7 @@ def audit_themes_file(): outfile.write(json.dumps({}, indent=4)) # ============================================================================= - def chart_stock_bar(self, dev=None): + def chart_stock_bar(self, dev: indigo.Device=None): """ Title Placeholder @@ -1569,7 +1569,7 @@ def chart_stock_bar(self, dev=None): return bars_data # ============================================================================= - def charts_refresh(self, dev_list=None): + def charts_refresh(self, dev_list: list=None): """ Refreshes all the plugin chart devices. @@ -1577,14 +1577,14 @@ def charts_refresh(self, dev_list=None): :param list dev_list: list of devices to be refreshed. """ - def convert_to_native(obj): + def convert_to_native(obj: (indigo.Dict, indigo.List)): """ Convert any indigo.Dict and indigo.List objects to native formats. credit: Jay Martin https://forums.indigodomo.com/viewtopic.php?p=193744#p193744 - :param obj: + :param (indigo.Dict, indigo.List) obj: :return: """ if isinstance(obj, indigo.List): @@ -1808,10 +1808,10 @@ def convert_to_native(obj): 'bbox_extra_artists': None, 'bbox_inches': None, 'format': None, - 'frameon': None, + # 'frameon': None, 'orientation': None, 'pad_inches': None, - 'papertype': None, + # 'papertype': None, 'transparent': True } else: @@ -1821,10 +1821,10 @@ def convert_to_native(obj): 'edgecolor': p_dict['backgroundColor'], 'facecolor': p_dict['backgroundColor'], 'format': None, - 'frameon': None, + # 'frameon': None, 'orientation': None, 'pad_inches': None, - 'papertype': None, + # 'papertype': None, 'transparent': False } @@ -2324,7 +2324,7 @@ def convert_to_native(obj): self.logger.debug(f"Payload raised error: {payload}") # Parse the output log - result = self.process_plotting_log(device=dev, replies=reply, errors=err) + result = self.process_plotting_log(dev=dev, replies=reply, errors=err) # If we have manually asked for all charts to update, don't refresh the last update time so # that the charts will update on their own at the next refresh cycle. if 'chartLastUpdated' in dev.states and not self.skipRefreshDateUpdate: @@ -2437,7 +2437,7 @@ def csv_check_unique(self): ) # ============================================================================= - def csv_item_add(self, values_dict=None, type_id="", dev_id=0): # noqa + def csv_item_add(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Add new item to CSV engine @@ -2518,7 +2518,7 @@ def csv_item_add(self, values_dict=None, type_id="", dev_id=0): # noqa return values_dict, error_msg_dict # ============================================================================= - def csv_item_delete(self, values_dict=None, type_id="", dev_id=0): # noqa + def csv_item_delete(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Deletes items from the CSV Engine configuration dialog @@ -2558,7 +2558,7 @@ def csv_item_delete(self, values_dict=None, type_id="", dev_id=0): # noqa return values_dict # ============================================================================= - def csv_item_list(self, filter="", values_dict=None, type_id="", target_id=0): # noqa + def csv_item_list(self, filter: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Construct the list of CSV items @@ -2592,7 +2592,7 @@ def csv_item_list(self, filter="", values_dict=None, type_id="", target_id=0): return result # ============================================================================= - def csv_item_update(self, values_dict=None, type_id="", dev_id=0): # noqa + def csv_item_update(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Updates items from the CSV Engine configuration dialog @@ -2655,7 +2655,7 @@ def csv_item_update(self, values_dict=None, type_id="", dev_id=0): # noqa return values_dict, error_msg_dict # ============================================================================= - def csv_item_select(self, values_dict=None, type_id="", dev_id=0): # noqa + def csv_item_select(self, values_dict: indigo.Dict=None, type_id: str="", dev_id: int=0): # noqa """ Populates CSV engine controls for updates and deletions @@ -2725,7 +2725,7 @@ def csv_refresh(self): self.csv_refresh_process(dev=dev, csv_dict=csv_dict) # ============================================================================= - def csv_refresh_process(self, dev=None, csv_dict=None): + def csv_refresh_process(self, dev: indigo.Device=None, csv_dict: dict=None): """ The csv_refresh_process() method processes CSV update requests @@ -2909,9 +2909,7 @@ def csv_refresh_process(self, dev=None, csv_dict=None): self.logger.critical(f"[{dev.name}] Error: {sub_error}") # ============================================================================= - def csv_refresh_device_action( - self, plugin_action=None, dev=None, caller_waiting_for_result=False # noqa - ): + def csv_refresh_device_action(self, plugin_action: indigo.ActionGroup=None, dev: indigo.Device=None, caller_waiting_for_result: bool=False): # noqa """ Perform a manual refresh of a single CSV Device @@ -2919,7 +2917,7 @@ def csv_refresh_device_action( will update all CSV sources associated with the selected CSV Engine device each time the Action item is called. Only CSV Engine devices set to a manual refresh interval will be presented. - :param indigo.PluginAction plugin_action: + :param indigo.ActionGroup plugin_action: :param indigo.Device dev: :param bool caller_waiting_for_result: :return: @@ -2941,7 +2939,7 @@ def csv_refresh_device_action( # ============================================================================= def csv_refresh_source_action( - self, plugin_action=None, dev=None, caller_waiting_for_result=False # noqa + self, plugin_action: indigo.ActionGroup=None, dev: indigo.Device=None, caller_waiting_for_result: bool=False # noqa ): """ Perform a manual refresh of a single CSV Source @@ -2951,11 +2949,12 @@ def csv_refresh_source_action( sources will be displayed. The user selects a single CSV source that will be updated each time the Action is called. Only CSV Engine devices set to a manual refresh interval will be presented. - :param indigo.PluginAction plugin_action: + :param indigo.ActionGroup plugin_action: :param indigo.Device dev: :param bool caller_waiting_for_result: :return: """ + indigo.server.log(f"{plugin_action}") dev_id = int(plugin_action.props['targetDevice']) dev = indigo.devices[dev_id] @@ -2971,7 +2970,7 @@ def csv_refresh_source_action( # ============================================================================= @staticmethod - def csv_source(type_id="", values_dict=None, dev_id=0, target_id=0): # noqa + def csv_source(type_id: str="", values_dict: indigo.Dict=None, dev_id: int=0, target_id: int=0): # noqa """ Construct a list of devices and variables for the CSV engine @@ -3015,7 +3014,7 @@ def csv_source(type_id="", values_dict=None, dev_id=0, target_id=0): # noqa # ============================================================================= @staticmethod - def csv_source_edit(type_id="", values_dict=None, dev_id=0, target_id=0): # noqa + def csv_source_edit(type_id: str="", values_dict: indigo.Dict=None, dev_id: int=0, target_id: int=0): # noqa """ Construct a list of devices and variables for the CSV engine @@ -3064,7 +3063,7 @@ def csv_source_edit(type_id="", values_dict=None, dev_id=0, target_id=0): # noq # ============================================================================= @staticmethod - def get_csv_device_list(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def get_csv_device_list(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Return a list of CSV Engine devices set to manual refresh @@ -3083,7 +3082,7 @@ def get_csv_device_list(fltr="", values_dict=None, type_id="", target_id=0): # # ============================================================================= @staticmethod - def get_csv_source_list(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def get_csv_source_list(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Return a list of CSV sources from CSV Engine devices set to manual refresh @@ -3113,7 +3112,7 @@ def get_csv_source_list(fltr="", values_dict=None, type_id="", target_id=0): # # ============================================================================= @staticmethod - def device_state_value_list_add(type_id="", values_dict=None, dev_id=0, target_id=0): # noqa + def device_state_value_list_add(type_id: str="", values_dict: indigo.Dict=None, dev_id: int=0, target_id: int=0): # noqa """ Formulates list of device states for CSV engine @@ -3159,7 +3158,7 @@ def device_state_value_list_add(type_id="", values_dict=None, dev_id=0, target_i # ============================================================================= @staticmethod - def device_state_value_list_edit(type_id="", values_dict=None, dev_id=0, target_id=0): # noqa + def device_state_value_list_edit(type_id: str="", values_dict: indigo.Dict=None, dev_id: int=0, target_id: int=0): # noqa """ Formulates list of device states for CSV engine @@ -3204,7 +3203,7 @@ def device_state_value_list_edit(type_id="", values_dict=None, dev_id=0, target_ # ============================================================================= @staticmethod - def fix_rgb(color=""): # noqa + def fix_rgb(color: str=""): # noqa """ Title Placeholder @@ -3220,7 +3219,7 @@ def fix_rgb(color=""): # noqa # ============================================================================= @staticmethod - def format_markers(p_dict=None): # noqa + def format_markers(p_dict: dict=None): # noqa """ Format matplotlib markers @@ -3248,7 +3247,7 @@ def format_markers(p_dict=None): # noqa return p_dict # ============================================================================= - def generatorDeviceStates(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorDeviceStates(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns device states list or variable 'value'. @@ -3270,7 +3269,7 @@ def generatorDeviceStates(self, fltr="", values_dict=None, type_id="", target_id return self.Fogbert.generatorStateOrValue(values_dict[fltr]) # ============================================================================= - def generatorDeviceList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorDeviceList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of Indigo variables. @@ -3287,7 +3286,7 @@ def generatorDeviceList(self, fltr="", values_dict=None, type_id="", target_id=0 # ============================================================================= @staticmethod - def generatorPrecisionList(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorPrecisionList(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of value precision options for pulldown menus. @@ -3306,7 +3305,7 @@ def generatorPrecisionList(fltr="", values_dict=None, type_id="", target_id=0): # ============================================================================= @staticmethod - def generatorLineStyleDefaultNoneList(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorLineStyleDefaultNoneList(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of Matplotlib line styles for pulldown menus. @@ -3327,7 +3326,7 @@ def generatorLineStyleDefaultNoneList(fltr="", values_dict=None, type_id="", tar # ============================================================================= @staticmethod - def generatorLineStyleDefaultSolidList(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorLineStyleDefaultSolidList(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of Matplotlib line styles for pulldown menus. @@ -3348,7 +3347,7 @@ def generatorLineStyleDefaultSolidList(fltr="", values_dict=None, type_id="", ta # ============================================================================= @staticmethod - def generatorMarkerList(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorMarkerList(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of Matplotlib Markers for pulldown menus. @@ -3387,7 +3386,7 @@ def generatorMarkerList(fltr="", values_dict=None, type_id="", target_id=0): # return marker_list # ============================================================================= - def latestDevVarList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def latestDevVarList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Title Placeholder @@ -3402,7 +3401,7 @@ def latestDevVarList(self, fltr="", values_dict=None, type_id="", target_id=0): return self.dev_var_list # ============================================================================= - def generatorDeviceAndVariableList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorDeviceAndVariableList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Create a list of devices and variables for config menu controls @@ -3419,7 +3418,7 @@ def generatorDeviceAndVariableList(self, fltr="", values_dict=None, type_id="", return self.Fogbert.deviceAndVariableList() # ============================================================================= - def generatorVariableList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def generatorVariableList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of Indigo variables. @@ -3436,7 +3435,7 @@ def generatorVariableList(self, fltr="", values_dict=None, type_id="", target_id # ============================================================================= @staticmethod - def get_axis_list(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def get_axis_list(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Returns a list of axis formats. @@ -3474,7 +3473,7 @@ def get_axis_list(fltr="", values_dict=None, type_id="", target_id=0): # noqa # ============================================================================= @staticmethod - def get_battery_device_list(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def get_battery_device_list(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Create a list of battery-powered devices @@ -3495,7 +3494,7 @@ def get_battery_device_list(fltr="", values_dict=None, type_id="", target_id=0): return batt_list # ============================================================================= - def getFileList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def getFileList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Get list of CSV files for various dropdown menus. @@ -3530,7 +3529,7 @@ def getFileList(self, fltr="", values_dict=None, type_id="", target_id=0): # no return file_name_list_menu # ============================================================================= - def getFontList(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def getFontList(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Provide a list of font names for various dropdown menus. @@ -3562,7 +3561,7 @@ def getFontList(self, fltr="", values_dict=None, type_id="", target_id=0): # no # ============================================================================= @staticmethod - def getRefreshList(fltr="", values_dict=None, type_id="", target_id=0): # noqa + def getRefreshList(fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ :param str fltr: @@ -3582,7 +3581,7 @@ def getRefreshList(fltr="", values_dict=None, type_id="", target_id=0): # noqa return menu # ============================================================================= - def getForecastSource(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def getForecastSource(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Return a list of WUnderground devices for forecast chart devices @@ -3622,7 +3621,7 @@ def getForecastSource(self, fltr="", values_dict=None, type_id="", target_id=0): return sorted(forecast_source_menu, key=lambda s: s[1].lower()) # ============================================================================= - def plotActionApi(self, plugin_action=None, dev=None, caller_waiting_for_result=False): # noqa + def plotActionApi(self, plugin_action: indigo.ActionGroup=None, dev: indigo.Device=None, caller_waiting_for_result: bool=False): # noqa """ Plugin API handler @@ -3642,7 +3641,7 @@ def plotActionApi(self, plugin_action=None, dev=None, caller_waiting_for_result= 'filename': 'chart_filename.png' } - :param indigo.PluginAction plugin_action: + :param indigo.ActionGroup plugin_action: :param indigo.Device dev: :param bool caller_waiting_for_result: """ @@ -3758,7 +3757,7 @@ def pluginEnvironmentLogger(self): # noqa self.logger.threaddebug(f"{'Initial Plugin Prefs:':<31} {dict(self.pluginPrefs)}") # ============================================================================= - def plugin_error_handler(self, sub_error=""): + def plugin_error_handler(self, sub_error: str=""): """ Centralized handling of traceback messages @@ -3777,14 +3776,14 @@ def plugin_error_handler(self, sub_error=""): self.logger.critical("!" * 80) # ============================================================================= - def process_plotting_log(self, device=None, replies=b"", errors=""): + def process_plotting_log(self, dev: indigo.Device=None, replies: bytes=b"", errors: str=""): """ Process output of multiprocessing queue messages The processLogQueue() method accepts a multiprocessing queue that contains log messages. The method parses those messages across the various self.logger.* calls. - :param indigo.Device device: + :param indigo.Device dev: :param bytes replies: :param str errors: """ @@ -3809,11 +3808,11 @@ def process_plotting_log(self, device=None, replies=b"", errors=""): success = False if not success: - device.updateStateImageOnServer(indigo.kStateImageSel.SensorTripped) - self.logger.critical(f"[{device.name}] error producing chart. See logs for more information.") + dev.updateStateImageOnServer(indigo.kStateImageSel.SensorTripped) + self.logger.critical(f"[{dev.name}] error producing chart. See logs for more information.") else: - device.updateStateImageOnServer(indigo.kStateImageSel.SensorOn) - self.logger.info(f"[{device.name}] chart refreshed.") + dev.updateStateImageOnServer(indigo.kStateImageSel.SensorOn) + self.logger.info(f"[{dev.name}] chart refreshed.") return success @@ -3827,18 +3826,18 @@ def process_plotting_log(self, device=None, replies=b"", errors=""): elif "'numpy.float64' object cannot be interpreted as an index" in errors: self.logger.critical( - f"[{device.name}] Unfortunately, your version of Matplotlib doesn't support Polar chart plotting. " + f"[{dev.name}] Unfortunately, your version of Matplotlib doesn't support Polar chart plotting. " f"Disabling device." ) - indigo.device.enable(device, False) + indigo.device.enable(dev, False) else: self.logger.critical(errors) - device.updateStateImageOnServer(indigo.kStateImageSel.Error) + dev.updateStateImageOnServer(indigo.kStateImageSel.Error) # ============================================================================= @staticmethod - def rc_params_device_update(dev=None): # noqa + def rc_params_device_update(dev: indigo.Device=None): # noqa """ Update rcParams device with updated state values @@ -3858,14 +3857,14 @@ def rc_params_device_update(dev=None): # noqa dev.updateStatesOnServer([{'key': 'onOffState', 'value': True, 'uiValue': 'Updated'}]) # ============================================================================= - def refreshAChartAction(self, plugin_action=None): # noqa + def refreshAChartAction(self, plugin_action: indigo.ActionGroup=None): # noqa """ Refreshes an individual plugin chart device. Process Indigo Action item call for a chart refresh. Passes the id of the device called from the action. This method is a handler to pass along the action call. The action will refresh only the specified chart. - :param indigo.PluginAction plugin_action: + :param indigo.ActionGroup plugin_action: """ # Indigo will trap if device is disabled. dev = indigo.devices[plugin_action.deviceId] @@ -3873,7 +3872,7 @@ def refreshAChartAction(self, plugin_action=None): # noqa self.logger.info(f"{' Redraw a Chart Action Complete ':{'='}^80}") # ============================================================================= - def refresh_the_charts_now(self, values_dict=None, menu_id=""): # noqa + def refresh_the_charts_now(self, values_dict: indigo.Dict=None, menu_id: str=""): # noqa """ Refresh all enabled charts @@ -3930,11 +3929,11 @@ def work_the_refresh_queue(): t.start() # ============================================================================= - def save_snapshot(self, action=None): # noqa + def save_snapshot(self, action: indigo.ActionGroup=None): # noqa """ Save a snapshot of select plugin information to disk for later debugging. - :param indigo.PluginAction action: + :param indigo.ActionGroup action: """ home = os.path.expanduser("~") with open(home + "/matplotlib_snapshot.txt", 'w', encoding='utf-8') as outfile: @@ -3948,7 +3947,7 @@ def save_snapshot(self, action=None): # noqa indigo.server.log('Snapshot written to user home directory.') # ============================================================================= - def themeNameGenerator(self, fltr="", values_dict=None, type_id="", target_id=0): # noqa + def themeNameGenerator(self, fltr: str="", values_dict: indigo.Dict=None, type_id: str="", target_id: int=0): # noqa """ Generate a list of theme names from the json file for UI controls @@ -3966,7 +3965,7 @@ def themeNameGenerator(self, fltr="", values_dict=None, type_id="", target_id=0) return [(key, key) for key in sorted(infile)] # ============================================================================= - def themeManagerCloseUi(self, values_dict=None, menu_item_id=""): # noqa + def themeManagerCloseUi(self, values_dict: indigo.Dict=None, menu_item_id: str=""): # noqa """ Apply theme settings when user closes Theme Manager dialog @@ -3989,11 +3988,11 @@ def themeManagerCloseUi(self, values_dict=None, menu_item_id=""): # noqa return True # ============================================================================= - def themeApplyAction(self, plugin_action=None): # noqa + def themeApplyAction(self, plugin_action: indigo.ActionGroup=None): # noqa """ Process the Indigo Apply Theme action item - :param indigo.PluginAction plugin_action: + :param indigo.ActionGroup plugin_action: """ full_path = f"{indigo.server.getInstallFolderPath()}/Preferences/Plugins/matplotlib plugin themes.json" selected_theme = plugin_action.props['targetTheme'] @@ -4014,7 +4013,7 @@ def themeApplyAction(self, plugin_action=None): # noqa self.logger.info(f"[{selected_theme}] theme applied.") # ============================================================================= - def themeApply(self, values_dict=None, menu_item_id=""): # noqa + def themeApply(self, values_dict: indigo.Dict=None, menu_item_id: str=""): # noqa """ Process the Theme Manager Apply Theme action @@ -4047,7 +4046,7 @@ def themeApply(self, values_dict=None, menu_item_id=""): # noqa return values_dict # ============================================================================= - def themeExecuteActionButton(self, values_dict=None, menu_item_id=0): # noqa + def themeExecuteActionButton(self, values_dict: indigo.Dict=None, menu_item_id: str=0): # noqa """ Process the Theme Manager Execute Action button press @@ -4077,7 +4076,7 @@ def themeExecuteActionButton(self, values_dict=None, menu_item_id=0): # noqa # ============================================================================= @staticmethod - def theme_rename(values_dict=None, menu_item_id=""): # noqa + def theme_rename(values_dict: indigo.Dict=None, menu_item_id: str=""): # noqa """ Process the Theme Manager Rename Theme action @@ -4119,12 +4118,12 @@ def theme_rename(values_dict=None, menu_item_id=""): # noqa return values_dict # ============================================================================= - def theme_save(self, values_dict=None, menu_item_id=None): # noqa + def theme_save(self, values_dict: indigo.Dict=None, menu_item_id: str=""): # noqa """ Process the Theme Manager Save Theme action :param indigo.Dict values_dict: - :param int menu_item_id: + :param str menu_item_id: """ self.logger.debug("theme_save") full_path = f"{indigo.server.getInstallFolderPath()}/Preferences/Plugins/matplotlib plugin themes.json" @@ -4174,7 +4173,7 @@ def theme_save(self, values_dict=None, menu_item_id=None): # noqa # ============================================================================= @staticmethod - def theme_delete(values_dict=None, menu_item_id=""): # noqa + def theme_delete(values_dict: indigo.Dict=None, menu_item_id: str=""): # noqa """ Process the Theme Manager Delete Theme action @@ -4229,7 +4228,7 @@ def __init__(self): # ============================================================================= @staticmethod - def clean_string(val=""): # noqa + def clean_string(val: str=""): # noqa """ Cleans long strings of whitespace and formats certain characters diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/plugin_defaults.py b/matplotlib.indigoPlugin/Contents/Server Plugin/plugin_defaults.py index 645422d..d3a4165 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/plugin_defaults.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/plugin_defaults.py @@ -3,7 +3,7 @@ """ try: - import indigo + import indigo # noqa except ImportError: ... diff --git a/matplotlib.indigoPlugin/Contents/Server Plugin/validate.py b/matplotlib.indigoPlugin/Contents/Server Plugin/validate.py index d08bb8d..afffa09 100644 --- a/matplotlib.indigoPlugin/Contents/Server Plugin/validate.py +++ b/matplotlib.indigoPlugin/Contents/Server Plugin/validate.py @@ -8,6 +8,11 @@ import re import logging +try: + import indigo # noqa +except ImportError: + pass + my_logger = logging.getLogger("Plugin") @@ -20,8 +25,12 @@ def __init__(): # =============================== Chart Colors ================================+ -def chart_colors(values_dict): - """Inspects various color controls and sets them to default when the value is not valid hex (A-F, 0-9).""" +def chart_colors(values_dict: indigo.Dict): + """ + Inspects various color controls and sets them to default when the value is not valid hex (A-F, 0-9). + + :param indigo.Dict values_dict: + """ # TODO: check to see whether this dict is up to date. color_dict = { 'fontColorAnnotation': "FF FF FF", 'fontColor': "FF FF FF", 'backgroundColor': "00 00 00", @@ -37,7 +46,13 @@ def chart_colors(values_dict): # ============================= Chart Dimensions ============================== -def chart_dimensions(values_dict, error_msg_dict): +def chart_dimensions(values_dict: indigo.Dict, error_msg_dict: indigo.Dict): + """ + + :param indigo.Dict values_dict: + :param indigo.Dict error_msg_dict: + :return: + """ for dimension_prop in ( 'rectChartHeight', 'rectChartWidth', @@ -64,7 +79,13 @@ def chart_dimensions(values_dict, error_msg_dict): # ============================= Chart Resolution ============================== # Note that chart resolution includes a warning feature that will pass the value after the warning is cleared. -def chart_resolution(values_dict, error_msg_dict): +def chart_resolution(values_dict: indigo.Dict, error_msg_dict: indigo.Dict): + """ + + :param values_dict: + :param error_msg_dict: + :return: + """ try: # If value is null, a null string, or all whitespace. if not values_dict['chartResolution'] or \ @@ -86,8 +107,13 @@ def chart_resolution(values_dict, error_msg_dict): # ================================ Data Paths ================================== -def data_paths(values_dict, error_dict): - """Ensure the data path value is valid.""" +def data_paths(values_dict: indigo.Dict, error_dict: indigo.Dict): + """ + Ensure the data path value is valid. + + :param indigo.Dict values_dict: + :param indigo.Dict error_dict: + """ for path_prop in ('chartPath', 'dataPath'): try: if not values_dict[path_prop].endswith('/'): @@ -102,7 +128,13 @@ def data_paths(values_dict, error_dict): # ================================ Line Weight ================================= # Line weight is a hidden prop in PluginConfig.xml and may no longer be needed. fixme -def line_weight(values_dict, error_msg_dict): +def line_weight(values_dict: indigo.Dict, error_msg_dict: indigo.Dict): + """ + + :param indigo.Dict values_dict: + :param indigo.Dict error_msg_dict: + :return: + """ try: if float(values_dict['lineWeight']) <= 0: error_msg_dict['lineWeight'] = "The line weight value must be greater than zero." @@ -117,8 +149,13 @@ def line_weight(values_dict, error_msg_dict): # ============================================================================== # =============================== Custom Ticks ================================= -def custom_ticks(values_dict, error_dict): - """ Ensure all custom tick locations are numeric, within bounds, and of the same length. """ +def custom_ticks(values_dict: indigo.Dict, error_dict: indigo.Dict): + """ + Ensure all custom tick locations are numeric, within bounds, and of the same length. + + :param indigo.Dict values_dict: + :param indigo.Dict error_dict: + """ my_ticks = values_dict['customTicksY'].split(',') # Make a list from a string. my_tick_labels = values_dict['customTicksLabelY'].split(',') # Make a list from a string.