Skip to content

Commit

Permalink
Changes to prepare for Indigo 2023.2 and code refinements.
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveL17 committed Dec 27, 2023
1 parent 35bd927 commit 4f59bfc
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 194 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -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
Expand Down
8 changes: 6 additions & 2 deletions _changelog.md
Original file line number Diff line number Diff line change
@@ -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'`.
Expand Down Expand Up @@ -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.)
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion _to_do_list.md
Original file line number Diff line number Diff line change
@@ -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).
Expand All @@ -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.
Expand Down
6 changes: 1 addition & 5 deletions matplotlib.indigoPlugin/Contents/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
<plist version="1.0">
<dict>
<key>PluginVersion</key>
<string>2022.1.7</string>
<string>2023.0.1</string>
<key>ServerApiVersion</key>
<string>3.0</string>
<key>IwsApiVersion</key>
<string>1.0.0</string>
<key>LoadPriority</key>
<integer>105</integer>
<key>CFBundleDisplayName</key>
<string>Matplotlib</string>
<key>CFBundleName</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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:
"""
Expand All @@ -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:
"""
Expand All @@ -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:
"""
Expand All @@ -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:
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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")]
"""
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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.")

Expand All @@ -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:
Expand All @@ -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.")

Expand All @@ -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:
"""
Expand All @@ -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:
"""
Expand All @@ -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
Expand Down Expand Up @@ -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): # <number>
value = node.n
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion matplotlib.indigoPlugin/Contents/Server Plugin/Devices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@
</Field>

<Field id="yAxisMin" type="textfield" defaultValue="None"
visibleBindingId="settingsGroup" visibleBindingValue="truye"
visibleBindingId="settingsGroup" visibleBindingValue="y"
tooltip="The minimum Y axis value.">
<Label>Min:</Label>
</Field>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
8 changes: 4 additions & 4 deletions matplotlib.indigoPlugin/Contents/Server Plugin/chart_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
)

Expand Down
16 changes: 8 additions & 8 deletions matplotlib.indigoPlugin/Contents/Server Plugin/chart_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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']}] "
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.")
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 4f59bfc

Please sign in to comment.