From 018812e7d5bb94dc2c86e36c46a1a726b46a9841 Mon Sep 17 00:00:00 2001 From: Patrick Kanzler Date: Tue, 5 Sep 2023 23:27:01 +0200 Subject: [PATCH] add handling for missing capabilities file --- src/escpos/capabilities.py | 36 ++++++++++++++++++--- test/test_load_module_missing_capability.py | 29 +++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 test/test_load_module_missing_capability.py diff --git a/src/escpos/capabilities.py b/src/escpos/capabilities.py index dcd7a64..a8057cd 100644 --- a/src/escpos/capabilities.py +++ b/src/escpos/capabilities.py @@ -50,14 +50,41 @@ if full_load: logger.debug("Loading and pickling capabilities") with open(capabilities_path) as cp, open(pickle_path, "wb") as pp: CAPABILITIES = yaml.safe_load(cp) + if not CAPABILITIES: + # yaml could not be loaded + print( + f"Capabilities yaml from {capabilities_path} could not be loaded.\n" + "This python package seems to be broken. If it has been installed " + "from official sources, please report an issue on GitHub.\n" + "Currently loaded capabilities:\n" + f"{CAPABILITIES}" + ) + CAPABILITIES = { + "profiles": { + "default": { + "name": "BrokenDefault", + "notes": "The integrated capabilities file could not be found and has been replaced.", + "codePages": {"0": "Broken"}, + "features": {}, + }, + }, + "encodings": { + "Broken": { + "name": "Broken", + "notes": "The configuration is broken.", + } + }, + } + print( + "Created a minimal backup profile, " + "many functionalities of the library will not work:\n" + f"{CAPABILITIES}" + ) pickle.dump(CAPABILITIES, pp, protocol=2) logger.debug("Finished loading capabilities took %.2fs", time.time() - t0) -PROFILES: Dict[str, Any] = CAPABILITIES["profiles"] - - class NotSupported(Exception): """Raised if a requested feature is not supported by the printer profile.""" @@ -128,7 +155,8 @@ def get_profile_class(name: str): database, then generate dynamically a class. """ if name not in CLASS_CACHE: - profile_data = PROFILES[name] + profiles: Dict[str, Any] = CAPABILITIES["profiles"] + profile_data = profiles[name] profile_name = clean(name) class_name = "{}{}Profile".format(profile_name[0].upper(), profile_name[1:]) new_class = type(class_name, (BaseProfile,), {"profile_data": profile_data}) diff --git a/test/test_load_module_missing_capability.py b/test/test_load_module_missing_capability.py new file mode 100644 index 0000000..c3bff7d --- /dev/null +++ b/test/test_load_module_missing_capability.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +"""basic test case that simulates an empty capability file + +:author: `Patrick Kanzler `_ +:organization: `python-escpos `_ +:copyright: Copyright (c) 2016 `python-escpos `_ +:license: MIT +""" + +import os +import tempfile + +import pytest + + +def test_instantiation(): + """test the instantiation of a escpos-printer class""" + # inject an environment variable that points to an empty capabilities file + os.environ["ESCPOS_CAPABILITIES_FILE"] = tempfile.NamedTemporaryFile().name + + import escpos.printer as printer + from escpos.exceptions import BarcodeTypeError + + # remove again the variable (so that no other tests are affected) + os.environ.pop("ESCPOS_CAPABILITIES_FILE") + + instance = printer.Dummy() + with pytest.raises(BarcodeTypeError): + instance.barcode("bc", "code")