mirror of
				https://github.com/python-escpos/python-escpos
				synced 2025-10-23 09:30:00 +00:00 
			
		
		
		
	558 improve capabilities handling (#562)
* add handling for missing capabilities file * improve documentation * Update doc/user/installation.rst
This commit is contained in:
		
							
								
								
									
										17
									
								
								doc/dev/repository.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								doc/dev/repository.rst
									
									
									
									
									
										Normal 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``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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})
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								test/test_load_module_missing_capability.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								test/test_load_module_missing_capability.py
									
									
									
									
									
										Normal 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")
 | 
				
			||||||
		Reference in New Issue
	
	Block a user