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
+}