Skip to content

Commit

Permalink
Add mypy, raise minimum version, fixup code (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
Benedikt-Brunner authored Nov 29, 2024
1 parent 44e71f7 commit b42322b
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 178 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ jobs:
- name: Lint everything
run: uvx tomlscript lint

run-static-analysis:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Install Python
run: uv python install
- name: Install dependencies
run: uv sync --all-extras --dev
- name: Run static analysis
run: uvx tomlscript typecheck

run-tests:
runs-on: ubuntu-latest
steps:
Expand Down
26 changes: 26 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,30 @@ are:
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

- `mypy` licensed as follows:
"""
The MIT License

Copyright (c) 2012-2023 Jukka Lehtosalo and contributors
Copyright (c) 2015-2023 Dropbox, Inc.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ To run test use `uvx tomlscript test`.

To run the linter use `uvx tomlscript lint` or `uvx tomlscript lint-fix` to fix the issues.

To statically type check the project use `uvx tomlscript typecheck`.

8 changes: 8 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[mypy]
ignore_missing_imports = True
warn_return_any = True
disallow_untyped_defs = True

[mypy-napytau.gui.*]
# ignore any returns in gui, as it uses external libraries without type hints and will have to return Any sometimes
warn_return_any = False
3 changes: 3 additions & 0 deletions napytau/cli/cli_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@


class CLIArguments:
headless: bool
filename: str

def __init__(self, raw_args: Namespace):
self.headless = coalesce(raw_args.headless, False)
self.filename = raw_args.filename
Expand Down
2 changes: 1 addition & 1 deletion napytau/core/logic_mockup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def logic(value):
def logic(value: int) -> int:
if value > 10:
return value ** 2
else:
Expand Down
17 changes: 9 additions & 8 deletions napytau/gui/ui_mockup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import tkinter as tk
from tkinter import Canvas
from tkinter import Widget

import customtkinter
from matplotlib.figure import Figure
Expand All @@ -16,7 +17,7 @@
) # Themes: "blue" (standard), "green", "dark-blue"


def plot(value, window) -> Canvas:
def plot(value: int, window: Widget) -> Canvas:
# the figure that will contain the plot
fig = Figure(figsize=(3, 2), dpi=100, facecolor="white", edgecolor="black")

Expand All @@ -38,7 +39,7 @@ def plot(value, window) -> Canvas:


class App(customtkinter.CTk):
def __init__(self):
def __init__(self) -> None:
super().__init__()

# values
Expand Down Expand Up @@ -153,20 +154,20 @@ def __init__(self):
self.slider_2.configure(command=self.use_slider_value)
self.label.configure(text="Result: ")

def change_appearance_mode_event(self, new_appearance_mode: str):
def change_appearance_mode_event(self, new_appearance_mode: str) -> None:
customtkinter.set_appearance_mode(new_appearance_mode)

def change_scaling_event(self, new_scaling: str):
def change_scaling_event(self, new_scaling: str) -> None:
new_scaling_float = int(new_scaling.replace("%", "")) / 100
customtkinter.set_widget_scaling(new_scaling_float)

def sidebar_button_event(self):
def sidebar_button_event(self) -> None:
print("sidebar_button click")

def use_slider_value(self, _value):
def use_slider_value(self, _value: int) -> None:
self.calc()

def calc(self):
def calc(self) -> None:
entry_value = self.tau.get()

self.label.configure(text=f"Result: {logic(entry_value)}")
Expand All @@ -182,6 +183,6 @@ def calc(self):
)


def init(cli_arguments: CLIArguments):
def init(cli_arguments: CLIArguments) -> None:
app = App()
app.mainloop()
2 changes: 1 addition & 1 deletion napytau/headless/headless_mockup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from napytau.ingest.ingest_mockup import ingest_file


def init(cli_arguments: CLIArguments):
def init(cli_arguments: CLIArguments) -> None:
print("running headless mockup")
if cli_arguments.has_filename():
print(
Expand Down
2 changes: 1 addition & 1 deletion napytau/ingest/ingest_mockup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def ingest_file(filename):
def ingest_file(filename: str) -> str:
# Ingest data from a file
with open(filename) as f:
data = f.read()
Expand Down
2 changes: 1 addition & 1 deletion napytau/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from cli.parser import parse_cli_arguments


def main():
def main() -> None:
args = parse_cli_arguments()

if args.headless:
Expand Down
6 changes: 4 additions & 2 deletions napytau/util/coalesce.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
def coalesce(*args):
from typing import Optional

def coalesce[T](*args: Optional[T]) -> T:
for arg in args:
if arg is not None:
return arg
return None
raise ValueError("All arguments are None")
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "napytau"
version = "0.1.0"
description = "A modern reimplementation of napatau"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.12"
dependencies = [
"customtkinter>=5.2.2",
"matplotlib>=3.9.2",
Expand All @@ -13,15 +13,20 @@ dependencies = [
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
packages = ["napytau"]

[tool.tomlscript]
run= "uv run napytau/main.py"
test = "uv run pytest -rA"
lint = "uv run ruff check --config ruff.toml"
lint-fix = "uv run ruff check --config ruff.toml --fix"
format = "uv run ruff format"
typecheck = "uv run mypy napytau --config-file=mypy.ini"

[dependency-groups]
dev = [
"pytest>=7.4.4",
"ruff>=0.8.0",
"mypy>=1.13.0",
]
10 changes: 5 additions & 5 deletions tests/util/coalesce_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ def test_returnsFirstNonNoneArgument(self):
"""Returns the first non-None argument."""
self.assertEqual(1, coalesce(None, None, None, 1, 2, 3))

def test_returnsNoneIfAllArgumentsAreNone(self):
"""Returns None if all arguments are None."""
self.assertIsNone(coalesce(None, None, None))
def test_raisesAValueErrorIfAllArgumentsAreNone(self):
"""Raises a ValueError if all arguments are None."""
self.assertRaises(ValueError, coalesce, None, None, None)

def test_returnsNoneIfNoArgumentsAreProvided(self):
def test_raisesAValueErrorIfNoArgumentsAreProvided(self):
"""Returns None if no arguments are provided."""
self.assertIsNone(coalesce())
self.assertRaises(ValueError, coalesce)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit b42322b

Please sign in to comment.