treewide: fix a bunch of lints

This commit is contained in:
2026-02-03 23:24:37 +09:00
parent e84b43e2a0
commit cf945143ba
23 changed files with 122 additions and 140 deletions

View File

@@ -1,8 +1,8 @@
from typing import Any
from pathlib import Path
import tomllib
import os
import sys
import tomllib
from pathlib import Path
from typing import Any
DEFAULT_CONFIG_PATH = Path("/etc/dibbler/dibbler.toml")
@@ -19,11 +19,11 @@ def default_config_path_submissive_and_readable() -> bool:
and DEFAULT_CONFIG_PATH.stat().st_gid == os.getgid()
),
(DEFAULT_CONFIG_PATH.stat().st_mode & 0o004),
]
],
)
config: dict[str, dict[str, Any]] = dict()
config: dict[str, dict[str, Any]] = {}
def load_config(config_path: Path | None = None):
@@ -49,7 +49,7 @@ def config_db_string() -> str:
path = Path(config["database"]["sqlite"]["path"])
return f"sqlite:///{path.absolute()}"
elif db_type == "postgresql":
if db_type == "postgresql":
host = config["database"]["postgresql"]["host"]
port = config["database"]["postgresql"].get("port", 5432)
username = config["database"]["postgresql"].get("username", "dibbler")
@@ -65,8 +65,6 @@ def config_db_string() -> str:
if host.startswith("/"):
return f"postgresql+psycopg2://{username}:{password}@/{dbname}?host={host}"
else:
return f"postgresql+psycopg2://{username}:{password}@{host}:{port}/{dbname}"
else:
print(f"Error: unknown database type '{db_type}'")
exit(1)
return f"postgresql+psycopg2://{username}:{password}@{host}:{port}/{dbname}"
print(f"Error: unknown database type '{db_type}'")
exit(1)

View File

@@ -2,7 +2,8 @@ import os
import pwd
import signal
import subprocess
from typing import Any, Callable, Literal
from collections.abc import Callable
from typing import Any, Literal
from sqlalchemy import and_, not_, or_
from sqlalchemy.orm import Session
@@ -24,18 +25,17 @@ def search_user(
)
if exact_match:
return exact_match
user_list = (
return (
sql_session.query(User)
.filter(
or_(
User.name.ilike(f"%{string}%"),
User.card.ilike(f"%{string}%"),
User.rfid.ilike(f"%{string}%"),
)
),
)
.all()
)
return user_list
def search_product(
@@ -60,7 +60,7 @@ def search_product(
Product.name == string,
not_(Product.hidden),
),
)
),
)
.first()
)
@@ -73,7 +73,7 @@ def search_product(
or_(
Product.bar_code.ilike(f"%{string}%"),
Product.name.ilike(f"%{string}%"),
)
),
)
.all()
)
@@ -87,7 +87,7 @@ def search_product(
Product.name.ilike(f"%{string}%"),
not_(Product.hidden),
),
)
),
)
.all()
)
@@ -121,7 +121,7 @@ def guess_data_type(string: str) -> Literal["card", "rfid", "bar_code", "usernam
def argmax(
d,
all: bool = False,
all_: bool = False,
value: Callable[[Any], Any] | None = None,
):
maxarg = None
@@ -133,7 +133,7 @@ def argmax(
for key in list(d.keys()):
if maxarg is None or d[key] > d[maxarg]:
maxarg = key
if all:
if all_:
return [k for k in list(d.keys()) if d[k] == d[maxarg]]
return maxarg

View File

@@ -1,5 +1,3 @@
import os
import datetime
# import barcode
# from brother_ql.brother_ql_create import create_label

View File

@@ -3,11 +3,12 @@
import datetime
from collections import defaultdict
from pathlib import Path
from sqlalchemy.orm import Session
from .helpers import *
from ..models import Transaction
from .helpers import *
def getUser(sql_session: Session):
@@ -176,7 +177,7 @@ def addLineToDatabase(database, inputLine):
if abs(inputLine.price) > 90000:
return database
# fyller inn for varer
if (not inputLine.product == "") and (
if (inputLine.product != "") and (
(inputLine.inputProduct == "") or (inputLine.inputProduct == inputLine.product)
):
database.varePersonAntall[inputLine.product][inputLine.user] = (
@@ -190,7 +191,7 @@ def addLineToDatabase(database, inputLine):
database.vareUkedagAntall[inputLine.product][inputLine.weekday] += 1
# fyller inn for personer
if (inputLine.inputUser == "") or (inputLine.inputUser == inputLine.user):
if not inputLine.product == "":
if inputLine.product != "":
database.personVareAntall[inputLine.user][inputLine.product] = (
database.personVareAntall[inputLine.user].setdefault(inputLine.product, 0) + 1
)
@@ -214,7 +215,7 @@ def addLineToDatabase(database, inputLine):
database.personNegTransactions[inputLine.user] = (
database.personNegTransactions.setdefault(inputLine.user, 0) + inputLine.price
)
elif not (inputLine.inputType == 1):
elif inputLine.inputType != 1:
database.globalVareAntall[inputLine.product] = (
database.globalVareAntall.setdefault(inputLine.product, 0) + 1
)
@@ -225,7 +226,7 @@ def addLineToDatabase(database, inputLine):
# fyller inn for global statistikk
if (inputLine.inputType == 3) or (inputLine.inputType == 4):
database.pengebeholdning[inputLine.dateNum] += inputLine.price
if not (inputLine.product == ""):
if inputLine.product != "":
database.globalPersonAntall[inputLine.user] = (
database.globalPersonAntall.setdefault(inputLine.user, 0) + 1
)
@@ -273,7 +274,7 @@ def buildDatabaseFromDb(inputType, inputProduct, inputUser, sql_session: Session
inputLine.price = 0
print("saving as default.dibblerlog...", end=" ")
f = open("default.dibblerlog", "w")
f = Path.open("default.dibblerlog", "w")
line_format = "%s|%s|%s|%s|%s|%s\n"
transaction_list = sql_session.query(Transaction).all()
for transaction in transaction_list:
@@ -290,7 +291,7 @@ def buildDatabaseFromDb(inputType, inputProduct, inputUser, sql_session: Session
transaction.description,
)
f.write(line.encode("utf8"))
f.close
f.close()
# bygg database.pengebeholdning
if (inputType == 3) or (inputType == 4):
for i in range(inputLine.numberOfDays + 1):
@@ -310,7 +311,7 @@ def buildDatabaseFromFile(inputFile, inputType, inputProduct, inputUser):
sdate = input("enter start date (yyyy-mm-dd)? ")
edate = input("enter end date (yyyy-mm-dd)? ")
f = open(inputFile)
f = Path.open(inputFile)
try:
fileLines = f.readlines()
finally:
@@ -328,7 +329,7 @@ def buildDatabaseFromFile(inputFile, inputType, inputProduct, inputUser):
database.globalUkedagForbruk = [0] * 7
database.pengebeholdning = [0] * (inputLine.numberOfDays + 1)
for linje in fileLines:
if not (linje[0] == "#") and not (linje == "\n"):
if linje[0] != "#" and linje != "\n":
# henter dateNum, products, user, price
restDel = linje.partition("|")
restDel = restDel[2].partition(" ")
@@ -406,7 +407,7 @@ def printWeekdays(week, days):
def printBalance(database, user):
forbruk = 0
if user in database.personVareVerdi:
forbruk = sum([i for i in list(database.personVareVerdi[user].values())])
forbruk = sum(list(database.personVareVerdi[user].values()))
print("totalt kjøpt for: ", forbruk, end=" ")
if user in database.personNegTransactions:
print("kr, totalt lagt til: ", -database.personNegTransactions[user], end=" ")
@@ -453,9 +454,9 @@ def printGlobal(database, dateLine, n):
"Det er solgt varer til en verdi av: ",
sum(database.globalDatoForbruk),
"kr, det er lagt til",
-sum([i for i in list(database.personNegTransactions.values())]),
-sum(list(database.personNegTransactions.values())),
"og tatt fra",
sum([i for i in list(database.personPosTransactions.values())]),
sum(list(database.personPosTransactions.values())),
end=" ",
)
print(
@@ -470,12 +471,12 @@ def alt4menuTextOnly(database, dateLine, sql_session: Session):
n = 10
while 1:
print(
"\n1: user-statistics, 2: product-statistics, 3:global-statistics, n: adjust amount of data shown q:quit"
"\n1: user-statistics, 2: product-statistics, 3:global-statistics, n: adjust amount of data shown q:quit",
)
inp = input("")
if inp == "q":
break
elif inp == "1":
if inp == "1":
try:
printUser(database, dateLine, getUser(sql_session), n)
except:
@@ -505,5 +506,5 @@ def statisticsTextOnly(sql_session: Session):
database, dateLine = buildDatabaseFromDb(inputType, product, user, sql_session)
elif inp == "0" or inp == "":
database, dateLine = buildDatabaseFromFile("default.dibblerlog", inputType, product, user)
if not inp == "q":
if inp != "q":
alt4menuTextOnly(database, dateLine, sql_session)

View File

@@ -4,7 +4,7 @@ from pathlib import Path
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from dibbler.conf import load_config, config_db_string
from dibbler.conf import config_db_string, load_config
parser = argparse.ArgumentParser()

View File

@@ -26,28 +26,28 @@ __all__ = [
from .addstock import AddStockMenu
from .buymenu import BuyMenu
from .editing import (
AddUserMenu,
EditUserMenu,
AddProductMenu,
EditProductMenu,
AddUserMenu,
AdjustStockMenu,
CleanupStockMenu,
EditProductMenu,
EditUserMenu,
)
from .faq import FAQMenu
from .helpermenus import Menu
from .mainmenu import MainMenu
from .miscmenus import (
ProductSearchMenu,
TransferMenu,
AdjustCreditMenu,
UserListMenu,
ShowUserMenu,
ProductListMenu,
ProductSearchMenu,
ShowUserMenu,
TransferMenu,
UserListMenu,
)
from .printermenu import PrintLabelMenu
from .stats import (
ProductPopularityMenu,
ProductRevenueMenu,
BalanceMenu,
LoggedStatisticsMenu,
ProductPopularityMenu,
ProductRevenueMenu,
)

View File

@@ -139,10 +139,10 @@ much money you're due in credits for the purchase when prompted.\n"""
old_price = product.price
old_hidden = product.hidden
product.price = int(
ceil(float(value) / (max(product.stock, 0) + self.products[product][0]))
ceil(float(value) / (max(product.stock, 0) + self.products[product][0])),
)
product.stock = max(
self.products[product][0], product.stock + self.products[product][0]
self.products[product][0], product.stock + self.products[product][0],
)
product.hidden = False
print(

View File

@@ -64,7 +64,7 @@ When finished, write an empty line to confirm the purchase.\n"""
print("***********************************************************************")
print("")
print(
f"USER {user.name} HAS LOWER CREDIT THAN {config['limits']['low_credit_warning_limit']:d}."
f"USER {user.name} HAS LOWER CREDIT THAN {config['limits']['low_credit_warning_limit']:d}.",
)
print("THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH.")
print("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.")
@@ -74,8 +74,7 @@ When finished, write an empty line to confirm the purchase.\n"""
if timeout:
print("THIS PURCHASE WILL AUTOMATICALLY BE PERFORMED IN 3 MINUTES!")
return self.confirm(prompt=">", default=True, timeout=180)
else:
return self.confirm(prompt=">", default=True)
return self.confirm(prompt=">", default=True)
def add_thing_to_purchase(
self,
@@ -145,7 +144,7 @@ When finished, write an empty line to confirm the purchase.\n"""
True,
True,
): "Enter more products or users, or an empty line to confirm",
}[(len(self.purchase.transactions) > 0, len(self.purchase.entries) > 0)]
}[(len(self.purchase.transactions) > 0, len(self.purchase.entries) > 0)],
)
# Read in a 'thing' (product or user):
@@ -163,16 +162,15 @@ When finished, write an empty line to confirm the purchase.\n"""
if thing is None:
if not self.complete_input():
if self.confirm(
"Not enough information entered. Abort purchase?", default=True
"Not enough information entered. Abort purchase?", default=True,
):
return False
continue
break
else:
# once we get something in the
# purchase, we want to protect the
# user from accidentally killing it
self.exit_confirm_msg = "Abort purchase?"
# once we get something in the
# purchase, we want to protect the
# user from accidentally killing it
self.exit_confirm_msg = "Abort purchase?"
# Add the thing to our purchase object:
if not self.add_thing_to_purchase(thing, amount=num):
@@ -221,7 +219,7 @@ When finished, write an empty line to confirm the purchase.\n"""
string += "(empty)"
else:
string += ", ".join(
[t.user.name + ("*" if not self.credit_check(t.user) else "") for t in transactions]
[t.user.name + ("*" if not self.credit_check(t.user) else "") for t in transactions],
)
string += "\n products: "
if len(entries) == 0:
@@ -229,7 +227,7 @@ When finished, write an empty line to confirm the purchase.\n"""
else:
string += "\n "
string += "\n ".join(
[f"{e.amount:d}x {e.product.name} ({e.product.price:d} kr)" for e in entries]
[f"{e.amount:d}x {e.product.name} ({e.product.price:d} kr)" for e in entries],
)
if len(transactions) > 1:
string += f"\n price per person: {self.purchase.price_per_transaction():d} kr"

View File

@@ -1,8 +1,8 @@
import sqlalchemy
from sqlalchemy.orm import Session
from dibbler.models import User, Product
from dibbler.models import Product, User
from .helpermenus import Menu, Selector
__all__ = [

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from sqlalchemy.orm import Session
from .helpermenus import Menu, MessageMenu

View File

@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
import re
import sys
from collections.abc import Callable, Iterable
from select import select
from typing import Any, Callable, Iterable, Literal, Self
from typing import Any, Literal, Self
from sqlalchemy.orm import Session
@@ -24,7 +24,7 @@ class ExitMenuException(Exception):
pass
class Menu(object):
class Menu:
name: str
sql_session: Session
items: list[Self | tuple | str]
@@ -111,10 +111,9 @@ class Menu(object):
def item_name(self, i: int) -> str:
if self.item_is_submenu(i):
return self.items[i].name
elif isinstance(self.items[i], tuple):
if isinstance(self.items[i], tuple):
return self.items[i][1]
else:
return self.items[i]
return self.items[i]
def item_value(self, i: int):
if isinstance(self.items[i], tuple):
@@ -189,7 +188,7 @@ class Menu(object):
):
if length_range[0] and length_range[1]:
print(
f"Value must have length in range [{length_range[0]:d}, {length_range[1]:d}]"
f"Value must have length in range [{length_range[0]:d}, {length_range[1]:d}]",
)
elif length_range[0]:
print(f"Value must have length at least {length_range[0]:d}")
@@ -231,7 +230,7 @@ class Menu(object):
else:
if result.isdigit():
choice = int(result)
if choice == 0 and 10 <= number_of_choices:
if choice == 0 and number_of_choices >= 10:
return 10
if 0 < choice <= number_of_choices:
return choice
@@ -342,29 +341,28 @@ class Menu(object):
search_lst = search_str.split(" ")
if search_str == "" and empty_input_permitted:
return None
else:
result = self.search_for_thing(
search_str,
permitted_things,
add_nonexisting,
find_hidden_products,
)
num = 1
result = self.search_for_thing(
search_str,
permitted_things,
add_nonexisting,
find_hidden_products,
)
num = 1
if (result is None) and (len(search_lst) > 1):
print('Interpreting input as "<number> <product>"')
try:
num = int(search_lst[0])
result = self.search_for_thing(
" ".join(search_lst[1:]),
permitted_things,
add_nonexisting,
find_hidden_products,
)
# Her kan det legges inn en except ValueError,
# men da blir det fort mye plaging av brukeren
except Exception as e:
print(e)
if (result is None) and (len(search_lst) > 1):
print('Interpreting input as "<number> <product>"')
try:
num = int(search_lst[0])
result = self.search_for_thing(
" ".join(search_lst[1:]),
permitted_things,
add_nonexisting,
find_hidden_products,
)
# Her kan det legges inn en except ValueError,
# men da blir det fort mye plaging av brukeren
except Exception as e:
print(e)
return result, num
def search_for_thing(
@@ -544,7 +542,7 @@ class Menu(object):
of money PVVVV owes the user. This value decreases with the
appropriate amount when you register a purchase, and you may increase
it by putting money in the box and using the "Adjust credit" menu.
"""
""",
)
def local_help(self):
@@ -627,17 +625,16 @@ class ConfirmMenu(Menu):
options = {True: "[y]/n", False: "y/[n]", None: "y/n"}[self.default]
while True:
result = self.input_str(
f"{self.prompt} ({options})", end_prompt=": ", timeout=self.timeout
f"{self.prompt} ({options})", end_prompt=": ", timeout=self.timeout,
)
result = result.lower().strip()
if result in ["y", "yes"]:
return True
elif result in ["n", "no"]:
if result in ["n", "no"]:
return False
elif self.default is not None and result == "":
if self.default is not None and result == "":
return self.default
else:
print("Please answer yes or no")
print("Please answer yes or no")
class Selector(Menu):

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import os
import random
import sys
@@ -48,18 +47,18 @@ class MainMenu(Menu):
restart()
pass
return True
elif result == "c":
if result == "c":
os.system(
'echo -e "\033['
+ str(random.randint(40, 49))
+ ";"
+ str(random.randint(30, 37))
+ ';5m"'
+ ';5m"',
)
os.system("clear")
self.show_context()
return True
elif result == "cs":
if result == "cs":
os.system('echo -e "\033[0m"')
os.system("clear")
self.show_context()

View File

@@ -2,8 +2,8 @@ import sqlalchemy
from sqlalchemy.orm import Session
from dibbler.conf import config
from dibbler.models import Transaction, Product, User
from dibbler.lib.helpers import less
from dibbler.models import Product, Transaction, User
from .helpermenus import Menu, Selector
@@ -90,10 +90,7 @@ class ShowUserMenu(Menu):
if t.purchase:
products = []
for entry in t.purchase.entries:
if abs(entry.amount) != 1:
amount = f"{abs(entry.amount)}x "
else:
amount = ""
amount = f"{abs(entry.amount)}x " if abs(entry.amount) != 1 else ""
product = f"{amount}{entry.product.name}"
products.append(product)
string += "purchase ("
@@ -215,14 +212,11 @@ class ProductSearchMenu(Menu):
self.print_header()
self.set_context("Enter (part of) product name or bar code")
product = self.input_product()
print(
"Result: %s, price: %d kr, bar code: %s, stock: %d, hidden: %s"
% (
product.name,
product.price,
product.bar_code,
product.stock,
("Y" if product.hidden else "N"),
)
)
print(", ".join([
f"Result: {product.name}",
f"price: {product.price} kr",
f"bar code: {product.bar_code}",
f"stock: {product.stock}",
f"hidden: {'Y' if product.hidden else 'N'}",
]))
# self.pause()

View File

@@ -1,11 +1,7 @@
import re
from sqlalchemy.orm import Session
from dibbler.conf import config
from dibbler.models import Product, User
# from dibbler.lib.printer_helpers import print_bar_code, print_name_label
from .helpermenus import Menu

View File

@@ -2,8 +2,8 @@ from sqlalchemy import desc, func
from sqlalchemy.orm import Session
from dibbler.lib.helpers import less
from dibbler.models import PurchaseEntry, Product, User
from dibbler.lib.statistikkHelpers import statisticsTextOnly
from dibbler.models import Product, PurchaseEntry, User
from .helpermenus import Menu

View File

@@ -18,7 +18,7 @@ class Base(DeclarativeBase):
"ck": "ck_%(table_name)s_`%(constraint_name)s`",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
},
)
@declared_attr.directive
@@ -38,7 +38,7 @@ class Base(DeclarativeBase):
isinstance(v, InstrumentedList),
isinstance(v, InstrumentedSet),
isinstance(v, InstrumentedDict),
]
],
)
)
return f"<{self.__class__.__name__}({columns})>"

View File

@@ -1,4 +1,5 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import (

View File

@@ -43,8 +43,7 @@ class Purchase(Base):
def price_per_transaction(self, round_up: bool = True) -> int:
if round_up:
return int(math.ceil(float(self.price) / len(self.transactions)))
else:
return int(math.floor(float(self.price) / len(self.transactions)))
return int(math.floor(float(self.price) / len(self.transactions)))
def set_price(self, round_up: bool = True) -> None:
self.price = 0

View File

@@ -1,9 +1,10 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import (
Integer,
ForeignKey,
Integer,
)
from sqlalchemy.orm import (
Mapped,
@@ -27,8 +28,8 @@ class PurchaseEntry(Base):
product_id: Mapped[int] = mapped_column(ForeignKey("products.product_id"))
purchase_id: Mapped[int] = mapped_column(ForeignKey("purchases.id"))
product: Mapped[Product] = relationship(back_populates='purchases', lazy="joined")
purchase: Mapped[Purchase] = relationship(back_populates='entries', lazy="joined")
product: Mapped[Product] = relationship(back_populates="purchases", lazy="joined")
purchase: Mapped[Purchase] = relationship(back_populates="entries", lazy="joined")
def __init__(self, purchase, product, amount):
self.product = product

View File

@@ -1,7 +1,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from datetime import datetime
from typing import TYPE_CHECKING
from sqlalchemy import (
DateTime,
@@ -18,8 +18,8 @@ from sqlalchemy.orm import (
from .Base import Base
if TYPE_CHECKING:
from .User import User
from .Purchase import Purchase
from .User import User
class Transaction(Base):
@@ -36,7 +36,7 @@ class Transaction(Base):
purchase_id: Mapped[int | None] = mapped_column(ForeignKey("purchases.id"))
user: Mapped[User] = relationship(lazy="joined")
purchase: Mapped[Purchase] = relationship(back_populates='transactions', lazy="joined")
purchase: Mapped[Purchase] = relationship(back_populates="transactions", lazy="joined")
def __init__(
self,

View File

@@ -1,9 +1,10 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import (
Integer,
ForeignKey,
Integer,
)
from sqlalchemy.orm import (
Mapped,
@@ -14,8 +15,8 @@ from sqlalchemy.orm import (
from .Base import Base
if TYPE_CHECKING:
from .User import User
from .Product import Product
from .User import User
class UserProducts(Base):

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import random
import sys
@@ -91,7 +90,9 @@ def main(sql_session: Session):
exit_confirm_msg="Really quit Dibbler?",
)
if not config["general"]["quit_allowed"]:
main_menu.exit_disallowed_msg = "You can check out any time you like, but you can never leave."
main_menu.exit_disallowed_msg = (
"You can check out any time you like, but you can never leave."
)
while True:
# noinspection PyBroadException
try:

View File

@@ -1,5 +1,4 @@
import json
from pathlib import Path
from sqlalchemy.orm import Session
@@ -21,7 +20,7 @@ def main(sql_session: Session):
product_items = []
user_items = []
with open(JSON_FILE) as f:
with Path.open(JSON_FILE) as f:
json_obj = json.load(f)
for product in json_obj["products"]: