From 751a7ad9e519a89077f5ff58f84c4b046108775d Mon Sep 17 00:00:00 2001 From: Kumi Date: Tue, 29 Aug 2023 18:58:32 +0200 Subject: [PATCH] Update version to 0.2.2, add DHL tracking provider, and improve config file generation and loading - Change version in pyproject.toml to 0.2.2 - Add DHL tracking provider to README.md - Update README.md with instructions for generating a config file - Improve config file generation in __main__.py - Load config file in Tracker class - Update start and start_async methods in Tracker class to accept an optional config file path --- README.md | 5 +++ pyproject.toml | 2 +- src/trackbert/__main__.py | 44 +++++++++++++++---- src/trackbert/classes/tracker.py | 25 ++++++++--- .../trackbert/config.dist.ini | 0 5 files changed, 59 insertions(+), 17 deletions(-) rename config.dist.ini => src/trackbert/config.dist.ini (100%) diff --git a/README.md b/README.md index e08bd8e..f1d1847 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Status information is stored in a SQLite database. - [Austrian Post](https://www.post.at) - [GLS](https://gls-group.eu) - [FedEx](https://www.fedex.com) (requires an API key, see [FedEx Developer Resource Center](https://www.fedex.com/en-us/developer.html)) +- [DHL](https://www.dhl.com) (requires an API key, see [DHL Developer Portal](https://developer.dhl.com/)) More tracking providers can be added easily by subclassing `trackbert.trackers.base.BaseTracker`. This should be relatively self-explanatory if you look at the existing implementations. Pull requests are welcome! @@ -43,6 +44,10 @@ First, assure that the virtual environment is activated: source venv/bin/activate ``` +If you need to create a new config file, run `trackbert -g`. You need this if +you want to provide API keys required for KeyDelivery or some of the other +tracking providers. + To add a new shipment, run `trackbert --tracking-number --carrier `. Find the required carrier ID in the [KeyDelivery API management](https://app.kd100.com/api-management). To run the main loop, run `trackbert`. This will check the status of all shipments every 5 minutes, and print the status to the console. If the status of a shipment changes, you will get a desktop notification. diff --git a/pyproject.toml b/pyproject.toml index 5b316ac..826be10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "trackbert" -version = "0.2.1" +version = "0.2.2" authors = [ { name="Kumi Mitterer", email="trackbert@kumi.email" }, ] diff --git a/src/trackbert/__main__.py b/src/trackbert/__main__.py index 38513db..4745271 100644 --- a/src/trackbert/__main__.py +++ b/src/trackbert/__main__.py @@ -6,13 +6,18 @@ import subprocess import argparse import logging import asyncio + from typing import Tuple, Never, Optional from .classes.database import Database from .classes.tracker import Tracker + def main(): parser = argparse.ArgumentParser() + + # Arguments related to the tracker + parser.add_argument("--tracking-number", "-n", type=str, required=False) parser.add_argument("--carrier", "-c", type=str, required=False) parser.add_argument("--description", "-d", type=str, required=False) @@ -30,17 +35,37 @@ def main(): required=False, help="Disable existing shipment", ) - parser.add_argument( - "--timeout", - "-t", - type=int, - required=False, - default=30, - help="Notification timeout in seconds", - ) + + # Arguments related to the config file + + parser.add_argument("--generate-config", action="store_true", required=False) + parser.add_argument("--config-file", "-C", type=str, required=False) args = parser.parse_args() + # Generate config file if requested + + config_file = Path(args.config_file or "config.ini") + + if args.generate_config: + if config_file.exists(): + print(f"Config file {config_file} already exists.") + exit(1) + + with Path(config_file).open("w") as config_file_obj: + template = Path(__file__).parent / "config.dist.ini" + config_file_obj.write(template.read_text()) + print(f"Generated config file {config_file}") + exit(0) + + # Load config file + + if not config_file.exists(): + print(f"Config file {config_file} does not exist. Use -g to generate it.") + exit(1) + + + db = Database("sqlite:///trackbert.db") if args.tracking_number is not None and args.carrier is not None: @@ -76,5 +101,6 @@ def main(): tracker = Tracker() asyncio.run(tracker.start_async()) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/trackbert/classes/tracker.py b/src/trackbert/classes/tracker.py index 329c7df..c00637b 100644 --- a/src/trackbert/classes/tracker.py +++ b/src/trackbert/classes/tracker.py @@ -3,8 +3,11 @@ import subprocess import time import importlib import asyncio + from pathlib import Path from typing import Optional, Tuple, Never +from os import PathLike +from configparser import ConfigParser from .database import Database from ..trackers.base import BaseTracker @@ -46,7 +49,7 @@ class Tracker: for carrier, priority in carriers: self.apis.append((carrier, priority, api)) except: - logging.exception(f"Error loading tracker {name}") + logging.exception(f"Error loading tracker {api.stem}") def query_api(self, tracking_number: str, carrier: str) -> list: logging.debug(f"Querying API for {tracking_number} with carrier {carrier}") @@ -173,12 +176,20 @@ class Tracker: await asyncio.sleep(self.loop_interval) - def start(self): - self.db = Database("sqlite:///trackbert.db") + def _pre_start(self, config: Optional[PathLike] = None): + parser = ConfigParser() + parser.read(config or []) + + self.database_uri = parser.get("Trackbert", "database", fallback="sqlite:///trackbert.db") + self.db = Database(self.database_uri) + + self.loop_interval = parser.getint("Trackbert", "interval", fallback=60) self.notify("Trackbert", "Starting up") + + def start(self, config: Optional[PathLike] = None): + self._pre_start(config) self.start_loop() - async def start_async(self): - self.db = Database("sqlite:///trackbert.db") - self.notify("Trackbert", "Starting up") - await self.start_loop_async() + async def start_async(self, config: Optional[PathLike] = None): + self._pre_start(config) + await self.start_loop_async() \ No newline at end of file diff --git a/config.dist.ini b/src/trackbert/config.dist.ini similarity index 100% rename from config.dist.ini rename to src/trackbert/config.dist.ini