Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable code linting (static code analysis) via pre-commit + ruff and fix findings #584

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
on:
push:
branches:
- main
- dev
pull_request:

name: pre-commit

concurrency:
# Concurrency group that uses the workflow name and PR number if available
# or commit SHA as a fallback. If a new build is triggered under that
# concurrency group while a previous build is running it will be canceled.
# Repeated pushes to a PR will cancel all previous builds, while multiple
# merges to main will not cancel.
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- uses: pre-commit/[email protected]
37 changes: 37 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Apply to all files without commiting:
# pre-commit run --all-files
# Or enabled to run as git pre-commit hook:
# pre-commit install
# Update this file:
# pre-commit autoupdate
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-added-large-files
- id: check-ast
- id: fix-byte-order-marker
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: debug-statements
- id: detect-private-key
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.5
hooks:
- id: ruff
args: [--fix, --show-fixes]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.14.0
hooks:
- id: pretty-format-toml
args: [--autofix]
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.29.0
hooks:
- id: check-github-workflows
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

[![CI](https://github.com/SeedSigner/seedsigner/actions/workflows/tests.yml/badge.svg)](https://github.com/SeedSigner/seedsigner/actions/workflows/tests.yml)
[![Build](https://github.com/SeedSigner/seedsigner/actions/workflows/build.yml/badge.svg)](https://github.com/SeedSigner/seedsigner/actions/workflows/build.yml)
[![pre-commit](https://github.com/SeedSigner/seedsigner/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/SeedSigner/seedsigner/actions/workflows/pre-commit.yml)

The goal of SeedSigner is to lower the cost and complexity of Bitcoin multi-signature wallet use. To accomplish this goal, SeedSigner offers anyone the opportunity to build a verifiably air-gapped, stateless Bitcoin signing device using inexpensive, publicly available hardware components (usually < $50). SeedSigner helps users save with Bitcoin by assisting with trustless private key generation and multisignature (aka "multisig") wallet setup, and helps users transact with Bitcoin via a secure, air-gapped QR-exchange signing model.

Expand Down
16 changes: 15 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,22 @@ skip_empty = true
branch = true

[tool.pytest.ini_options]
testpaths = ["tests"]
log_level = "DEBUG"
testpaths = ["tests"]

[tool.ruff]
target-version = "py310"

[tool.ruff.lint]
fixable = ["ALL"]
# List of rules https://docs.astral.sh/ruff/rules/
select = ["F", "T20"]

[tool.ruff.lint.per-file-ignores]
# vendored, so ignoring
"src/seedsigner/helpers/ur2/*" = ["F", "T20"]
"tests/**" = ["T20"]
"tools/*.py" = ["T20"]

[tool.setuptools]
include-package-data = true
Expand Down
2 changes: 1 addition & 1 deletion src/seedsigner/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def run(self):
def time_import(module_name):
last = time.time()
import_module(module_name)
# print(time.time() - last, module_name)
logger.debug(f"Importing {module_name} took {time.time() - last} seconds")

time_import('embit')
time_import('seedsigner.helpers.embit_utils')
Expand Down
4 changes: 3 additions & 1 deletion src/seedsigner/gui/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .renderer import Renderer
from .renderer import Renderer

__all__ = [Renderer]
5 changes: 2 additions & 3 deletions src/seedsigner/gui/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os
import pathlib
import re
from time import time

from dataclasses import dataclass
from decimal import Decimal
Expand Down Expand Up @@ -344,7 +343,7 @@ def __post_init__(self):
# Multiply for the number of lines plus the spacer
total_text_height = self.text_height_above_baseline * len(self.text_lines) + self.line_spacing * (len(self.text_lines) - 1)

if not self.height_ignores_below_baseline and re.findall(f"[gjpqy]", self.text_lines[-1]["text"]):
if not self.height_ignores_below_baseline and re.findall("[gjpqy]", self.text_lines[-1]["text"]):
# Last line has at least one char that dips below baseline
total_text_height += self.text_height_below_baseline

Expand Down Expand Up @@ -1352,7 +1351,7 @@ def reflow_text_for_width(text: str,
# We have to figure out if and where to make line breaks in the text so that it
# fits in its bounding rect (plus accounting for edge padding) using its given
# font.
start = time()
# start = time()
font = Fonts.get_font(font_name=font_name, size=font_size)
# Measure from left baseline ("ls")
(left, top, full_text_width, bottom) = font.getbbox(text, anchor="ls")
Expand Down
10 changes: 5 additions & 5 deletions src/seedsigner/gui/keyboard.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from PIL import Image, ImageDraw, ImageFont
from PIL import Image, ImageDraw
from typing import Tuple

from seedsigner.gui.components import Fonts, GUIConstants
Expand Down Expand Up @@ -318,7 +318,7 @@ def get_key_at(self, index_x, index_y):
return None

effective_index = 0
key = None
# key = None
for cur_key in self.keys[index_y]:
if index_x >= effective_index and index_x < effective_index + cur_key.size:
return cur_key
Expand Down Expand Up @@ -552,7 +552,7 @@ def render(self, cur_text=None, cursor_position=None):

if self.cursor_mode == TextEntryDisplay.CURSOR_MODE__BLOCK:
cursor_block_width = 18
cursor_block_height = 33
# cursor_block_height = 33

# Draw n-1 of the selected letters
(left, top, right, bottom) = self.font.getbbox(self.cur_text[:-1], anchor="ls")
Expand Down Expand Up @@ -592,7 +592,7 @@ def render(self, cur_text=None, cursor_position=None):
# The entire cur_text plus the cursor bar fits
self.text_offset = 3 + cursor_bar_serif_half_width
left, top, right, bottom = self.font.getbbox(self.cur_text[:cursor_position])
tw_left, th = right - left, bottom - top
tw_left, _ = right - left, bottom - top
cursor_bar_x = self.text_offset + tw_left

else:
Expand All @@ -601,7 +601,7 @@ def render(self, cur_text=None, cursor_position=None):

# Is the cursor at either extreme?
left, top, right, bottom = self.font.getbbox(self.cur_text[:cursor_position])
tw_left, th = right - left, bottom - top
tw_left, _ = right - left, bottom - top

if self.text_offset + tw_left + cursor_bar_serif_half_width + 3 >= self.width:
# Cursor is at the extreme right; have to push the full tw_right off
Expand Down
1 change: 0 additions & 1 deletion src/seedsigner/gui/renderer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from PIL import Image, ImageDraw
from threading import Lock

from seedsigner.gui.components import Fonts, GUIConstants
from seedsigner.hardware.ST7789 import ST7789
from seedsigner.models.singleton import ConfigurableSingleton

Expand Down
2 changes: 1 addition & 1 deletion src/seedsigner/gui/screens/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .screen import *
# from .screen import *
22 changes: 11 additions & 11 deletions src/seedsigner/gui/screens/psbt_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from seedsigner.gui.renderer import Renderer
from seedsigner.models.threads import BaseThread

from .screen import ButtonListScreen, WarningScreen
from ..components import (BtcAmount, Button, Icon, FontAwesomeIconConstants, IconTextLine, FormattedAddress, GUIConstants, Fonts, SeedSignerIconConstants, TextArea,
from .screen import ButtonListScreen
from ..components import (BtcAmount, Icon, FontAwesomeIconConstants, IconTextLine, FormattedAddress, GUIConstants, Fonts, SeedSignerIconConstants, TextArea,
calc_bezier_curve, linear_interp)


Expand Down Expand Up @@ -100,7 +100,7 @@ def __post_init__(self):
max_inputs_text_width = 0
for input in inputs_column:
left, top, right, bottom = font.getbbox(input)
tw, th = right - left, bottom - top
tw, _ = right - left, bottom - top
max_inputs_text_width = max(tw, max_inputs_text_width)

# Given how wide we want our curves on each side to be...
Expand Down Expand Up @@ -139,11 +139,11 @@ def truncate_destination_addr(addr):
destination_column.append(truncate_destination_addr("self-transfer"))
else:
# destination_column.append(f"{len(self.destination_addresses)} recipients")
destination_column.append(f"recipient 1")
destination_column.append(f"[ ... ]")
destination_column.append("recipient 1")
destination_column.append("[ ... ]")
destination_column.append(f"recipient {len(self.destination_addresses) + self.num_self_transfer_outputs}")

destination_column.append(f"fee")
destination_column.append("fee")

if self.has_op_return:
destination_column.append("OP_RETURN")
Expand All @@ -155,7 +155,7 @@ def truncate_destination_addr(addr):
max_destination_text_width = 0
for destination in destination_column:
left, top, right, bottom = font.getbbox(destination)
tw, th = right - left, bottom - top
tw, _ = right - left, bottom - top
max_destination_text_width = max(tw, max_destination_text_width)

return (max_destination_text_width, destination_column)
Expand Down Expand Up @@ -202,7 +202,7 @@ def truncate_destination_addr(addr):
for input in inputs_column:
# Calculate right-justified input display
left, top, right, bottom = font.getbbox(input)
tw, th = right - left, bottom - top
tw, _ = right - left, bottom - top
cur_x = inputs_x + max_inputs_text_width - tw
draw.text(
(cur_x, inputs_y),
Expand Down Expand Up @@ -530,9 +530,9 @@ def render_amount(cur_y, amount_str, info_text, info_text_color=GUIConstants.BOD
mid_zone = display_str[-6:-3]
end_zone = display_str[-3:]
left, top, right, bottom = fixed_width_font.getbbox(main_zone)
main_zone_width, th = right - left, bottom - top
main_zone_width, _ = right - left, bottom - top
left, top, right, bottom = fixed_width_font.getbbox(end_zone)
mid_zone_width, th = right - left, bottom - top
mid_zone_width, _ = right - left, bottom - top
draw.text((0, cur_y), text=main_zone, font=fixed_width_font, fill=GUIConstants.BODY_FONT_COLOR)
draw.text((main_zone_width + digit_group_spacing, cur_y), text=mid_zone, font=fixed_width_font, fill=secondary_digit_color)
draw.text((main_zone_width + digit_group_spacing + mid_zone_width + digit_group_spacing, cur_y), text=end_zone, font=fixed_width_font, fill=tertiary_digit_color)
Expand Down Expand Up @@ -562,7 +562,7 @@ def render_amount(cur_y, amount_str, info_text, info_text_color=GUIConstants.BOD
render_amount(
cur_y,
f"-{self.fee_amount}",
info_text=f""" fee""",
info_text=""" fee""",
)

cur_y += digits_height + GUIConstants.BODY_LINE_SPACING * ssf
Expand Down
2 changes: 1 addition & 1 deletion src/seedsigner/gui/screens/scan_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from seedsigner.models.threads import BaseThread, ThreadsafeCounter

from .screen import BaseScreen
from ..components import GUIConstants, Fonts, SeedSignerIconConstants
from ..components import GUIConstants, Fonts



Expand Down
2 changes: 1 addition & 1 deletion src/seedsigner/gui/screens/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def __post_init__(self):
self.down_arrow_img = Image.new("RGBA", size=(2 * self.arrow_half_width, 8), color="black")
self.down_arrow_img_y = self.canvas_height - 16 + 2
arrow_draw = ImageDraw.Draw(self.down_arrow_img)
center_x = int(self.canvas_width / 2)
# center_x = int(self.canvas_width / 2)
arrow_draw.line((self.arrow_half_width, 7, 0, 1), fill=GUIConstants.BUTTON_FONT_COLOR)
arrow_draw.line((self.arrow_half_width, 7, 2 * self.arrow_half_width, 1), fill=GUIConstants.BUTTON_FONT_COLOR)

Expand Down
6 changes: 3 additions & 3 deletions src/seedsigner/gui/screens/seed_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def render_possible_matches(self, highlight_word=None):

highlighted_row = 3
num_possible_rows = 11
y = self.highlighted_row_y - GUIConstants.LIST_ITEM_PADDING - 3 * self.matches_list_row_height
# y = self.highlighted_row_y - GUIConstants.LIST_ITEM_PADDING - 3 * self.matches_list_row_height

if not highlight_word:
list_starting_index = self.selected_possible_words_index - highlighted_row
Expand Down Expand Up @@ -1189,8 +1189,8 @@ def __post_init__(self):
msg = "click to exit"
font = Fonts.get_font(GUIConstants.BODY_FONT_NAME, GUIConstants.BODY_FONT_SIZE)
(left, top, right, bottom) = font.getbbox(msg, anchor="ls")
msg_height = -1 * top
msg_width = right
# msg_height = -1 * top
# msg_width = right
# draw.rectangle(
# (
# int((self.canvas_width - msg_width)/2 - GUIConstants.COMPONENT_PADDING),
Expand Down
5 changes: 2 additions & 3 deletions src/seedsigner/gui/screens/settings_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
from dataclasses import dataclass
from PIL.ImageOps import autocontrast
from typing import List
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, IconTextLine, TextArea
from seedsigner.gui.screens.scan_screens import ScanScreen
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, TextArea

from seedsigner.gui.screens.screen import BaseScreen, BaseTopNavScreen, ButtonListScreen
from seedsigner.gui.screens.screen import BaseTopNavScreen, ButtonListScreen
from seedsigner.hardware.buttons import HardwareButtonsConstants
from seedsigner.hardware.camera import Camera
from seedsigner.models.settings import SettingsConstants
Expand Down
1 change: 0 additions & 1 deletion src/seedsigner/hardware/pivideostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from picamera.array import PiRGBArray
from picamera import PiCamera
from threading import Thread
import time

logger = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion src/seedsigner/helpers/embit_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def get_standard_derivation_path(network: str = SettingsConstants.MAINNET, walle

elif wallet_type == SettingsConstants.MULTISIG:
if script_type == SettingsConstants.LEGACY_P2PKH:
return f"m/45'" #BIP45
return "m/45'" #BIP45
elif script_type == SettingsConstants.NESTED_SEGWIT:
return f"m/48'/{network_path}/0'/1'"
elif script_type == SettingsConstants.NATIVE_SEGWIT:
Expand Down
Loading
Loading