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

Add ruff for linting and formatting #20

Merged
merged 8 commits into from
Jun 4, 2024
Merged
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
2 changes: 0 additions & 2 deletions .flake8

This file was deleted.

30 changes: 28 additions & 2 deletions pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ octologo = "octologo.__main__:main"
[tool.pdm]
distribution = true

[tool.pdm.dev-dependencies]
dev = [
"ruff>=0.4.7",
]

[tool.pdm.scripts]
format = "ruff format"
format-check = "ruff format --check"
lint = "ruff check --fix --show-fixes"
lint-check = "ruff check"
15 changes: 15 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Default formatting rules are pretty good
line-length = 120
[lint]
# Read more here https://beta.ruff.rs/docs/rules/
# By default, Ruff enables Flake8's E and F rules
# Pyflakes - F, pycodestyle - E, W
# flake8-builtins - A
# flake8-annotations - ANN
# flake8-simplify - SIM
# Pylint - PLC, PLE, PLW
# isort - I
select = ['E', 'F', 'W', 'A', 'PLC', 'PLE', 'PLW', 'I', 'SIM', 'ANN']
ignore = [
'ANN101'
]
2 changes: 1 addition & 1 deletion src/octologo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Simple program that generates a logo for your open source projects"""

__version__ = "3.0.0"
__version__ = "3.0.0-dev"
33 changes: 18 additions & 15 deletions src/octologo/__main__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import os
from collections.abc import Generator
from time import time
from octologo.utils import BASE_DIR, style_names, styles, logger
from octologo import __version__
from octologo.wizard import TextQuestion, SelectQuestion, Wizard, inq_ask

from click_extra import ExtraContext, Parameter, extra_command, option
from PIL.Image import Image
from textual.app import App
from textual.widgets import Header, Footer, Label, LoadingIndicator
from textual.validation import Length
from PIL import Image
from textual.events import Key
from click_extra import extra_command, option, ExtraContext, Parameter
from textual.validation import Length
from textual.widgets import Footer, Header, Label, LoadingIndicator

from octologo import __version__
from octologo.utils import BASE_DIR, logger, style_names, styles
from octologo.wizard import SelectQuestion, TextQuestion, Wizard, inq_ask

# from textual import log

Expand All @@ -23,7 +26,7 @@
]


def get_output_filaname(project_name):
def get_output_filaname(project_name: str) -> str:
return f"octologo_{project_name}_{int(time())}.png"


Expand All @@ -38,16 +41,16 @@ class OctoLogoApp(App):
TITLE = "Octo Logo Wizard"
finished: bool = False
save_to: str | None = None
result: Image.Image | None = None
result: Image | None = None
loading_wid: LoadingIndicator = LoadingIndicator(classes="hidden")

async def on_key(self, event: Key):
async def on_key(self, event: Key) -> None:
if event.key == "enter" and self.finished:
await self.action_quit()
elif event.key == "v" and self.finished:
self.result.show()

def on_wizard_finished(self, message: Wizard.Finished):
def on_wizard_finished(self, message: Wizard.Finished) -> None:
# Get the wizard answers and the wizard's id
self.answers.update(message.answers)
finished_wizard_id = message.wizard_id
Expand All @@ -70,7 +73,7 @@ def on_wizard_finished(self, message: Wizard.Finished):
self.set_timer(2, self.final_message)

# Final message
def final_message(self):
def final_message(self) -> None:
self.loading_wid.add_class("hidden")
self.mount(
Label(
Expand All @@ -82,7 +85,7 @@ def final_message(self):
self.result.save(self.save_to)
self.finished = True

def compose(self):
def compose(self) -> Generator:
self.app.title = f"Octo Logo v{__version__}"

yield Header(show_clock=True)
Expand All @@ -95,7 +98,7 @@ def compose(self):
yield self.loading_wid


def disable_ansi(ctx: ExtraContext, param: Parameter, val: bool):
def disable_ansi(ctx: ExtraContext, param: Parameter, val: bool) -> bool:
ctx.color = not val

# We must return the value for the main function no_ansi parameter not to be None
Expand All @@ -106,7 +109,7 @@ def disable_ansi(ctx: ExtraContext, param: Parameter, val: bool):
@option(
"-t", "--no-tui", is_flag=True, help="Dont use the Textual Terminal User Interface"
)
def main(no_tui: bool):
def main(no_tui: bool) -> None:
use_tui = not no_tui

if use_tui:
Expand Down
4 changes: 3 additions & 1 deletion src/octologo/styles/first_letter_underlined.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from PIL.Image import Image

from . import underline_core

display_name = "First letters underlined"
active = True
questions = underline_core.questions


def get_image(answers):
def get_image(answers: dict) -> Image:
return underline_core.get_image(answers)
77 changes: 50 additions & 27 deletions src/octologo/styles/underline_core.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
from octologo.wizard import TextQuestion, SelectQuestion
from textual.validation import Number
from octologo.utils import font_list, color_scheme_names, FONTS_DIR, color_schemes, os, get_font_height, get_text_size
from PIL import Image, ImageDraw, ImageFont, ImageColor
import sys

from octologo.utils import (
FONTS_DIR,
color_scheme_names,
color_schemes,
font_list,
get_font_height,
get_text_size,
os,
)
from octologo.wizard import SelectQuestion, TextQuestion
from PIL import Image, ImageColor, ImageDraw, ImageFont
from PIL.Image import Image as ImageClass
from PIL.ImageFont import FreeTypeFont
from textual.validation import Number

sys.path.append("..")


questions = [
SelectQuestion("font", "Select a font", [(font, font) for font in font_list], "Iosevka-Nerd-Font-Complete.ttf"),
SelectQuestion(
"font",
"Select a font",
[(font, font) for font in font_list],
"Iosevka-Nerd-Font-Complete.ttf",
),
SelectQuestion("color", "Select a color scheme", color_scheme_names, "adi1090x"),
TextQuestion("underline_count", "Lettrs to undrline", [Number(minimum=0)], "1", "1"),
TextQuestion(
"underline_count", "Lettrs to undrline", [Number(minimum=0)], "1", "1"
),
TextQuestion("padding_x", "Padding x (px)", [Number()], "200", "200"),
TextQuestion("padding_y", "Padding y (px)", [Number()], "20", "20"),
TextQuestion("gap", "Gap between text and bar (px)", [Number()], "20", "20"),
TextQuestion("bar_size", "Bar weight (px)", [Number()], "20", "20"),
TextQuestion("additionnal_bar_width", "Additionnal bar width (px)", [Number()], "20", "20"),
TextQuestion(
"additionnal_bar_width", "Additionnal bar width (px)", [Number()], "20", "20"
),
]

active = False


def get_image(answers):
def get_image(answers: dict) -> ImageClass:
# Load the selected font
font_size = 500
font = ImageFont.truetype(os.path.join(FONTS_DIR, answers["font"]), font_size)
font: FreeTypeFont = ImageFont.truetype(os.path.join(FONTS_DIR, answers["font"]), font_size)

# Set the colors
background = ImageColor.getrgb(color_schemes[answers['color']]["background"])
text = ImageColor.getrgb(color_schemes[answers['color']]["text"])
accent = ImageColor.getrgb(color_schemes[answers['color']]["accent"])
background = ImageColor.getrgb(color_schemes[answers["color"]]["background"])
text = ImageColor.getrgb(color_schemes[answers["color"]]["text"])
accent = ImageColor.getrgb(color_schemes[answers["color"]]["accent"])

# Get the width and height of the texts
text_width, text_height = get_text_size(answers['name'], font)
text_width, text_height = get_text_size(answers["name"], font)
font_height = get_font_height(font)

# Get the correct image width and height
image_width = 2 * int(answers['padding_x']) + text_width
image_height = 2 * int(answers['padding_y']) + font_height
image_width = 2 * int(answers["padding_x"]) + text_width
image_height = 2 * int(answers["padding_y"]) + font_height

# Create the image
image = Image.new("RGB", (image_width, image_height), background)
Expand All @@ -46,39 +66,42 @@ def get_image(answers):
# Get the text anchor type and position on the image (where the text will be drawn)
# LM = Left/Middle
anchor_type = "lm"
anchor_x = int(answers['padding_x'])
anchor_y = image_height / 2 - (int(answers['gap']) + int(answers['bar_size'])) / 2
anchor_x = int(answers["padding_x"])
anchor_y = image_height / 2 - (int(answers["gap"]) + int(answers["bar_size"])) / 2

anchor_pos = (anchor_x, anchor_y)

if int(answers['underline_count']) > 0:
if int(answers["underline_count"]) > 0:
# Get the bbox of the first n letter to underline
first_letters_bbox = draw.textbbox(
anchor_pos,
answers['name'][:int(answers['underline_count'])],
answers["name"][: int(answers["underline_count"])],
font=font,
anchor=anchor_type)
anchor=anchor_type,
)

# Get the underline position
underline_start_x = first_letters_bbox[0] - int(answers['additionnal_bar_width'])
underline_start_y = first_letters_bbox[3] + int(answers['gap'])
underline_start_x = first_letters_bbox[0] - int(
answers["additionnal_bar_width"]
)
underline_start_y = first_letters_bbox[3] + int(answers["gap"])

underline_end_x = int(answers['additionnal_bar_width']) + first_letters_bbox[2]
underline_end_x = int(answers["additionnal_bar_width"]) + first_letters_bbox[2]

underline_end_y = underline_start_y + int(answers['bar_size'])
underline_end_y = underline_start_y + int(answers["bar_size"])

underline_start = (underline_start_x, underline_start_y)
underline_end = (underline_end_x, underline_end_y)

underline_pos = [underline_start, underline_end]

# Underline the first letter
draw.rectangle(underline_pos, fill=accent, width=answers['bar_size'])
draw.rectangle(underline_pos, fill=accent, width=answers["bar_size"])

# Draw the text
draw.text(
anchor_pos,
answers['name'],
answers["name"],
font=font,
fill=text,
anchor=anchor_type,
Expand All @@ -87,7 +110,7 @@ def get_image(answers):
# Redraw the first letter
draw.text(
anchor_pos,
answers['name'][0],
answers["name"][0],
font=font,
fill=accent,
anchor=anchor_type,
Expand Down
Loading