Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Armachat coding problem
#1
Hello guys!
I built Armachat from the link below
https://github.com/bobricius/Armachat-circuitpython
https://hackaday.io/project/183657-armac...-messenger
It works on raspberry pico, ST7789V display, LoRa module and 30 buttons.
After assebly and run programm i get this message
Error:
Traceback (most recent call last) File "code.py", line 43, in <module> File "<string>", line 15, in <module> File "lib/adafruit_display_text/label.py", line 30 in <module>
First of all what is "File "<string>""? Where i can find it?

Second, if I understand correctly, problem in label.py file, but it's a standard library...

code.py

import time
import board
import busio
import terminalio
import displayio
import os
import microcontroller

from config import *
from picomputer import *

import digitalio
hidden_ID = ['.', '_', 'TRASH', 'boot_out.txt', 'main.py', 'code.py', 'menu.py', 'main.txt', 'code.txt', 'boot.py']         # List of file name elements and names we do not want to see
#pnt20"1234567890123456789")
print("/~~~~Doomsday~~~~~\\")
print("| Operating System|")
print("\__Select program_/")

def file_filter(data):
    for y in hidden_ID:
        filtered_data = [x for x in data if not x.startswith(y)]
        data = filtered_data
    filtered_data = [x for x in data if x[-3:] == '.py' or x[-4:] == '.txt' ]
    return sorted(filtered_data)

menu_options = file_filter(os.listdir())
max_length = len(menu_options)

for i in range(0, max_length, 1):
        print( "[{}] {}".format(i, menu_options[i]))
#pnt20"1234567890123456789")
print("[Press number 0-9]",end="")
while True:

    keys=getKey(1)
    if keys:
        try:
            selected =int(keys[0])
        except Exception:
            selected = 0

        if selected<max_length:
            exec(open(menu_options[selected]).read())
            print("Program finished ... rebooting ....")
            microcontroller.reset()
label.py

# SPDX-FileCopyrightText: 2019 Scott Shawcroft for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""
`adafruit_display_text.label`
====================================================
Displays text labels using CircuitPython's displayio.
* Author(s): Scott Shawcroft
Implementation Notes
--------------------
**Hardware:**
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
  https://circuitpython.org/downloads
"""

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"


from displayio import Bitmap, Palette, TileGrid
from adafruit_display_text import LabelBase

try:
    from typing import Optional, Tuple
    from fontio import FontProtocol
except ImportError:
    pass


class Label(LabelBase):
    # pylint: disable=too-many-instance-attributes

    """A label displaying a string of text. The origin point set by ``x`` and ``y``
    properties will be the left edge of the bounding box, and in the center of a M
    glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
    it will try to have it be center-left as close as possible.
    :param font: A font class that has ``get_bounding_box`` and ``get_glyph``.
      Must include a capital M for measuring character size.
    :type font: ~FontProtocol
    :param str text: Text to display
    :param int|Tuple(int, int, int) color: Color of all text in HEX or RGB
    :param int|Tuple(int, int, int)|None background_color: Color of the background, use `None`
     for transparent
    :param float line_spacing: Line spacing of text to display
    :param bool background_tight: Set `True` only if you want background box to tightly
     surround text. When set to 'True' Padding parameters will be ignored.
    :param int padding_top: Additional pixels added to background bounding box at top.
     This parameter could be negative indicating additional pixels subtracted from the
     background bounding box.
    :param int padding_bottom: Additional pixels added to background bounding box at bottom.
     This parameter could be negative indicating additional pixels subtracted from the
     background bounding box.
    :param int padding_left: Additional pixels added to background bounding box at left.
     This parameter could be negative indicating additional pixels subtracted from the
     background bounding box.
    :param int padding_right: Additional pixels added to background bounding box at right.
     This parameter could be negative indicating additional pixels subtracted from the
     background bounding box.
    :param Tuple(float, float) anchor_point: Point that anchored_position moves relative to.
     Tuple with decimal percentage of width and height.
     (E.g. (0,0) is top left, (1.0, 0.5): is middle right.)
    :param Tuple(int, int) anchored_position: Position relative to the anchor_point. Tuple
     containing x,y pixel coordinates.
    :param int scale: Integer value of the pixel scaling
    :param bool base_alignment: when True allows to align text label to the baseline.
     This is helpful when two or more labels need to be aligned to the same baseline
    :param Tuple(int, str) tab_replacement: tuple with tab character replace information. When
     (4, " ") will indicate a tab replacement of 4 spaces, defaults to 4 spaces by
     tab character
    :param str label_direction: string defining the label text orientation. There are 5
     configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left
     ``TTB``-Top-To-Bottom ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``"""

    def __init__(self, font: FontProtocol, **kwargs) -> None:
        self._background_palette = Palette(1)
        self._added_background_tilegrid = False

        super().__init__(font, **kwargs)

        text = self._replace_tabs(self._text)

        self._width = len(text)
        self._height = self._font.get_bounding_box()[1]

        # Create the two-color text palette
        self._palette[0] = 0
        self._palette.make_transparent(0)

        if text is not None:
            self._reset_text(str(text))

    def _create_background_box(self, lines: int, y_offset: int) -> TileGrid:
        """Private Class function to create a background_box
        :param lines: int number of lines
        :param y_offset: int y pixel bottom coordinate for the background_box"""

        left = self._bounding_box[0]
        if self._background_tight:  # draw a tight bounding box
            box_width = self._bounding_box[2]
            box_height = self._bounding_box[3]
            x_box_offset = 0
            y_box_offset = self._bounding_box[1]

        else:  # draw a "loose" bounding box to include any ascenders/descenders.
            ascent, descent = self._ascent, self._descent

            if self._label_direction in ("UPR", "DWR", "TTB"):
                box_height = (
                    self._bounding_box[3] + self._padding_top + self._padding_bottom
                )
                x_box_offset = -self._padding_bottom
                box_width = (
                    (ascent + descent)
                    + int((lines - 1) * self._width * self._line_spacing)
                    + self._padding_left
                    + self._padding_right
                )
            else:
                box_width = (
                    self._bounding_box[2] + self._padding_left + self._padding_right
                )
                x_box_offset = -self._padding_left
                box_height = (
                    (ascent + descent)
                    + int((lines - 1) * self._height * self._line_spacing)
                    + self._padding_top
                    + self._padding_bottom
                )

            if self._base_alignment:
                y_box_offset = -ascent - self._padding_top
            else:
                y_box_offset = -ascent + y_offset - self._padding_top

        box_width = max(0, box_width)  # remove any negative values
        box_height = max(0, box_height)  # remove any negative values

        if self._label_direction == "UPR":
            movx = left + x_box_offset
            movy = -box_height - x_box_offset
        elif self._label_direction == "DWR":
            movx = left + x_box_offset
            movy = x_box_offset
        elif self._label_direction == "TTB":
            movx = left + x_box_offset
            movy = x_box_offset
        else:
            movx = left + x_box_offset
            movy = y_box_offset

        background_bitmap = Bitmap(box_width, box_height, 1)
        tile_grid = TileGrid(
            background_bitmap,
            pixel_shader=self._background_palette,
            x=movx,
            y=movy,
        )

        return tile_grid

    def _set_background_color(self, new_color: Optional[int]) -> None:
        """Private class function that allows updating the font box background color
        :param int new_color: Color as an RGB hex number, setting to None makes it transparent
        """

        if new_color is None:
            self._background_palette.make_transparent(0)
            if self._added_background_tilegrid:
                self._local_group.pop(0)
                self._added_background_tilegrid = False
        else:
            self._background_palette.make_opaque(0)
            self._background_palette[0] = new_color
        self._background_color = new_color

        lines = self._text.rstrip("\n").count("\n") + 1
        y_offset = self._ascent // 2

        if self._bounding_box is None:
            # Still in initialization
            return

        if not self._added_background_tilegrid:  # no bitmap is in the self Group
            # add bitmap if text is present and bitmap sizes > 0 pixels
            if (
                (len(self._text) > 0)
                and (
                    self._bounding_box[2] + self._padding_left + self._padding_right > 0
                )
                and (
                    self._bounding_box[3] + self._padding_top + self._padding_bottom > 0
                )
            ):
                self._local_group.insert(
                    0, self._create_background_box(lines, y_offset)
                )
                self._added_background_tilegrid = True

        else:  # a bitmap is present in the self Group
            # update bitmap if text is present and bitmap sizes > 0 pixels
            if (
                (len(self._text) > 0)
                and (
                    self._bounding_box[2] + self._padding_left + self._padding_right > 0
                )
                and (
                    self._bounding_box[3] + self._padding_top + self._padding_bottom > 0
                )
            ):
                self._local_group[0] = self._create_background_box(
                    lines, self._y_offset
                )
            else:  # delete the existing bitmap
                self._local_group.pop(0)
                self._added_background_tilegrid = False

    def _update_text(self, new_text: str) -> None:
        # pylint: disable=too-many-branches,too-many-statements

        x = 0
        y = 0
        if self._added_background_tilegrid:
            i = 1
        else:
            i = 0
        tilegrid_count = i
        if self._base_alignment:
            self._y_offset = 0
        else:
            self._y_offset = self._ascent // 2

        if self._label_direction == "RTL":
            left = top = bottom = 0
            right = None
        elif self._label_direction == "LTR":
            right = top = bottom = 0
            left = None
        else:
            top = right = left = 0
            bottom = 0

        for character in new_text:
            if character == "\n":
                y += int(self._height * self._line_spacing)
                x = 0
                continue
            glyph = self._font.get_glyph(ord(character))
            if not glyph:
                continue

            position_x, position_y = 0, 0

            if self._label_direction in ("LTR", "RTL"):
                bottom = max(bottom, y - glyph.dy + self._y_offset)
                if y == 0:  # first line, find the Ascender height
                    top = min(top, -glyph.height - glyph.dy + self._y_offset)
                position_y = y - glyph.height - glyph.dy + self._y_offset

                if self._label_direction == "LTR":
                    right = max(right, x + glyph.shift_x, x + glyph.width + glyph.dx)
                    if x == 0:
                        if left is None:
                            left = 0
                        else:
                            left = min(left, glyph.dx)
                    position_x = x + glyph.dx
                else:
                    left = max(
                        left, abs(x) + glyph.shift_x, abs(x) + glyph.width + glyph.dx
                    )
                    if x == 0:
                        if right is None:
                            right = 0
                        else:
                            right = max(right, glyph.dx)
                    position_x = x - glyph.width

            elif self._label_direction == "TTB":
                if x == 0:
                    if left is None:
                        left = 0
                    else:
                        left = min(left, glyph.dx)
                if y == 0:
                    top = min(top, -glyph.dy)

                bottom = max(bottom, y + glyph.height, y + glyph.height + glyph.dy)
                right = max(
                    right, x + glyph.width + glyph.dx, x + glyph.shift_x + glyph.dx
                )
                position_y = y + glyph.dy
                position_x = x - glyph.width // 2 + self._y_offset

            elif self._label_direction == "UPR":
                if x == 0:
                    if bottom is None:
                        bottom = -glyph.dx

                if y == 0:  # first line, find the Ascender height
                    bottom = min(bottom, -glyph.dy)
                left = min(left, x - glyph.height + self._y_offset)
                top = min(top, y - glyph.width - glyph.dx, y - glyph.shift_x)
                right = max(right, x + glyph.height, x + glyph.height - glyph.dy)
                position_y = y - glyph.width - glyph.dx
                position_x = x - glyph.height - glyph.dy + self._y_offset

            elif self._label_direction == "DWR":
                if y == 0:
                    if top is None:
                        top = -glyph.dx
                top = min(top, -glyph.dx)
                if x == 0:
                    left = min(left, -glyph.dy)
                left = min(left, x, x - glyph.dy - self._y_offset)
                bottom = max(bottom, y + glyph.width + glyph.dx, y + glyph.shift_x)
                right = max(right, x + glyph.height)
                position_y = y + glyph.dx
                position_x = x + glyph.dy - self._y_offset

            if glyph.width > 0 and glyph.height > 0:
                face = TileGrid(
                    glyph.bitmap,
                    pixel_shader=self._palette,
                    default_tile=glyph.tile_index,
                    tile_width=glyph.width,
                    tile_height=glyph.height,
                    x=position_x,
                    y=position_y,
                )

                if self._label_direction == "UPR":
                    face.transpose_xy = True
                    face.flip_x = True
                if self._label_direction == "DWR":
                    face.transpose_xy = True
                    face.flip_y = True

                if tilegrid_count < len(self._local_group):
                    self._local_group[tilegrid_count] = face
                else:
                    self._local_group.append(face)
                tilegrid_count += 1

            if self._label_direction == "RTL":
                x = x - glyph.shift_x
            if self._label_direction == "TTB":
                if glyph.height < 2:
                    y = y + glyph.shift_x
                else:
                    y = y + glyph.height + 1
            if self._label_direction == "UPR":
                y = y - glyph.shift_x
            if self._label_direction == "DWR":
                y = y + glyph.shift_x
            if self._label_direction == "LTR":
                x = x + glyph.shift_x

            i += 1

        if self._label_direction == "LTR" and left is None:
            left = 0
        if self._label_direction == "RTL" and right is None:
            right = 0
        if self._label_direction == "TTB" and top is None:
            top = 0

        while len(self._local_group) > tilegrid_count:  # i:
            self._local_group.pop()

        if self._label_direction == "RTL":
            # pylint: disable=invalid-unary-operand-type
            # type-checkers think left can be None
            self._bounding_box = (-left, top, left - right, bottom - top)
        if self._label_direction == "TTB":
            self._bounding_box = (left, top, right - left, bottom - top)
        if self._label_direction == "UPR":
            self._bounding_box = (left, top, right, bottom - top)
        if self._label_direction == "DWR":
            self._bounding_box = (left, top, right, bottom - top)
        if self._label_direction == "LTR":
            self._bounding_box = (left, top, right - left, bottom - top)

        self._text = new_text

        if self._background_color is not None:
            self._set_background_color(self._background_color)

    def _reset_text(self, new_text: str) -> None:
        current_anchored_position = self.anchored_position
        self._update_text(str(self._replace_tabs(new_text)))
        self.anchored_position = current_anchored_position

    def _set_font(self, new_font: FontProtocol) -> None:
        old_text = self._text
        current_anchored_position = self.anchored_position
        self._text = ""
        self._font = new_font
        self._height = self._font.get_bounding_box()[1]
        self._update_text(str(old_text))
        self.anchored_position = current_anchored_position

    def _set_line_spacing(self, new_line_spacing: float) -> None:
        self._line_spacing = new_line_spacing
        self.text = self._text  # redraw the box

    def _set_text(self, new_text: str, scale: int) -> None:
        self._reset_text(new_text)

    def _set_label_direction(self, new_label_direction: str) -> None:
        self._label_direction = new_label_direction
        self._update_text(str(self._text))

    def _get_valid_label_directions(self) -> Tuple[str, ...]:
        return "LTR", "RTL", "UPR", "DWR", "TTB"
According to the instructions, I just have to load the files onto the board and everything will work.
I think I'm making some stupid mistake, but I can't find where.
Reply
#2
You forgot to post the error message. You only posted the stack trace. The error message says what happened. The stack trace says where it happened.

The error is not in label, that is just where the error causes the program to crash. The error will be in the code you selected to run. It tried to make a label but passed a bad argument.

There is no <string> file. This would be the menu option you selected. The program reads the associated file into a str, and passes that to exec()
exec(open(menu_options[selected]).read())
# filename = menu_options[selected]
# <string> = open(filename).read()
# exec(<string>)
gad969 likes this post
Reply
#3
Thanks a lot! You really help Rolleyes
I change code a little
menu_options = file_filter(os.listdir())
max_length = len(menu_options)

for i in range(0, max_length, 1):
        print( "[{}] {}".format(i, menu_options[i]))
#pnt20"1234567890123456789")
print("[Press number 0-9]")
try:
    exec(open("simplechat.py").read())
except Exception as err:
    print(f"Unexpected {err=}, {type(err)=}")
And get this message

Unexpected err=no module named 'adafruit_display_text.LabelBase', type(err)=<class 'ImportError'>
According to the traceback from my post, import LabelBase takes place in label.py
It is not possible to import the LabelBase class from the standard library? But I don't understand why
Reply
#4
You should post your quesitons on a dedicated circuitpython forum. You'll get better response.

https://learn.adafruit.com/welcome-to-ci...-community
gad969 likes this post
Reply
#5
I found what the problem was, there was no init file in the library folder Doh
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Coding problem portfolio grade max70990 1 742 Dec-11-2022, 12:30 PM
Last Post: Larz60+
  coding problem from older book teddfirth 3 2,157 Mar-06-2021, 03:51 PM
Last Post: teddfirth
  Begginer coding problem wiktor 2 3,246 Jan-26-2018, 06:24 PM
Last Post: wiktor
  IR coding problem DPaul 3 2,791 Jan-09-2018, 08:02 AM
Last Post: DPaul
  new user coding problem mattkrebs 1 3,040 Mar-21-2017, 12:45 PM
Last Post: buran
  Coding problem VISHU 3 4,851 Mar-16-2017, 06:54 AM
Last Post: Larz60+
  Incredibly basic coding problem AndyF 12 8,544 Feb-11-2017, 03:52 PM
Last Post: AndyF

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020