From 24217756f77cf9c87a712197a13faeeabc965d2d Mon Sep 17 00:00:00 2001 From: Patrick Kanzler <4189642+patkan@users.noreply.github.com> Date: Wed, 6 Sep 2023 00:05:38 +0200 Subject: [PATCH] 558 improve capabilities handling (#562) * add handling for missing capabilities file * improve documentation * Update doc/user/installation.rst --- doc/dev/repository.rst | 17 ++++++++++ doc/index.rst | 1 + doc/user/installation.rst | 14 ++++++++ src/escpos/capabilities.py | 36 ++++++++++++++++++--- test/test_load_module_missing_capability.py | 29 +++++++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 doc/dev/repository.rst create mode 100644 test/test_load_module_missing_capability.py diff --git a/doc/dev/repository.rst b/doc/dev/repository.rst new file mode 100644 index 0000000..b5d50ec --- /dev/null +++ b/doc/dev/repository.rst @@ -0,0 +1,17 @@ +.. _developer-manual-repository: + +Repository +========== + +:Last Reviewed: 2023-09-05 + +This project uses subprojects and retrieves its versioning +information from version control. +Therefore it is crucial that you follow these rules when +working with the project (e.g. for packaging a +development version). + +* Make sure that the git project is complete. A call to git status for example should succeed. +* Make sure that you have checked out all available subprojects. +* Proper initialization of submodules can be ensured with ``git submodule update --init --recursive`` + diff --git a/doc/index.rst b/doc/index.rst index 68e3d33..65021fb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -53,6 +53,7 @@ developers of this library. dev/release-process dev/contributing + dev/repository dev/changelog dev/todo diff --git a/doc/user/installation.rst b/doc/user/installation.rst index fd4d6f7..33a2dbb 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -29,6 +29,20 @@ The following installation options exist: * `win32`: install packages required for win32 printing (only Windows) * `cups`: install packages required for CUPS printing +Other installation methods +-------------------------- +Officially, no other installation methods are supplied. + +If you want to install nevertheless from another source, +please make sure that you have received the correct package +and that the capabilities data is properly integrated. +When packaging from source please read the developer +information in :ref:`developer-manual-repository`. + +If your packaging method breaks the resource system from setuptools, +it might be necessary to supply the path to the capabilities file: +:ref:`advanced-usage-change-capabilities-profile`. + Setup udev for USB-Printers --------------------------- 1. Get the *Product ID* and *Vendor ID* from the lsusb command 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")