diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fff3aa9..1dad804 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: source actions-ci/install.sh - name: Pip install pylint, black, & Sphinx run: | - pip install --force-reinstall pylint==1.9.2 black==19.10b0 Sphinx sphinx-rtd-theme + pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme - name: Library version run: git describe --dirty --always --tags - name: PyLint diff --git a/adafruit_display_notification/__init__.py b/adafruit_display_notification/__init__.py index e815908..f0088d2 100755 --- a/adafruit_display_notification/__init__.py +++ b/adafruit_display_notification/__init__.py @@ -41,29 +41,35 @@ TEXT_FONT = terminalio.FONT # pylint: disable=too-few-public-methods + class NotificationFree(displayio.Group): """Widget to show when no notifications are active.""" + def __init__(self, width, height, *, dark_mode=True): # pylint: disable=unused-argument super().__init__() if dark_mode: - text_color = 0xffffff + text_color = 0xFFFFFF else: text_color = 0x000000 # Create the text label - self.title = label.Label(TEXT_FONT, text="None!", y=height//2, color=text_color) + self.title = label.Label( + TEXT_FONT, text="None!", y=height // 2, color=text_color + ) self.append(self.title) + class PlainNotification(displayio.Group): """Plain text widget with a title and message.""" + def __init__(self, title, message, width, height, *, dark_mode=True): super().__init__() # Set text, font, and color if dark_mode: - text_color = 0xffffff + text_color = 0xFFFFFF else: text_color = 0x000000 @@ -76,11 +82,9 @@ class PlainNotification(displayio.Group): max_lines = height // 20 message = "\n".join(lines[:max_lines]) - self.message = label.Label(terminalio.FONT, - text=message, - color=text_color, - x=2, - y=height // 2 + 8) + self.message = label.Label( + terminalio.FONT, text=message, color=text_color, x=2, y=height // 2 + 8 + ) self.append(self.message) # cribbed from pyportal @@ -90,17 +94,17 @@ class PlainNotification(displayio.Group): :param str string: The text to be wrapped. :param int max_chars: The maximum number of characters on a line before wrapping. """ - string = string.replace('\n', '').replace('\r', '') # strip confusing newlines - words = string.split(' ') + string = string.replace("\n", "").replace("\r", "") # strip confusing newlines + words = string.split(" ") the_lines = [] the_line = "" for w in words: - if len(the_line+' '+w) <= max_chars: - the_line += ' '+w + if len(the_line + " " + w) <= max_chars: + the_line += " " + w else: the_lines.append(the_line) - the_line = ''+w - if the_line: # last line remaining + the_line = "" + w + if the_line: # last line remaining the_lines.append(the_line) # remove first space from first line: the_lines[0] = the_lines[0][1:] diff --git a/adafruit_display_notification/apple.py b/adafruit_display_notification/apple.py index bb2431e..bdee834 100755 --- a/adafruit_display_notification/apple.py +++ b/adafruit_display_notification/apple.py @@ -34,7 +34,12 @@ from . import PlainNotification __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Notification.git" -def create_notification_widget(notification, max_width, max_height, *, color_count=2**16): + +def create_notification_widget( + notification, max_width, max_height, *, color_count=2 ** 16 +): """Creates a notification widget for the given Apple notification.""" # pylint: disable=unused-argument - return PlainNotification(notification.title, notification.message, max_width, max_height) + return PlainNotification( + notification.title, notification.message, max_width, max_height + ) diff --git a/docs/conf.py b/docs/conf.py index 82b0ffa..55e97bd 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,8 @@ import os import sys -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) # -- General configuration ------------------------------------------------ @@ -10,42 +11,50 @@ sys.path.insert(0, os.path.abspath('..')) # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinx.ext.napoleon', - 'sphinx.ext.todo', + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.napoleon", + "sphinx.ext.todo", ] # TODO: Please Read! # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -autodoc_mock_imports = ["displayio", "adafruit_bitmap_font", "adafruit_display_text", "terminalio"] +autodoc_mock_imports = [ + "displayio", + "adafruit_bitmap_font", + "adafruit_display_text", + "terminalio", +] -intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)} +intersphinx_mapping = { + "python": ("https://docs.python.org/3.4", None), + "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), +} # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'Adafruit Display_Notification Library' -copyright = u'2019 Scott Shawcroft' -author = u'Scott Shawcroft' +project = "Adafruit Display_Notification Library" +copyright = "2019 Scott Shawcroft" +author = "Scott Shawcroft" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = u'1.0' +version = "1.0" # The full version, including alpha/beta/rc tags. -release = u'1.0' +release = "1.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -57,7 +66,7 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -69,7 +78,7 @@ default_role = "any" add_function_parentheses = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -84,59 +93,62 @@ napoleon_numpy_docstring = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +on_rtd = os.environ.get("READTHEDOCS", None) == "True" if not on_rtd: # only import and set the theme if we're building docs locally try: import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] + + html_theme = "sphinx_rtd_theme" + html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."] except: - html_theme = 'default' - html_theme_path = ['.'] + html_theme = "default" + html_theme_path = ["."] else: - html_theme_path = ['.'] + html_theme_path = ["."] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # -html_favicon = '_static/favicon.ico' +html_favicon = "_static/favicon.ico" # Output file base name for HTML help builder. -htmlhelp_basename = 'AdafruitDisplay_notificationLibrarydoc' +htmlhelp_basename = "AdafruitDisplay_notificationLibrarydoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'AdafruitDisplay_NotificationLibrary.tex', u'AdafruitDisplay_Notification Library Documentation', - author, 'manual'), + ( + master_doc, + "AdafruitDisplay_NotificationLibrary.tex", + "AdafruitDisplay_Notification Library Documentation", + author, + "manual", + ), ] # -- Options for manual page output --------------------------------------- @@ -144,8 +156,13 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'AdafruitDisplay_Notificationlibrary', u'Adafruit Display_Notification Library Documentation', - [author], 1) + ( + master_doc, + "AdafruitDisplay_Notificationlibrary", + "Adafruit Display_Notification Library Documentation", + [author], + 1, + ) ] # -- Options for Texinfo output ------------------------------------------- @@ -154,7 +171,13 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'AdafruitDisplay_NotificationLibrary', u'Adafruit Display_Notification Library Documentation', - author, 'AdafruitDisplay_NotificationLibrary', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "AdafruitDisplay_NotificationLibrary", + "Adafruit Display_Notification Library Documentation", + author, + "AdafruitDisplay_NotificationLibrary", + "One line description of project.", + "Miscellaneous", + ), ] diff --git a/examples/display_notification_eink_gizmo.py b/examples/display_notification_eink_gizmo.py index a00e89b..b1ea7e2 100644 --- a/examples/display_notification_eink_gizmo.py +++ b/examples/display_notification_eink_gizmo.py @@ -11,6 +11,7 @@ from adafruit_gizmo import eink_gizmo # This is a whitelist of apps to show notifications from. APPS = ["com.tinyspeck.chatlyio", "com.atebits.Tweetie2"] + def find_connection(): for connection in radio.connections: if AppleNotificationCenterService not in connection: @@ -20,6 +21,7 @@ def find_connection(): return connection, connection[AppleNotificationCenterService] return None, None + # Start advertising before messing with the display so that we can connect immediately. radio = adafruit_ble.BLERadio() a = SolicitServicesAdvertisement() @@ -51,14 +53,19 @@ while True: if not screen_updated: remaining_time = display.time_to_refresh new_notification = None - for notification in notification_service.wait_for_new_notifications(remaining_time): + for notification in notification_service.wait_for_new_notifications( + remaining_time + ): # Filter notifications we don't care about. if APPS and notification.app_id not in APPS: continue # For now, use _raw_date even though we should use a parsed version of the date. # pylint: disable=protected-access # Ignore notifications older than the currently shown one. - if latest_notification and notification._raw_date < latest_notification._raw_date: + if ( + latest_notification + and notification._raw_date < latest_notification._raw_date + ): continue new_notification = notification break @@ -67,9 +74,11 @@ while True: print(new_notification) latest_notification = new_notification screen_updated = False - display.show(apple.create_notification_widget(latest_notification, - display.width, - display.height)) + display.show( + apple.create_notification_widget( + latest_notification, display.width, display.height + ) + ) elif latest_notification and latest_notification.removed: # Stop showing the latest and show that there are no new notifications. latest_notification = None diff --git a/examples/display_notification_simpletest.py b/examples/display_notification_simpletest.py index 57e2a15..3b5e62c 100644 --- a/examples/display_notification_simpletest.py +++ b/examples/display_notification_simpletest.py @@ -7,19 +7,20 @@ notifications. import time import board import digitalio -import displayio - import adafruit_ble from adafruit_ble.advertising.standard import SolicitServicesAdvertisement +import displayio + from adafruit_ble_apple_notification_center import AppleNotificationCenterService from adafruit_display_notification import apple from adafruit_display_notification import NotificationFree from adafruit_display_ble_status.advertising import AdvertisingWidget -#from adafruit_circuitplayground import cp + +# from adafruit_circuitplayground import cp from adafruit_gizmo import tft_gizmo # This is a whitelist of apps to show notifications from. -#APPS = ["com.tinyspeck.chatlyio", "com.atebits.Tweetie2"] +# APPS = ["com.tinyspeck.chatlyio", "com.atebits.Tweetie2"] APPS = [] DELAY_AFTER_PRESS = 15 @@ -30,6 +31,7 @@ a.switch_to_input(pull=digitalio.Pull.DOWN) b = digitalio.DigitalInOut(board.BUTTON_B) b.switch_to_input(pull=digitalio.Pull.DOWN) + def find_connection(): for connection in radio.connections: if AppleNotificationCenterService not in connection: @@ -39,6 +41,7 @@ def find_connection(): return connection, connection[AppleNotificationCenterService] return None, None + # Start advertising before messing with the display so that we can connect immediately. radio = adafruit_ble.BLERadio() advertisement = SolicitServicesAdvertisement() @@ -88,9 +91,11 @@ while True: group[0] = NotificationFree(width, height) elif all_ids: now = time.monotonic() - if (current_notification and - current_notification.id in all_ids and - now - last_press < DELAY_AFTER_PRESS): + if ( + current_notification + and current_notification.id in all_ids + and now - last_press < DELAY_AFTER_PRESS + ): index = all_ids.index(current_notification.id) else: index = len(all_ids) - 1 @@ -106,7 +111,9 @@ while True: if not current_notification or current_notification.id != notification_id: current_notification = current_notifications[notification_id] print(current_notification._raw_date, current_notification) - group[0] = apple.create_notification_widget(current_notification, width, height) + group[0] = apple.create_notification_widget( + current_notification, width, height + ) active_connection = None notification_service = None diff --git a/setup.py b/setup.py index 5f9edcf..f0dd11a 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ https://github.com/pypa/sampleproject """ from setuptools import setup, find_packages + # To use a consistent encoding from codecs import open from os import path @@ -13,53 +14,41 @@ from os import path here = path.abspath(path.dirname(__file__)) # Get the long description from the README file -with open(path.join(here, 'README.rst'), encoding='utf-8') as f: +with open(path.join(here, "README.rst"), encoding="utf-8") as f: long_description = f.read() setup( - name='adafruit-circuitpython-display-notification', - + name="adafruit-circuitpython-display-notification", use_scm_version=True, - setup_requires=['setuptools_scm'], - - description='Displayio Widgets for displaying notifications', + setup_requires=["setuptools_scm"], + description="Displayio Widgets for displaying notifications", long_description=long_description, - long_description_content_type='text/x-rst', - + long_description_content_type="text/x-rst", # The project's main homepage. - url='https://github.com/adafruit/Adafruit_CircuitPython_Display_Notification', - + url="https://github.com/adafruit/Adafruit_CircuitPython_Display_Notification", # Author details - author='Adafruit Industries', - author_email='circuitpython@adafruit.com', - - install_requires=[ - 'Adafruit-Blinka', - 'adafruit-circuitpython-display-text' - ], - + author="Adafruit Industries", + author_email="circuitpython@adafruit.com", + install_requires=["Adafruit-Blinka", "adafruit-circuitpython-display-text"], # Choose your license - license='MIT', - + license="MIT", # See https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries', - 'Topic :: System :: Hardware', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries", + "Topic :: System :: Hardware", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", ], - # What does your project relate to? - keywords='adafruit blinka circuitpython micropython display_notification displayio ble ' - 'ancs', - + keywords="adafruit blinka circuitpython micropython display_notification displayio ble " + "ancs", # You can just specify the packages manually here if your project is # simple. Or you can use find_packages(). # TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER, # CHANGE `py_modules=['...']` TO `packages=['...']` - py_modules=['adafruit_display_notification'], + py_modules=["adafruit_display_notification"], )