Replace configparser with tomllib
This commit is contained in:
12
README.md
12
README.md
@@ -20,9 +20,9 @@ Installer python, og lag og aktiver et venv. Installer så avhengighetene med `p
|
||||
Deretter kan du kjøre programmet med
|
||||
|
||||
```console
|
||||
python -m dibbler -c example-config.ini create-db
|
||||
python -m dibbler -c example-config.ini seed-data
|
||||
python -m dibbler -c example-config.ini loop
|
||||
python -m dibbler -c example-config.toml create-db
|
||||
python -m dibbler -c example-config.toml seed-data
|
||||
python -m dibbler -c example-config.toml loop
|
||||
```
|
||||
|
||||
## Nix
|
||||
@@ -46,7 +46,7 @@ Du kan også bygge pakken manuelt, eller kjøre den direkte:
|
||||
```console
|
||||
nix build .#dibbler
|
||||
|
||||
nix run .# -- --config example-config.ini create-db
|
||||
nix run .# -- --config example-config.ini seed-data
|
||||
nix run .# -- --config example-config.ini loop
|
||||
nix run .# -- --config example-config.toml create-db
|
||||
nix run .# -- --config example-config.toml seed-data
|
||||
nix run .# -- --config example-config.toml loop
|
||||
```
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
# This module is supposed to act as a singleton and be filled
|
||||
# with config variables by cli.py
|
||||
from typing import Any
|
||||
from pathlib import Path
|
||||
import tomllib
|
||||
import os
|
||||
import sys
|
||||
|
||||
import configparser
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
DEFAULT_CONFIG_PATH = Path('/etc/dibbler/dibbler.conf')
|
||||
DEFAULT_CONFIG_PATH = Path('/etc/dibbler/dibbler.toml')
|
||||
|
||||
def default_config_path_submissive_and_readable() -> bool:
|
||||
return DEFAULT_CONFIG_PATH.is_file() and any(
|
||||
@@ -23,3 +20,17 @@ def default_config_path_submissive_and_readable() -> bool:
|
||||
(DEFAULT_CONFIG_PATH.stat().st_mode & 0o004),
|
||||
]
|
||||
)
|
||||
|
||||
config: dict[str, dict[str, Any]] = dict()
|
||||
|
||||
def load_config(config_path: Path | None = None):
|
||||
global config
|
||||
if config_path is not None:
|
||||
with Path(config_path).open("rb") as file:
|
||||
config = tomllib.load(file)
|
||||
elif default_config_path_submissive_and_readable():
|
||||
with DEFAULT_CONFIG_PATH.open("rb") as file:
|
||||
config = tomllib.load(file)
|
||||
else:
|
||||
print("Could not read config file, it was neither provided nor readable in default location", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
from pathlib import Path
|
||||
from sqlalchemy.engine.base import Engine
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from dibbler.conf import config
|
||||
|
||||
database_url: str | None = None
|
||||
|
||||
if (url := config.get("database", "url")) is not None:
|
||||
database_url = url
|
||||
elif (url_file := config.get("database", "url_file")) is not None:
|
||||
with Path(url_file).open() as file:
|
||||
database_url = file.read().strip()
|
||||
|
||||
assert database_url is not None, "Database URL must be specified in config"
|
||||
|
||||
engine = create_engine(database_url)
|
||||
Session = sessionmaker(bind=engine)
|
||||
engine: Engine = None
|
||||
session: Session = None
|
||||
|
||||
@@ -6,13 +6,13 @@ from collections import defaultdict
|
||||
|
||||
from .helpers import *
|
||||
from ..models import Transaction
|
||||
from ..db import Session
|
||||
from ..db import session as create_session
|
||||
|
||||
|
||||
def getUser():
|
||||
while 1:
|
||||
string = input("user? ")
|
||||
session = Session()
|
||||
session = create_session()
|
||||
user = search_user(string, session)
|
||||
session.close()
|
||||
if not isinstance(user, list):
|
||||
@@ -40,7 +40,7 @@ def getUser():
|
||||
def getProduct():
|
||||
while 1:
|
||||
string = input("product? ")
|
||||
session = Session()
|
||||
session = create_session()
|
||||
product = search_product(string, session)
|
||||
session.close()
|
||||
if not isinstance(product, list):
|
||||
@@ -242,7 +242,7 @@ def buildDatabaseFromDb(inputType, inputProduct, inputUser):
|
||||
sdate = input("enter start date (yyyy-mm-dd)? ")
|
||||
edate = input("enter end date (yyyy-mm-dd)? ")
|
||||
print("building database...")
|
||||
session = Session()
|
||||
session = create_session()
|
||||
transaction_list = session.query(Transaction).all()
|
||||
inputLine = InputLine(inputUser, inputProduct, inputType)
|
||||
startDate = getDateDb(transaction_list[0].time, sdate)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from dibbler.conf import DEFAULT_CONFIG_PATH, config, default_config_path_submissive_and_readable
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from dibbler.conf import load_config
|
||||
from dibbler.db import engine, session
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
@@ -12,7 +15,7 @@ parser.add_argument(
|
||||
help="Path to the config file",
|
||||
type=Path,
|
||||
metavar="FILE",
|
||||
default="config.ini",
|
||||
required=False,
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(
|
||||
@@ -29,12 +32,13 @@ subparsers.add_parser("seed-data", help="Fill with mock data")
|
||||
def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.config is not None:
|
||||
config.read(args.config)
|
||||
elif default_config_path_submissive_and_readable():
|
||||
config.read(DEFAULT_CONFIG_PATH)
|
||||
else:
|
||||
print("Could not read config file, it was neither provided nor readable in default location", file=sys.stderr)
|
||||
load_config(args.config)
|
||||
|
||||
from dibbler.conf import config
|
||||
|
||||
global engine, session
|
||||
engine = create_engine(config['database']['url'])
|
||||
session = sessionmaker(bind=engine)
|
||||
|
||||
if args.subcommand == "loop":
|
||||
import dibbler.subcommands.loop as loop
|
||||
|
||||
@@ -37,7 +37,7 @@ When finished, write an empty line to confirm the purchase.\n"""
|
||||
"""
|
||||
assert isinstance(user, User)
|
||||
|
||||
return user.credit > config.getint("limits", "low_credit_warning_limit")
|
||||
return user.credit > config["limits"]["low_credit_warning_limit"]
|
||||
|
||||
def low_credit_warning(self, user, timeout=False):
|
||||
assert isinstance(user, User)
|
||||
@@ -58,7 +58,7 @@ When finished, write an empty line to confirm the purchase.\n"""
|
||||
print("***********************************************************************")
|
||||
print("")
|
||||
print(
|
||||
f"USER {user.name} HAS LOWER CREDIT THAN {config.getint('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.")
|
||||
@@ -178,9 +178,9 @@ When finished, write an empty line to confirm the purchase.\n"""
|
||||
for t in self.purchase.transactions:
|
||||
if not t.user.is_anonymous():
|
||||
print(f"User {t.user.name}'s credit is now {t.user.credit:d} kr")
|
||||
if t.user.credit < config.getint("limits", "low_credit_warning_limit"):
|
||||
if t.user.credit < config["limits"]["low_credit_warning_limit"]:
|
||||
print(
|
||||
f"USER {t.user.name} HAS LOWER CREDIT THAN {config.getint('limits', 'low_credit_warning_limit'):d},",
|
||||
f"USER {t.user.name} HAS LOWER CREDIT THAN {config['limits']['low_credit_warning_limit']:d},",
|
||||
"AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.",
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import re
|
||||
import sys
|
||||
from select import select
|
||||
|
||||
from dibbler.db import Session
|
||||
from dibbler.db import session as create_session
|
||||
from dibbler.models import User
|
||||
from dibbler.lib.helpers import (
|
||||
search_user,
|
||||
@@ -485,7 +485,7 @@ class Menu(object):
|
||||
self.set_context(None)
|
||||
try:
|
||||
if self.uses_db and not self.session:
|
||||
self.session = Session()
|
||||
self.session = create_session()
|
||||
return self._execute(**kwargs)
|
||||
except ExitMenu:
|
||||
self.at_exit()
|
||||
|
||||
@@ -3,7 +3,7 @@ import os
|
||||
import random
|
||||
import sys
|
||||
|
||||
from dibbler.db import Session
|
||||
from dibbler.db import session as create_session
|
||||
|
||||
from .buymenu import BuyMenu
|
||||
from .faq import FAQMenu
|
||||
@@ -28,7 +28,7 @@ class MainMenu(Menu):
|
||||
else:
|
||||
num = 1
|
||||
item_name = in_str
|
||||
buy_menu = BuyMenu(Session())
|
||||
buy_menu = BuyMenu(create_session())
|
||||
thing = buy_menu.search_for_thing(item_name, find_hidden_products=False)
|
||||
if thing:
|
||||
buy_menu.execute(initial_contents=[(thing, num)])
|
||||
|
||||
@@ -56,7 +56,7 @@ class ShowUserMenu(Menu):
|
||||
(
|
||||
"transactions",
|
||||
"Recent transactions (List of last "
|
||||
+ str(config.getint("limits", "user_recent_transaction_limit"))
|
||||
+ str(config["limits"]["user_recent_transaction_limit"])
|
||||
+ ")",
|
||||
),
|
||||
("products", f"Which products {user.name} has bought, and how many"),
|
||||
@@ -65,7 +65,7 @@ class ShowUserMenu(Menu):
|
||||
)
|
||||
what = selector.execute()
|
||||
if what == "transactions":
|
||||
self.print_transactions(user, config.getint("limits", "user_recent_transaction_limit"))
|
||||
self.print_transactions(user, config["limits"]["user_recent_transaction_limit"])
|
||||
elif what == "products":
|
||||
self.print_purchased_products(user)
|
||||
elif what == "transactions-all":
|
||||
|
||||
@@ -32,14 +32,14 @@ Put it up somewhere in the vicinity.
|
||||
thing.bar_code,
|
||||
thing.name,
|
||||
barcode_type=bar_type,
|
||||
rotate=config.getboolean("printer", "rotate"),
|
||||
rotate=config["printer"]["rotate"],
|
||||
printer_type="QL-700",
|
||||
label_type=config.get("printer", "label_type"),
|
||||
)
|
||||
elif isinstance(thing, User):
|
||||
print_name_label(
|
||||
text=thing.name,
|
||||
label_type=config.get("printer", "label_type"),
|
||||
rotate=config.getboolean("printer", "rotate"),
|
||||
label_type=config["printer"]["label_type"],
|
||||
rotate=config["printer"]["rotate"],
|
||||
printer_type="QL-700",
|
||||
)
|
||||
|
||||
@@ -13,10 +13,10 @@ random.seed()
|
||||
|
||||
|
||||
def main():
|
||||
if not config.getboolean("general", "stop_allowed"):
|
||||
if not config["general"]["stop_allowed"]:
|
||||
signal.signal(signal.SIGQUIT, signal.SIG_IGN)
|
||||
|
||||
if not config.getboolean("general", "stop_allowed"):
|
||||
if not config["general"]["stop_allowed"]:
|
||||
signal.signal(signal.SIGTSTP, signal.SIG_IGN)
|
||||
|
||||
main = MainMenu(
|
||||
@@ -56,7 +56,7 @@ def main():
|
||||
exit_msg="happy happy joy joy",
|
||||
exit_confirm_msg="Really quit Dibbler?",
|
||||
)
|
||||
if not config.getboolean("general", "quit_allowed"):
|
||||
if not config["general"]["quit_allowed"]:
|
||||
main.exit_disallowed_msg = "You can check out any time you like, but you can never leave."
|
||||
while True:
|
||||
# noinspection PyBroadException
|
||||
@@ -68,7 +68,7 @@ def main():
|
||||
except:
|
||||
print("Something went wrong.")
|
||||
print(f"{sys.exc_info()[0]}: {sys.exc_info()[1]}")
|
||||
if config.getboolean("general", "show_tracebacks"):
|
||||
if config["general"]["show_tracebacks"]:
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
else:
|
||||
break
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import json
|
||||
from dibbler.db import Session
|
||||
from dibbler.db import session as create_session
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
@@ -17,7 +17,7 @@ def clear_db(session):
|
||||
|
||||
|
||||
def main():
|
||||
session = Session()
|
||||
session = create_session()
|
||||
clear_db(session)
|
||||
product_items = []
|
||||
user_items = []
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from dibbler.db import Session
|
||||
from dibbler.db import session as create_session
|
||||
from dibbler.models import User
|
||||
|
||||
|
||||
def main():
|
||||
# Start an SQL session
|
||||
session = Session()
|
||||
session = create_session()
|
||||
# Let's find all users with a negative credit
|
||||
slabbedasker = session.query(User).filter(User.credit < 0).all()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{ config, pkgs, lib, ... }: let
|
||||
cfg = config.services.dibbler;
|
||||
|
||||
format = pkgs.formats.ini { };
|
||||
format = pkgs.formats.toml { };
|
||||
in {
|
||||
options.services.dibbler = {
|
||||
enable = lib.mkEnableOption "dibbler, the little kiosk computer";
|
||||
@@ -58,7 +58,7 @@ in {
|
||||
|
||||
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||
{
|
||||
services.dibbler.settings = lib.pipe ../example-config.ini [
|
||||
services.dibbler.settings = lib.pipe ../example-config.toml [
|
||||
builtins.readFile
|
||||
builtins.fromTOML
|
||||
(lib.mapAttrsRecursive (_: lib.mkDefault))
|
||||
@@ -67,7 +67,7 @@ in {
|
||||
{
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.etc."dibbler/dibbler.conf".source = format.generate "dibbler.conf" cfg.settings;
|
||||
environment.etc."dibbler/dibbler.toml".source = format.generate "dibbler.toml" cfg.settings;
|
||||
|
||||
users = {
|
||||
users.dibbler = {
|
||||
@@ -97,7 +97,7 @@ in {
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${lib.getExe cfg.package} --config /etc/dibbler/dibbler.conf create-db";
|
||||
ExecStart = "${lib.getExe cfg.package} --config /etc/dibbler/dibbler.toml create-db";
|
||||
ExecStartPost = "${lib.getExe' pkgs.coreutils "touch"} /var/lib/dibbler/.db-setup-done";
|
||||
StateDirectory = "dibbler";
|
||||
|
||||
@@ -163,7 +163,7 @@ in {
|
||||
];
|
||||
|
||||
dibblerArgs = lib.cli.toCommandLineShellGNU { } {
|
||||
config = "/etc/dibbler/dibbler.conf";
|
||||
config = "/etc/dibbler/dibbler.toml";
|
||||
};
|
||||
|
||||
in "${lib.getExe cfg.screenPackage} ${screenArgs} ${lib.getExe cfg.package} ${dibblerArgs} loop";
|
||||
|
||||
Reference in New Issue
Block a user