558 improve capabilities handling (#562)

* add handling for missing capabilities file

* improve documentation

* Update doc/user/installation.rst
This commit is contained in:
Patrick Kanzler 2023-09-06 00:05:38 +02:00 committed by GitHub
parent e3e1500d35
commit 24217756f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 4 deletions

17
doc/dev/repository.rst Normal file
View File

@ -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``

View File

@ -53,6 +53,7 @@ developers of this library.
dev/release-process dev/release-process
dev/contributing dev/contributing
dev/repository
dev/changelog dev/changelog
dev/todo dev/todo

View File

@ -29,6 +29,20 @@ The following installation options exist:
* `win32`: install packages required for win32 printing (only Windows) * `win32`: install packages required for win32 printing (only Windows)
* `cups`: install packages required for CUPS printing * `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 Setup udev for USB-Printers
--------------------------- ---------------------------
1. Get the *Product ID* and *Vendor ID* from the lsusb command 1. Get the *Product ID* and *Vendor ID* from the lsusb command

View File

@ -50,14 +50,41 @@ if full_load:
logger.debug("Loading and pickling capabilities") logger.debug("Loading and pickling capabilities")
with open(capabilities_path) as cp, open(pickle_path, "wb") as pp: with open(capabilities_path) as cp, open(pickle_path, "wb") as pp:
CAPABILITIES = yaml.safe_load(cp) 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) pickle.dump(CAPABILITIES, pp, protocol=2)
logger.debug("Finished loading capabilities took %.2fs", time.time() - t0) logger.debug("Finished loading capabilities took %.2fs", time.time() - t0)
PROFILES: Dict[str, Any] = CAPABILITIES["profiles"]
class NotSupported(Exception): class NotSupported(Exception):
"""Raised if a requested feature is not supported by the printer profile.""" """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. database, then generate dynamically a class.
""" """
if name not in CLASS_CACHE: if name not in CLASS_CACHE:
profile_data = PROFILES[name] profiles: Dict[str, Any] = CAPABILITIES["profiles"]
profile_data = profiles[name]
profile_name = clean(name) profile_name = clean(name)
class_name = "{}{}Profile".format(profile_name[0].upper(), profile_name[1:]) class_name = "{}{}Profile".format(profile_name[0].upper(), profile_name[1:])
new_class = type(class_name, (BaseProfile,), {"profile_data": profile_data}) new_class = type(class_name, (BaseProfile,), {"profile_data": profile_data})

View File

@ -0,0 +1,29 @@
#!/usr/bin/python
"""basic test case that simulates an empty capability file
:author: `Patrick Kanzler <dev@pkanzler.de>`_
:organization: `python-escpos <https://github.com/python-escpos>`_
:copyright: Copyright (c) 2016 `python-escpos <https://github.com/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")