Skip to content

Commit

Permalink
Type hinting updates
Browse files Browse the repository at this point in the history
Move mypy configuration into `pyproject.toml`.
Use modern style type hints.
  • Loading branch information
smsearcy committed Jun 8, 2024
1 parent 58e03b3 commit 92638ba
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 119 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get install -y librrd-dev
pdm sync -G mypy
pdm sync -G mypy -G testing
- name: Run mypy
run: |
pdm run mypy meshinfo tests
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
all: pre-commit lint mypy tests docs
all: lint pre-commit mypy tests docs

pre-commit:
pdm run pre-commit run --all-files
Expand Down
58 changes: 29 additions & 29 deletions meshinfo/aredn.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import typing
from functools import cached_property
from itertools import zip_longest
from typing import Any, Dict, List, Optional, Tuple
from typing import Any

import attr
import structlog
Expand Down Expand Up @@ -173,10 +173,10 @@ class Interface:

name: str
mac_address: str
ip_address: Optional[str] = None
ip_address: str | None = None

@classmethod
def from_json(cls, raw_data: Dict[str, str]) -> Interface:
def from_json(cls, raw_data: dict[str, str]) -> Interface:
return cls(
name=raw_data["name"],
# some tunnel interfaces lack a MAC address
Expand All @@ -194,7 +194,7 @@ class Service:
link: str

@classmethod
def from_json(cls, raw_data: Dict[str, str]) -> Service:
def from_json(cls, raw_data: dict[str, str]) -> Service:
return cls(
name=raw_data["name"], protocol=raw_data["protocol"], link=raw_data["link"]
)
Expand All @@ -213,17 +213,17 @@ class LinkInfo:
destination_ip: str
type: LinkType
interface: str
quality: Optional[float] = None
neighbor_quality: Optional[float] = None
signal: Optional[int] = None
noise: Optional[int] = None
tx_rate: Optional[float] = None
rx_rate: Optional[float] = None
olsr_cost: Optional[float] = None
quality: float | None = None
neighbor_quality: float | None = None
signal: int | None = None
noise: int | None = None
tx_rate: float | None = None
rx_rate: float | None = None
olsr_cost: float | None = None

@classmethod
def from_json(
cls, raw_data: Dict[str, Any], *, source: str, ip_address: str
cls, raw_data: dict[str, Any], *, source: str, ip_address: str
) -> LinkInfo:
"""Construct the `Link` dataclass from the AREDN JSON information.
Expand Down Expand Up @@ -290,9 +290,9 @@ class SystemInfo:
display_name: str
api_version: str
grid_square: str
latitude: Optional[float]
longitude: Optional[float]
interfaces: Dict[str, Interface]
latitude: float | None
longitude: float | None
interfaces: dict[str, Interface]
ssid: str
channel: str
channel_bandwidth: str
Expand All @@ -301,16 +301,16 @@ class SystemInfo:
firmware_version: str
firmware_manufacturer: str
active_tunnel_count: int
services: List[Service]
services_json: List[Dict]
services: list[Service]
services_json: list[dict]
status: str
source_json: Dict
source_json: dict
description: str = ""
frequency: str = ""
up_time: str = ""
load_averages: Optional[List[float]] = None
links: List[LinkInfo] = attr.Factory(list)
link_count: Optional[int] = None
load_averages: list[float] | None = None
links: list[LinkInfo] = attr.Factory(list)
link_count: int | None = None
connection_ip: str = ""

@property
Expand All @@ -323,7 +323,7 @@ def lan_ip_address(self) -> str:
return ""

@cached_property
def primary_interface(self) -> Optional[Interface]:
def primary_interface(self) -> Interface | None:
"""Get the active wireless interface."""
# FIXME: should this just be done once as part of parsing?
# (that might simplify the `ip_address` property as well,
Expand Down Expand Up @@ -362,7 +362,7 @@ def band(self) -> Band:
return Band.UNKNOWN

@property
def up_time_seconds(self) -> Optional[int]:
def up_time_seconds(self) -> int | None:
"""Convert uptime string to seconds."""
if self.up_time == "":
return None
Expand All @@ -379,14 +379,14 @@ def up_time_seconds(self) -> Optional[int]:
return 86_400 * days + 3_600 * hours + 60 * minutes + seconds

@property
def radio_link_count(self) -> Optional[int]:
def radio_link_count(self) -> int | None:
if not self.links:
# the absence of the data presumably means an older API and thus unknown
return None
return sum(1 for link in self.links if link.type == LinkType.RF)

@property
def dtd_link_count(self) -> Optional[int]:
def dtd_link_count(self) -> int | None:
if not self.links:
# the absence of the data presumably means an older API and thus unknown
return None
Expand All @@ -400,7 +400,7 @@ def tunnel_link_count(self) -> int:
return sum(1 for link in self.links if link.type == LinkType.TUN)

@property
def api_version_tuple(self) -> Tuple[int, ...]:
def api_version_tuple(self) -> tuple[int, ...]:
try:
return tuple(int(value) for value in self.api_version.split("."))
except ValueError:
Expand Down Expand Up @@ -508,8 +508,8 @@ class VersionChecker:
"""

_firmware: Tuple[int, ...]
_api: Tuple[int, ...]
_firmware: tuple[int, ...]
_api: tuple[int, ...]

@classmethod
def from_config(cls, config: AppConfig.Aredn) -> VersionChecker:
Expand All @@ -536,7 +536,7 @@ def api(self, version: str) -> int:
return _version_delta(current, self._api)


def _version_delta(sample: Tuple[int, ...], standard: Tuple[int, ...]) -> int:
def _version_delta(sample: tuple[int, ...], standard: tuple[int, ...]) -> int:
"""Weight the difference between two versions on a scale of 0 to 3."""
length = max(len(standard), len(sample))
for position, (current, goal) in enumerate(
Expand Down
2 changes: 1 addition & 1 deletion meshinfo/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import subprocess
import tarfile
from collections import Counter
from collections.abc import Iterator
from multiprocessing.pool import Pool
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Iterator

import rrdtool
import structlog
Expand Down
4 changes: 2 additions & 2 deletions meshinfo/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import logging
import os
from pathlib import Path
from typing import Any, Dict, Optional
from typing import Any

import attrs
import environ
Expand Down Expand Up @@ -121,7 +121,7 @@ def from_env() -> AppConfig:


def configure(
settings: Optional[Dict[str, Any]] = None, *, app_config: Optional[AppConfig] = None
settings: dict[str, Any] | None = None, *, app_config: AppConfig | None = None
) -> Configurator:
"""Configure the Pyramid application."""

Expand Down
23 changes: 12 additions & 11 deletions meshinfo/historical.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from __future__ import annotations

import enum
from collections.abc import Iterable
from itertools import cycle
from pathlib import Path
from typing import Any, Iterable, List, Optional
from typing import Any

import attr
import pendulum
Expand Down Expand Up @@ -56,9 +57,9 @@ class Period(enum.Enum):

@attr.s(auto_attribs=True, slots=True)
class GraphParams:
period: Optional[Period] = None
start: Optional[pendulum.DateTime] = None
end: Optional[pendulum.DateTime] = None
period: Period | None = None
start: pendulum.DateTime | None = None
end: pendulum.DateTime | None = None
title: str = ""

def as_dict(self):
Expand Down Expand Up @@ -551,12 +552,12 @@ class Graph:
end: str = ""
title: str = ""
vertical_label: str = ""
lower_bound: Optional[float] = None
options: List[str] = attr.Factory(list)
data_definitions: List[str] = attr.Factory(list)
data_calculations: List[str] = attr.Factory(list)
variable_definitions: List[str] = attr.Factory(list)
elements: List[str] = attr.Factory(list)
lower_bound: float | None = None
options: list[str] = attr.Factory(list)
data_definitions: list[str] = attr.Factory(list)
data_calculations: list[str] = attr.Factory(list)
variable_definitions: list[str] = attr.Factory(list)
elements: list[str] = attr.Factory(list)

_common_stats = {
"lst": "LAST",
Expand All @@ -572,7 +573,7 @@ def add_summarized_ds(
color: str,
style: str,
definition: str = "",
definitions: Optional[Iterable[str]] = None,
definitions: Iterable[str] | None = None,
calculation: str = "",
legend: str = "",
fmt: str = "%10.2lf",
Expand Down
2 changes: 1 addition & 1 deletion meshinfo/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

import contextlib
from typing import Iterator
from collections.abc import Iterator

import attr
import zope.sqlalchemy
Expand Down
3 changes: 1 addition & 2 deletions meshinfo/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from __future__ import annotations

import enum
from typing import Optional

import attr

Expand All @@ -18,7 +17,7 @@ class LinkId:
type: LinkType

@classmethod
def from_url(cls, params: dict) -> Optional[LinkId]:
def from_url(cls, params: dict) -> LinkId | None:
"""Create `LinkId` object from path parameters."""

try:
Expand Down
3 changes: 1 addition & 2 deletions meshinfo/views/nodes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import csv
import io
from operator import attrgetter
from typing import List

from pyramid.request import Request, Response
from pyramid.view import view_config, view_defaults
Expand All @@ -18,7 +17,7 @@ def __init__(self, request: Request):

# TODO: parameters to determine which nodes to return
query = dbsession.query(Node).filter(Node.status != NodeStatus.INACTIVE)
self.nodes: List[Node] = sorted(query.all(), key=attrgetter("name"))
self.nodes: list[Node] = sorted(query.all(), key=attrgetter("name"))
self.request = request

@view_config(match_param="view=table", renderer="pages/nodes.jinja2")
Expand Down
25 changes: 0 additions & 25 deletions mypy.ini

This file was deleted.

37 changes: 26 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ Documentation = "https://mesh-info-ki7onk.readthedocs.io/"
[project.scripts]
meshinfo = "meshinfo.cli:main"


[tool.mypy]
# postponing enabling this for another day
# disallow_untyped_defs = true

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = [
"appdirs.*",
"hupper.*",
"pyramid.*",
"rrdtool.*",
"sqlalchemy.*",
"transaction.*",
"webtest.*",
"zope.*",
]


[tool.pdm.dev-dependencies]
testing = [
"Faker>=25.3.0",
Expand All @@ -73,6 +92,7 @@ mypy = [
"mypy>=1.10.0",
]


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

Expand All @@ -89,21 +109,16 @@ select = [
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"PLC", "PLE", "PLW", # "PLR" # pylint
"PLC", "PLE", "PLW", # pylint
"UP", # pyupgrade
"YTT", # flake8-2020
# "D", # pydocstyle
# "RET", # flake8-return
# "SIM", # flake8-simplify
# "UP", # pyupgrade
# Saving these for another day
# "D", # pydocstyle
# "RET", # flake8-return
# "SIM", # flake8-simplify
]
ignore = [
"A003", # builtin-attribute-shadowing
"C416", # unnecessary `dict` comprehension
"D105", # magic-method
"D107", # public-init
"D203", # one-blank-line-before-class
"D213", # multi-line-summary-second-line
"PLR2004", # magic-value-comparison
]

[tool.ruff.lint.isort]
Expand Down
Loading

0 comments on commit 92638ba

Please sign in to comment.