diff --git a/documentation/Plugins.md b/documentation/Plugins.md index b1a164e..fafabf3 100644 --- a/documentation/Plugins.md +++ b/documentation/Plugins.md @@ -15,18 +15,32 @@ All plugins are configured through the `paperpi.ini` files. For a single-user co + + [start: basic_clock]: # ### [basic_clock](../paperpi/plugins/basic_clock/README.md) ![basic_clock sample image](../paperpi/plugins/basic_clock/basic_clock.layout-L-sample.png) [end: basic_clock]: # + + [start: dec_binary_clock]: # + ### [dec_binary_clock](../paperpi/plugins/dec_binary_clock/README.md) + ![dec_binary_clock sample image](../paperpi/plugins/dec_binary_clock/dec_binary_clock.layout-L-sample.png) + + [end: dec_binary_clock]: # +[start: debugging]: # +### [debugging](../paperpi/plugins/debugging/README.md) +![debugging sample image](../paperpi/plugins/debugging/debugging.layout-L-sample.png) + +[end: debugging]: # + [start: default]: # ### [default](../paperpi/plugins/default/README.md) ![default sample image](../paperpi/plugins/default/default.layout-L-sample.png) @@ -93,12 +107,13 @@ All plugins are configured through the `paperpi.ini` files. For a single-user co [end: system_info]: # + + [start: word_clock]: # ### [word_clock](../paperpi/plugins/word_clock/README.md) RGB ![word_clock sample image](../paperpi/plugins/word_clock/word_clock.layout-L-sample.png) [end: word_clock]: # - [start: xkcd_comic]: # ### [xkcd_comic](../paperpi/plugins/xkcd_comic/README.md) ![xkcd_comic sample image](../paperpi/plugins/xkcd_comic/xkcd_comic.layout-L-sample.png) @@ -111,6 +126,19 @@ All plugins are configured through the `paperpi.ini` files. For a single-user co + + + + + + + + + + + + + diff --git a/install/install.sh b/install/install.sh index 50853f7..467629c 100755 --- a/install/install.sh +++ b/install/install.sh @@ -232,7 +232,7 @@ function copy_files { echo "Installing files to $INSTALLPATH" rsync -a --exclude-from=$EXCLUDE --include-from=$INCLUDE $LOCALPATH $rsyncPath # cp $SCRIPT_DIR/../Pipfile $INSTALLPATH - chown -R paperpi:paperpi $INSTALLPATH + # chown -R paperpi:paperpi $INSTALLPATH fi } diff --git a/paperpi/config/paperpi.ini b/paperpi/config/paperpi.ini index 85f0052..4010f08 100644 --- a/paperpi/config/paperpi.ini +++ b/paperpi/config/paperpi.ini @@ -20,7 +20,7 @@ mirror = False color = False # Disable screen wipe at shutdown (Default: True) # This setting will leave the last image on the screen at shutdown -no_wipe = False +no_wipe = True # plugin timeout - amount of time in seconds to wait for a hung plugin to complete execution plugin_timeout = 30 @@ -53,172 +53,14 @@ refresh_rate = 30 min_display_time = 60 max_priority = 2**15 -[xPlugin: Basic Clock] -layout = layout -plugin = basic_clock -refresh_rate = 30 -min_display_time = 50 -max_priority = 2 - -[xPlugin: decimal binary clock] -layout = layout -plugin = dec_bin_clock -refresh_rate = 30 +[xPlugin: Debugging 50] +layout = debugging_basic +plugin = debugging min_display_time = 50 -max_priority = 2 - -[xPlugin: default fallback plugin] -layout = layout -plugin = default -refresh_rate = 30 -min_display_time = 60 -max_priority = 2**15 - -[xPlugin: A Demo Plugin] -# this is a sample config users can use to help setup the plugin -# default layout -layout = layout -# the literal name of your module -plugin = demo_plugin -# recommended display time -min_display_time = 30 -# maximum priority in display loop max_priority = 1 -# your name -your_name = Slartybartfast -# your favorite color -your_color = chartreuse - -[xPlugin: Librespot] -layout = layout -plugin = librespot_client -refresh_rate = 10 -max_priority = 0 -min_display_time = 15 -# name of librespot player - use ("*"" to track any and all spotify players) -player_name = LibreSpot-Spotify -# time in seconds before plugin is removed from the display loop -idle_timeout = 10 -# port to search for librespot (if unset, defaults to 24879) -port = 24879 - -[xPlugin: LMS - Your Player Name] -layout = layout -plugin = lms_client -player_name = Your Player Name refresh_rate = 5 -min_display_time = 30 -max_priority = 0 -idle_timeout = 15 - -[xPlugin: Weather Adis Ababa] -layout = layout -plugin = met_no -refresh_rate = 300 -min_display_time = 50 -max_priority = 2 -location_name = Adis Ababa -lat = 9.000 -lon = 38.750 -# this is required by Met.no -- please use a real value -email = you@host.diamond -# Text color [RED, ORANGE, YELLOW, GREEN, BLUE, BLACK WHITE] or random -# bkground color is not supported in this plugin -# text_color = BLUE - -[xPlugin: Moon Phase] -# default layout -layout = layout -plugin = moon_phase -min_display_time = 30 -max_priority = 2 -refresh_rate = 1200 -# your email address for MET.no API access -- failure to specify may lead to a perma-ban -email = you@host.diamond -# Timezone locale name in Region/City format (see --run_plugin_func moon_phase.list_country_locales) -# Use a known city in your timezone; this is critical for calculating the moonrise time -location_name = Europe/Amsterdam -# lat/lon of your physical location (optional) (see --run_plugin_func moon_phase.get_coord) -lat = 52.3 -lon = 4.9 - -[xPlugin: New Yorker Comic] -layout = layout -plugin = newyorker -day_range = 5 # number of past days to choose from -refresh_rate = 120 -min_display_time = 60 -max_priority = 2 - -[xPlugin: Reddit Quotes] -layout = layout -plugin = reddit_quote -refresh_rate = 100 -min_display_time = 50 -max_priority = 2 -# maximum length of quote (in characters) including spaces, a la Twitter -max_length = 144 -# Text/background color [RED, ORANGE, YELLOW, GREEN, BLUE, BLACK WHITE] or random -# bkground color is not supported in this plugin -# text_color = RED -# bkground_color = random - -[xPlugin: Slideshow] -# default layout -layout = layout -plugin = slideshow -# time between choosing new image (seconds) -refresh_rate = 90 -# recommended display time (seconds) -min_display_time = 50 -# maximum priority in display loop -max_priority = 2 -# path to image directory -image_path = /pi/documents/images -# order to pull images in: random, sequential -order = random -# frame style to use (see README) -frame = black & silver: matted - -[xPlugin: System Info] -# show basic facts about the system including IP, Hostname, CPU usage, temperature and storage -# default layout -layout = layout -# the literal name of your module -plugin = system_info -# recommended display time -min_display_time = 45 -# maximum priority in display loop -max_priority = 2 -# storage units in decimal: [KB] KiloByte 10^3; [MB] MegaByte 10^6; [GB] GigaByte 10^12; [TB] TeraByte 10^12 -storage_unit = GB -# colors for RGB screens -text_color = BLUE -bkground_color = WHITE - -[xPlugin: Word Clock] -layout = layout -plugin = word_clock -refresh_rate = 125 -min_display_time = 255 -max_priority = 2 -# Text color [RED, ORANGE, YELLOW, GREEN, BLUE, BLACK WHITE] or random -# text_color = random -# bkground_color = random - -[xPlugin: XKCD Comic Plugin] -# default layout -layout = layout -plugin = xkcd_comic -refresh_rate = 1200 -min_display_time = 120 -# maximum x dimension of comic image -max_x = 800 -# maximum y dimension of comic image -max_y = 600 -# max attempts to find a suitable comic image -# 0 do not rsize small comics / 1 maximize small comics to max_x, max_y -resize = 0 -max_retries = 10 -max_priority = 2 +title = Debugging 50 +crash_rate = .5 +max_priority_rate = .1 +min_priority = 2 diff --git a/paperpi/my_constants.py b/paperpi/my_constants.py index 16b20e5..19edb1c 100644 --- a/paperpi/my_constants.py +++ b/paperpi/my_constants.py @@ -6,7 +6,7 @@ APP_NAME = 'PaperPi' CONTACT='aaron.ciuffo@gmail.com' DEVEL_NAME = f'com.txoof.{APP_NAME.lower()}' -VERSION='0.5.6.0 RGB' +VERSION='0.5.7.0 01Aug24' URL = 'https://github.com/ txoof/PaperPi' diff --git a/paperpi/paperpi.ipynb b/paperpi/paperpi.ipynb index 25548f8..57c78a7 100644 --- a/paperpi/paperpi.ipynb +++ b/paperpi/paperpi.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "119a4f48", "metadata": {}, "outputs": [], @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "abb7e915", "metadata": {}, "outputs": [], @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "17ae615b", "metadata": {}, "outputs": [], @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "66b0acda", "metadata": {}, "outputs": [], @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "a62bba7c", "metadata": {}, "outputs": [], @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "03ea4051", "metadata": {}, "outputs": [], @@ -99,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "e7b7f971", "metadata": {}, "outputs": [], @@ -173,7 +173,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "6e9f7da6", "metadata": {}, "outputs": [], @@ -234,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "200250e6", "metadata": {}, "outputs": [], @@ -302,7 +302,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "faf3f875", "metadata": {}, "outputs": [], @@ -338,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "0e0f8ae3", "metadata": {}, "outputs": [], @@ -440,7 +440,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "f112e225", "metadata": {}, "outputs": [], @@ -468,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "b31d4402", "metadata": {}, "outputs": [], @@ -526,7 +526,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "a06c6603", "metadata": { "lines_to_next_cell": 2 @@ -534,25 +534,30 @@ "outputs": [], "source": [ "def update_loop(plugins, screen, max_refresh=5):\n", + " \n", " def _update_plugins(force_update=False):\n", " '''private function for updating plugins'''\n", " s = ' '*5\n", " logger.info(f'>>__________UPDATING PLUGINS__________<<')\n", " logger.debug(f'{len(plugins)} total plugins available')\n", " my_priority_list = [2**16]\n", + " plugin_crashed = False\n", " for plugin in plugins:\n", " logger.info(f'{\"#\"*10}{plugin.name}{\"#\"*10}')\n", - " if force_update:\n", - " logger.info(f'{s}forcing update')\n", - " try:\n", + "\n", + " try:\n", + " if force_update:\n", + " logger.info(f'{s}forcing update')\n", " plugin.force_update()\n", - " except Exception as e:\n", - " logging.error(f'{Plugin} crashed while updating: {e}')\n", - " else:\n", - " try:\n", + " else:\n", " plugin.update()\n", - " except Exception as e:\n", - " logging.error(f'{Plugin} crashed while updating: {e}') \n", + " except Exception as e:\n", + " logging.error(f'{Plugin} crashed while updating: {e}')\n", + " plugin_crashed = True\n", + "\n", + " if plugin_crashed:\n", + " logging.warning('due to crash, resetting plugin priority and update status')\n", + " plugin.priority = 2**15\n", "\n", " logger.info(f'{s}PRIORITY: {plugin.priority} of max {plugin.max_priority}')\n", " my_priority_list.append(plugin.priority)\n", @@ -662,7 +667,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "id": "7ee8f888", "metadata": {}, "outputs": [], @@ -859,13 +864,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "d92ae6c1-285f-43ec-8eba-145ad62599b7", + "cell_type": "raw", + "id": "5603645a-7013-48b8-ac47-124c506b5ede", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "261d3b8c-cba4-48ce-b0fd-2d43c921f369", "metadata": {}, - "outputs": [], "source": [] - } ], "metadata": { diff --git a/paperpi/paperpi.py b/paperpi/paperpi.py index 749cc36..1a61ced 100755 --- a/paperpi/paperpi.py +++ b/paperpi/paperpi.py @@ -444,25 +444,30 @@ def ret_obj(obj=None, status=0, message=None): # + def update_loop(plugins, screen, max_refresh=5): + def _update_plugins(force_update=False): '''private function for updating plugins''' s = ' '*5 logger.info(f'>>__________UPDATING PLUGINS__________<<') logger.debug(f'{len(plugins)} total plugins available') my_priority_list = [2**16] + plugin_crashed = False for plugin in plugins: logger.info(f'{"#"*10}{plugin.name}{"#"*10}') - if force_update: - logger.info(f'{s}forcing update') - try: + + try: + if force_update: + logger.info(f'{s}forcing update') plugin.force_update() - except Exception as e: - logging.error(f'{Plugin} crashed while updating: {e}') - else: - try: + else: plugin.update() - except Exception as e: - logging.error(f'{Plugin} crashed while updating: {e}') + except Exception as e: + logging.error(f'{Plugin} crashed while updating: {e}') + plugin_crashed = True + + if plugin_crashed: + logging.warning('due to crash, resetting plugin priority and update status') + plugin.priority = 2**15 logger.info(f'{s}PRIORITY: {plugin.priority} of max {plugin.max_priority}') my_priority_list.append(plugin.priority) @@ -745,3 +750,9 @@ def main(): exit_code = main() sys.exit(exit_code) + +# + active="" +# +# - + +# diff --git a/paperpi/plugins/debugging/README.md b/paperpi/plugins/debugging/README.md new file mode 100644 index 0000000..f12d969 --- /dev/null +++ b/paperpi/plugins/debugging/README.md @@ -0,0 +1,63 @@ +# debugging + +![sample image for plugin debugging](./debugging.layout-L-sample.png) +```ini + +PLUGIN: debugging v:0.1.0 + + +FUNCTION: update_function +update function for debugging plugin provides title, time, crash rate + + This plugin shows minimal data and is designed to throw exceptions to test other functionality. + The plugin will deliberately and randomly throw exceptions at the rate specified in the configuration. + When an exception is not thrown, the plugin will randomly change its priority to the max set in the + configuration. Set the rate at which the plugin should jump to the higher priority status in the configuration. + + + Args: + self(`namespace`) + title(`str`): title of plugin to display + crash_rate(`float`): value between 0 and 1 indicating probability of throwing + exception on execution + +___________________________________________________________________________ + + + +SAMPLE CONFIGURATION FOR paperpi.plugins.debugging.debugging + +[Plugin: Debugging 50] +layout = debugging_basic +plugin = debugging +min_display_time = 50 +max_priority = 1 +refresh_rate = 5 +title = Debugging 50 +crash_rate = .5 +max_priority_rate = .1 +min_priority = 2 + + +LAYOUTS AVAILABLE: + debugging_basic + layout + + +DATA KEYS AVAILABLE FOR USE IN LAYOUTS PROVIDED BY paperpi.plugins.debugging.debugging: + title + crash_rate +``` + +## Provided Layouts + +layout: **debugging_basic** + +![sample image for plugin debugging_basic](./debugging.debugging_basic-L-sample.png) + + +layout: **layout** + +![sample image for plugin layout](./debugging.layout-L-sample.png) + + diff --git a/paperpi/plugins/debugging/__init__.py b/paperpi/plugins/debugging/__init__.py new file mode 100644 index 0000000..3d2e4e1 --- /dev/null +++ b/paperpi/plugins/debugging/__init__.py @@ -0,0 +1 @@ +from .debugging import update_function diff --git a/paperpi/plugins/debugging/constants.ipynb b/paperpi/plugins/debugging/constants.ipynb new file mode 100644 index 0000000..9fe5c25 --- /dev/null +++ b/paperpi/plugins/debugging/constants.ipynb @@ -0,0 +1,95 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2a309182", + "metadata": {}, + "outputs": [], + "source": [ + "version = '0.1.0'\n", + "name = 'debugging'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6bdd488", + "metadata": {}, + "outputs": [], + "source": [ + "default_title = 'Debug'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aaa457d3", + "metadata": {}, + "outputs": [], + "source": [ + "# do not include a sample INI configuration\n", + "include_ini = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8f2122d", + "metadata": {}, + "outputs": [], + "source": [ + "sample_config='''\n", + "[Plugin: Debugging 50]\n", + "layout = debugging_basic\n", + "plugin = debugging\n", + "min_display_time = 50\n", + "max_priority = 1\n", + "refresh_rate = 5\n", + "title = Debugging 50\n", + "crash_rate = .5\n", + "max_priority_rate = .1\n", + "min_priority = 2\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6fc7f73-0803-45e0-a98c-721a702febdc", + "metadata": {}, + "outputs": [], + "source": [ + "data = {\n", + " 'title': 'title of plugin',\n", + " 'crash_rate': 'float between 0 and 1 indicating how frequently plugin should crash'\n", + "}" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "venv_e-Paper-6143c5ac7f", + "language": "python", + "name": "venv_e-paper-6143c5ac7f" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/paperpi/plugins/debugging/constants.py b/paperpi/plugins/debugging/constants.py new file mode 100644 index 0000000..1f6d340 --- /dev/null +++ b/paperpi/plugins/debugging/constants.py @@ -0,0 +1,25 @@ +version = '0.1.0' +name = 'debugging' + +default_title = 'Debug' + +# do not include a sample INI configuration +include_ini = False + +sample_config=''' +[Plugin: Debugging 50] +layout = debugging_basic +plugin = debugging +min_display_time = 50 +max_priority = 1 +refresh_rate = 5 +title = Debugging 50 +crash_rate = .5 +max_priority_rate = .1 +min_priority = 2 +''' + +data = { + 'title': 'title of plugin', + 'crash_rate': 'float between 0 and 1 indicating how frequently plugin should crash' +} diff --git a/paperpi/plugins/debugging/debugging.debugging_basic-L-sample.png b/paperpi/plugins/debugging/debugging.debugging_basic-L-sample.png new file mode 100644 index 0000000..d3fcefb Binary files /dev/null and b/paperpi/plugins/debugging/debugging.debugging_basic-L-sample.png differ diff --git a/paperpi/plugins/debugging/debugging.ipynb b/paperpi/plugins/debugging/debugging.ipynb new file mode 100644 index 0000000..e1e2f1b --- /dev/null +++ b/paperpi/plugins/debugging/debugging.ipynb @@ -0,0 +1,235 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "from datetime import datetime\n", + "from time import time\n", + "import random\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [ + "# two different import modes for development or distribution\n", + "try:\n", + " # import from other modules above this level\n", + " from . import layout\n", + " from . import constants\n", + "except ImportError:\n", + " import constants\n", + " # development in jupyter notebook\n", + " import layout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "# fugly hack for making the library module available to the plugins\n", + "sys.path.append(layout.dir_path+'/../..')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logger = logging.getLogger(__name__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def remove_non_alphanumeric(s):\n", + " # Using list comprehension to filter out non-alphanumeric characters\n", + " filtered_string = ''.join([char for char in s if char.isalnum()])\n", + " return filtered_string" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [ + "def update_function(self, title=None, crash_rate=None, *args, **kwargs):\n", + " '''update function for debugging plugin provides title, time, crash rate\n", + " \n", + " This plugin shows minimal data and is designed to throw exceptions to test other functionality. \n", + " The plugin will deliberately and randomly throw exceptions at the rate specified in the configuration. \n", + " When an exception is not thrown, the plugin will randomly change its priority to the max set in the \n", + " configuration. Set the rate at which the plugin should jump to the higher priority status in the configuration.\n", + " \n", + " \n", + " Args:\n", + " self(`namespace`)\n", + " title(`str`): title of plugin to display\n", + " crash_rate(`float`): value between 0 and 1 indicating probability of throwing \n", + " exception on execution\n", + " %U'''\n", + "\n", + " crash = False\n", + " priority = self.max_priority\n", + " is_updated = False\n", + " \n", + " if not title:\n", + " title = self.config.get('title', constants.default_title)\n", + "\n", + " # sentinal file to indicate that the plugin has been setup\n", + " filename = ''.join([char for char in title if char.isalnum()])\n", + " first_run_file = Path(str(self.cache))/filename\n", + " logging.info(f'first-run sentinal file: {first_run_file}') \n", + " \n", + " if not crash_rate:\n", + " crash_rate = self.config.get('crash_rate', 0)\n", + "\n", + " max_priority_rate = self.config.get('max_priority_rate', 0)\n", + " \n", + " \n", + " random.seed(time())\n", + " rand_val = random.random()\n", + " rand_priority = random.random()\n", + " # if this is the first run, do NOT crash; paperpi will exclude any\n", + " # plugin that crashes during setup\n", + " if not first_run_file.exists():\n", + " logging.info(f'This is the first run of this plugin; creating sential file: {first_run_file}')\n", + " rand_val = 2\n", + " logging.info('plugin will not crash on first run')\n", + " first_run_file.touch()\n", + " else:\n", + " pass\n", + "\n", + " logging.info(f'rand_priority: {rand_priority}, max_priority_rate: {max_priority_rate}')\n", + " if rand_priority <= max_priority_rate:\n", + " priority = self.max_priority\n", + " else:\n", + " priority = self.config.get('min_priority', 2)\n", + "\n", + " logging.info(f'priority set to: {priority}')\n", + " \n", + " \n", + " data = {\n", + " 'title': f'{title}',\n", + " 'crash_rate': f'Crash Rate: {crash_rate*100:.0f}%',\n", + " 'digit_time': datetime.now().strftime(\"%H:%M:%S\"),\n", + " 'priority': f'priority: {priority}',\n", + " }\n", + "\n", + " logging.info(data)\n", + "\n", + " \n", + " if rand_val <= crash_rate:\n", + " logging.info('random crash occurred: will throw exception')\n", + " crash = True\n", + " else:\n", + " logging.info('random crash did not occur: will not throw exception')\n", + " crash = False\n", + "\n", + " if crash:\n", + " raise Exception(f'random crash occured: random value {rand_val:.2f} <= {crash_rate:.2f}')\n", + " else:\n", + " is_updated = True\n", + " \n", + " is_updated = True\n", + " return is_updated, data, priority" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# # this code snip simulates running from within the display loop use this and the following\n", + "# # cell to test the output\n", + "# import logging\n", + "# logging.root.setLevel('DEBUG')\n", + "# from library.CacheFiles import CacheFiles\n", + "# from library.Plugin import Plugin\n", + "# from IPython.display import display\n", + "# test_plugin = Plugin(resolution=(800, 600), screen_mode='L', max_priority=0)\n", + "# test_plugin.config = {\n", + "# 'text_color': 'random',\n", + "# 'bkground_color': 'White'\n", + "# }\n", + "# test_plugin.refresh_rate = 1\n", + "# l = layout.layout\n", + "# test_plugin.config = {\n", + "# 'title': 'Dummy 00',\n", + "# 'crash_rate': .33,\n", + "# 'max_priority_rate': .5,\n", + "# 'min_priority': 2\n", + "# }\n", + "# test_plugin.layout = l\n", + "# test_plugin.cache = CacheFiles()\n", + "# test_plugin.update_function = update_function\n", + "# # test_plugin.update()\n", + "# # test_plugin.image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# test_plugin.update()\n", + "# test_plugin.image" + ] + } + ], + "metadata": { + "jupytext": { + "formats": "ipynb,py:light" + }, + "kernelspec": { + "display_name": "venv_paperpi-9876705927", + "language": "python", + "name": "venv_paperpi-9876705927" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/paperpi/plugins/debugging/debugging.layout-L-sample.png b/paperpi/plugins/debugging/debugging.layout-L-sample.png new file mode 100644 index 0000000..93b2287 Binary files /dev/null and b/paperpi/plugins/debugging/debugging.layout-L-sample.png differ diff --git a/paperpi/plugins/debugging/debugging.py b/paperpi/plugins/debugging/debugging.py new file mode 100644 index 0000000..c2b8114 --- /dev/null +++ b/paperpi/plugins/debugging/debugging.py @@ -0,0 +1,160 @@ +# --- +# jupyter: +# jupytext: +# formats: ipynb,py:light +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.16.1 +# kernelspec: +# display_name: venv_paperpi-9876705927 +# language: python +# name: venv_paperpi-9876705927 +# --- + +# %load_ext autoreload +# %autoreload 2 + +import logging +from datetime import datetime +from time import time +import random +from pathlib import Path + +# two different import modes for development or distribution +try: + # import from other modules above this level + from . import layout + from . import constants +except ImportError: + import constants + # development in jupyter notebook + import layout + + +import sys +# fugly hack for making the library module available to the plugins +sys.path.append(layout.dir_path+'/../..') + +logger = logging.getLogger(__name__) + + +def remove_non_alphanumeric(s): + # Using list comprehension to filter out non-alphanumeric characters + filtered_string = ''.join([char for char in s if char.isalnum()]) + return filtered_string + + +def update_function(self, title=None, crash_rate=None, *args, **kwargs): + '''update function for debugging plugin provides title, time, crash rate + + This plugin shows minimal data and is designed to throw exceptions to test other functionality. + The plugin will deliberately and randomly throw exceptions at the rate specified in the configuration. + When an exception is not thrown, the plugin will randomly change its priority to the max set in the + configuration. Set the rate at which the plugin should jump to the higher priority status in the configuration. + + + Args: + self(`namespace`) + title(`str`): title of plugin to display + crash_rate(`float`): value between 0 and 1 indicating probability of throwing + exception on execution + %U''' + + crash = False + priority = self.max_priority + is_updated = False + + if not title: + title = self.config.get('title', constants.default_title) + + # sentinal file to indicate that the plugin has been setup + filename = ''.join([char for char in title if char.isalnum()]) + first_run_file = Path(str(self.cache))/filename + logging.info(f'first-run sentinal file: {first_run_file}') + + if not crash_rate: + crash_rate = self.config.get('crash_rate', 0) + + max_priority_rate = self.config.get('max_priority_rate', 0) + + + random.seed(time()) + rand_val = random.random() + rand_priority = random.random() + # if this is the first run, do NOT crash; paperpi will exclude any + # plugin that crashes during setup + if not first_run_file.exists(): + logging.info(f'This is the first run of this plugin; creating sential file: {first_run_file}') + rand_val = 2 + logging.info('plugin will not crash on first run') + first_run_file.touch() + else: + pass + + logging.info(f'rand_priority: {rand_priority}, max_priority_rate: {max_priority_rate}') + if rand_priority <= max_priority_rate: + priority = self.max_priority + else: + priority = self.config.get('min_priority', 2) + + logging.info(f'priority set to: {priority}') + + + data = { + 'title': f'{title}', + 'crash_rate': f'Crash Rate: {crash_rate*100:.0f}%', + 'digit_time': datetime.now().strftime("%H:%M:%S"), + 'priority': f'priority: {priority}', + } + + logging.info(data) + + + if rand_val <= crash_rate: + logging.info('random crash occurred: will throw exception') + crash = True + else: + logging.info('random crash did not occur: will not throw exception') + crash = False + + if crash: + raise Exception(f'random crash occured: random value {rand_val:.2f} <= {crash_rate:.2f}') + else: + is_updated = True + + is_updated = True + return is_updated, data, priority + + +# + +# # this code snip simulates running from within the display loop use this and the following +# # cell to test the output +# import logging +# logging.root.setLevel('DEBUG') +# from library.CacheFiles import CacheFiles +# from library.Plugin import Plugin +# from IPython.display import display +# test_plugin = Plugin(resolution=(800, 600), screen_mode='L', max_priority=0) +# test_plugin.config = { +# 'text_color': 'random', +# 'bkground_color': 'White' +# } +# test_plugin.refresh_rate = 1 +# l = layout.layout +# test_plugin.config = { +# 'title': 'Dummy 00', +# 'crash_rate': .33, +# 'max_priority_rate': .5, +# 'min_priority': 2 +# } +# test_plugin.layout = l +# test_plugin.cache = CacheFiles() +# test_plugin.update_function = update_function +# # test_plugin.update() +# # test_plugin.image + +# + +# test_plugin.update() +# test_plugin.image diff --git a/paperpi/plugins/debugging/layout.ipynb b/paperpi/plugins/debugging/layout.ipynb new file mode 100644 index 0000000..04fd9c0 --- /dev/null +++ b/paperpi/plugins/debugging/layout.ipynb @@ -0,0 +1,115 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "f05e5d2d", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [ + "import os\n", + "dir_path = os.path.dirname(os.path.realpath(__file__))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c1bb6c2", + "metadata": {}, + "outputs": [], + "source": [ + "debugging_basic = {\n", + " 'title': {\n", + " 'type': 'TextBlock',\n", + " 'image': None,\n", + " 'max_lines': 2,\n", + " 'width': 1,\n", + " 'height': 1/3,\n", + " 'abs_coordinates': (0, 0),\n", + " 'rand': False,\n", + " 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf',\n", + " 'fill': 'BLACK',\n", + " 'bkground': 'WHITE'\n", + " },\n", + " 'crash_rate': {\n", + " 'type': 'TextBlock',\n", + " 'image': None,\n", + " 'max_lines': 2,\n", + " 'width': 1/2,\n", + " 'height': 1/3,\n", + " 'abs_coordinates': (0, None),\n", + " 'relative': ['crash_rate', 'title'],\n", + " 'rand': False,\n", + " 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf',\n", + " 'fill': 'BLACK',\n", + " 'bkground': 'WHITE'\n", + " },\n", + " 'priority': {\n", + " 'type': 'TextBlock',\n", + " 'image': None,\n", + " 'max_lines': 2,\n", + " 'width': 1/2,\n", + " 'height': 1/3,\n", + " 'abs_coordinates': (None, None),\n", + " 'relative': ['crash_rate', 'title'],\n", + " 'rand': False,\n", + " 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf',\n", + " 'fill': 'BLACK',\n", + " 'bkground': 'WHITE'\n", + " }, \n", + " 'digit_time': {\n", + " 'type': 'TextBlock',\n", + " 'image': None,\n", + " 'max_lines': 2,\n", + " 'width': 1,\n", + " 'height': 1/3,\n", + " 'abs_coordinates': (0, None),\n", + " 'relative': ['digit_time', 'crash_rate'],\n", + " 'rand': False,\n", + " 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf',\n", + " 'fill': 'BLACK',\n", + " 'bkground': 'WHITE'\n", + " },\n", + " \n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a604fbf", + "metadata": {}, + "outputs": [], + "source": [ + "layout = debugging_basic" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "venv_e-Paper-6143c5ac7f", + "language": "python", + "name": "venv_e-paper-6143c5ac7f" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/paperpi/plugins/debugging/layout.py b/paperpi/plugins/debugging/layout.py new file mode 100644 index 0000000..6171b57 --- /dev/null +++ b/paperpi/plugins/debugging/layout.py @@ -0,0 +1,62 @@ +import os +dir_path = os.path.dirname(os.path.realpath(__file__)) + + +# + +debugging_basic = { + 'title': { + 'type': 'TextBlock', + 'image': None, + 'max_lines': 2, + 'width': 1, + 'height': 1/3, + 'abs_coordinates': (0, 0), + 'rand': False, + 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf', + 'fill': 'BLACK', + 'bkground': 'WHITE' + }, + 'crash_rate': { + 'type': 'TextBlock', + 'image': None, + 'max_lines': 2, + 'width': 1/2, + 'height': 1/3, + 'abs_coordinates': (0, None), + 'relative': ['crash_rate', 'title'], + 'rand': False, + 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf', + 'fill': 'BLACK', + 'bkground': 'WHITE' + }, + 'priority': { + 'type': 'TextBlock', + 'image': None, + 'max_lines': 2, + 'width': 1/2, + 'height': 1/3, + 'abs_coordinates': (None, None), + 'relative': ['crash_rate', 'title'], + 'rand': False, + 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf', + 'fill': 'BLACK', + 'bkground': 'WHITE' + }, + 'digit_time': { + 'type': 'TextBlock', + 'image': None, + 'max_lines': 2, + 'width': 1, + 'height': 1/3, + 'abs_coordinates': (0, None), + 'relative': ['digit_time', 'crash_rate'], + 'rand': False, + 'font': dir_path+'/../../fonts/Kanit/Kanit-Medium.ttf', + 'fill': 'BLACK', + 'bkground': 'WHITE' + }, + +} +# - + +layout = debugging_basic diff --git a/paperpi/plugins/debugging/requirements-debugging.txt b/paperpi/plugins/debugging/requirements-debugging.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/paperpi/plugins/debugging/requirements-debugging.txt @@ -0,0 +1 @@ + diff --git a/paperpi/plugins/debugging/sample.ipynb b/paperpi/plugins/debugging/sample.ipynb new file mode 100644 index 0000000..390f173 --- /dev/null +++ b/paperpi/plugins/debugging/sample.ipynb @@ -0,0 +1,47 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "894bbc95", + "metadata": {}, + "outputs": [], + "source": [ + "config = {\n", + " 'layout': 'layout',\n", + " 'min_display_time': 30,\n", + " 'refresh_rate': 5,\n", + " 'max_priority': 1,\n", + " 'title': 'Debugging 50',\n", + " 'crash_rate': .5,\n", + " 'max_priority_rate': .1\n", + "}" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "notebook_metadata_filter": "-all" + }, + "kernelspec": { + "display_name": "venv_e-Paper-6143c5ac7f", + "language": "python", + "name": "venv_e-paper-6143c5ac7f" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/paperpi/plugins/debugging/sample.py b/paperpi/plugins/debugging/sample.py new file mode 100644 index 0000000..e56e049 --- /dev/null +++ b/paperpi/plugins/debugging/sample.py @@ -0,0 +1,9 @@ +config = { + 'layout': 'layout', + 'min_display_time': 30, + 'refresh_rate': 5, + 'max_priority': 1, + 'title': 'Debugging 50', + 'crash_rate': .5, + 'max_priority_rate': .1 +}