mirror of
				https://github.com/python-escpos/python-escpos
				synced 2025-10-23 09:30:00 +00:00 
			
		
		
		
	start removal of six and improve type annotation (#607)
* fix unfinished Python2 -> 3 translation * remove some six usage * annotate * fix regression in Six removal * mypy: self.enf is always defined * fix return type of cups.py * Usb idVendor/idProduct are integers * self.default_args is always defined * tweak usb_args, PEP589 is better * lp.py: reassure mypy * correctly cast call to CashDrawerError() * update CUPS test * add missing close() method in metaclass * document a bug in typeshed * query_status() returns bytes as seen in constants.py * remove more SIX usage * test examples too * remove type comment where type is annotated * adapt behavior of cups printer to match other implementations --------- Co-authored-by: Patrick Kanzler <dev@pkanzler.de> Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							06bdb56937
						
					
				
				
					commit
					66a2e78e16
				
			@@ -1,7 +1,7 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
"""python-escpos enables you to manipulate escpos-printers."""
 | 
			
		||||
 | 
			
		||||
__all__ = ["constants", "escpos", "exceptions", "printer"]
 | 
			
		||||
__all__ = ["constants", "escpos", "exceptions", "printer", "__version__"]
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from .version import version as __version__  # noqa
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ from tempfile import mkdtemp
 | 
			
		||||
from typing import Any, Dict, Optional, Type
 | 
			
		||||
 | 
			
		||||
import importlib_resources
 | 
			
		||||
import six
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
logging.basicConfig()
 | 
			
		||||
@@ -92,7 +91,7 @@ class NotSupported(Exception):
 | 
			
		||||
BARCODE_B = "barcodeB"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseProfile(object):
 | 
			
		||||
class BaseProfile:
 | 
			
		||||
    """This represents a printer profile.
 | 
			
		||||
 | 
			
		||||
    A printer profile knows about the number of columns, supported
 | 
			
		||||
@@ -111,20 +110,22 @@ class BaseProfile(object):
 | 
			
		||||
        Makes sure that the requested `font` is valid.
 | 
			
		||||
        """
 | 
			
		||||
        font = {"a": 0, "b": 1}.get(font, font)
 | 
			
		||||
        if not six.text_type(font) in self.fonts:
 | 
			
		||||
        if not str(font) in self.fonts:
 | 
			
		||||
            raise NotSupported(f'"{font}" is not a valid font in the current profile')
 | 
			
		||||
        return font
 | 
			
		||||
 | 
			
		||||
    def get_columns(self, font):
 | 
			
		||||
    def get_columns(self, font) -> int:
 | 
			
		||||
        """Return the number of columns for the given font."""
 | 
			
		||||
        font = self.get_font(font)
 | 
			
		||||
        return self.fonts[six.text_type(font)]["columns"]
 | 
			
		||||
        columns = self.fonts[str(font)]["columns"]
 | 
			
		||||
        assert type(columns) is int
 | 
			
		||||
        return columns
 | 
			
		||||
 | 
			
		||||
    def supports(self, feature):
 | 
			
		||||
    def supports(self, feature) -> bool:
 | 
			
		||||
        """Return true/false for the given feature."""
 | 
			
		||||
        return self.features.get(feature)
 | 
			
		||||
 | 
			
		||||
    def get_code_pages(self):
 | 
			
		||||
    def get_code_pages(self) -> Dict[str, int]:
 | 
			
		||||
        """Return the support code pages as a ``{name: index}`` dict."""
 | 
			
		||||
        return {v: k for k, v in self.codePages.items()}
 | 
			
		||||
 | 
			
		||||
@@ -161,7 +162,7 @@ def get_profile_class(name: str) -> Type[BaseProfile]:
 | 
			
		||||
    return CLASS_CACHE[name]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def clean(s):
 | 
			
		||||
def clean(s: str) -> str:
 | 
			
		||||
    """Clean profile name."""
 | 
			
		||||
    # Remove invalid characters
 | 
			
		||||
    s = re.sub("[^0-9a-zA-Z_]", "", s)
 | 
			
		||||
@@ -180,14 +181,14 @@ class Profile(ProfileBaseClass):
 | 
			
		||||
    For users, who want to provide their own profile.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, columns=None, features=None):
 | 
			
		||||
    def __init__(self, columns: Optional[int] = None, features=None) -> None:
 | 
			
		||||
        """Initialize profile."""
 | 
			
		||||
        super(Profile, self).__init__()
 | 
			
		||||
 | 
			
		||||
        self.columns = columns
 | 
			
		||||
        self.features = features or {}
 | 
			
		||||
 | 
			
		||||
    def get_columns(self, font):
 | 
			
		||||
    def get_columns(self, font) -> int:
 | 
			
		||||
        """Get column count of printer."""
 | 
			
		||||
        if self.columns is not None:
 | 
			
		||||
            return self.columns
 | 
			
		||||
 
 | 
			
		||||
@@ -20,15 +20,13 @@ except ImportError:
 | 
			
		||||
    pass  # noqa
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import six
 | 
			
		||||
 | 
			
		||||
from . import config
 | 
			
		||||
from . import printer as escpos_printer_module
 | 
			
		||||
from . import version
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Must be defined before it's used in DEMO_FUNCTIONS
 | 
			
		||||
def str_to_bool(string):
 | 
			
		||||
def str_to_bool(string: str) -> bool:
 | 
			
		||||
    """Convert string to bool.
 | 
			
		||||
 | 
			
		||||
    Used as a type in argparse so that we get back a proper
 | 
			
		||||
@@ -563,7 +561,7 @@ def generate_parser() -> argparse.ArgumentParser:
 | 
			
		||||
    return parser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
def main() -> None:
 | 
			
		||||
    """Handle main entry point of CLI script.
 | 
			
		||||
 | 
			
		||||
    Handles loading of configuration and creating and processing of command
 | 
			
		||||
@@ -580,9 +578,7 @@ def main():
 | 
			
		||||
    if not args_dict:
 | 
			
		||||
        parser.print_help()
 | 
			
		||||
        sys.exit()
 | 
			
		||||
    command_arguments = dict(
 | 
			
		||||
        [k, v] for k, v in six.iteritems(args_dict) if v is not None
 | 
			
		||||
    )
 | 
			
		||||
    command_arguments = dict([k, v] for k, v in args_dict.items() if v is not None)
 | 
			
		||||
 | 
			
		||||
    # If version should be printed, do this, then exit
 | 
			
		||||
    print_version = command_arguments.pop("version", None)
 | 
			
		||||
@@ -621,7 +617,7 @@ def main():
 | 
			
		||||
        globals()[target_command](**command_arguments)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def demo(printer, **kwargs):
 | 
			
		||||
def demo(printer, **kwargs) -> None:
 | 
			
		||||
    """Print demos.
 | 
			
		||||
 | 
			
		||||
    Called when CLI is passed `demo`. This function
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import yaml
 | 
			
		||||
from . import exceptions, printer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Config(object):
 | 
			
		||||
class Config:
 | 
			
		||||
    """Configuration handler class.
 | 
			
		||||
 | 
			
		||||
    This class loads configuration from a default or specified directory. It
 | 
			
		||||
@@ -21,7 +21,7 @@ class Config(object):
 | 
			
		||||
    _app_name = "python-escpos"
 | 
			
		||||
    _config_file = "config.yaml"
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
    def __init__(self) -> None:
 | 
			
		||||
        """Initialize configuration.
 | 
			
		||||
 | 
			
		||||
        Remember to add anything that needs to be reset between configurations
 | 
			
		||||
@@ -33,7 +33,7 @@ class Config(object):
 | 
			
		||||
        self._printer_name = None
 | 
			
		||||
        self._printer_config = None
 | 
			
		||||
 | 
			
		||||
    def _reset_config(self):
 | 
			
		||||
    def _reset_config(self) -> None:
 | 
			
		||||
        """Clear the loaded configuration.
 | 
			
		||||
 | 
			
		||||
        If we are loading a changed config, we don't want to have leftover
 | 
			
		||||
 
 | 
			
		||||
@@ -46,9 +46,7 @@ HW_RESET: bytes = ESC + b"\x3f\x0a\x00"  # Reset printer hardware
 | 
			
		||||
# (TODO: Where is this specified?)
 | 
			
		||||
 | 
			
		||||
# Cash Drawer (ESC p <pin> <on time: 2*ms> <off time: 2*ms>)
 | 
			
		||||
_CASH_DRAWER = (
 | 
			
		||||
    lambda m, t1="", t2="": ESC + b"p" + m + six.int2byte(t1) + six.int2byte(t2)
 | 
			
		||||
)
 | 
			
		||||
_CASH_DRAWER = lambda m, t1="", t2="": ESC + b"p" + m + bytes((t1, t2))
 | 
			
		||||
 | 
			
		||||
#: decimal cash drawer kick sequence
 | 
			
		||||
CD_KICK_DEC_SEQUENCE = (
 | 
			
		||||
 
 | 
			
		||||
@@ -9,13 +9,14 @@ This module contains the abstract base class :py:class:`Escpos`.
 | 
			
		||||
:copyright: Copyright (c) 2012-2017 Bashlinux and python-escpos
 | 
			
		||||
:license: MIT
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import textwrap
 | 
			
		||||
import warnings
 | 
			
		||||
from abc import ABCMeta, abstractmethod  # abstract base class support
 | 
			
		||||
from re import match as re_match
 | 
			
		||||
from typing import List, Literal, Optional, Union
 | 
			
		||||
from types import TracebackType
 | 
			
		||||
from typing import Any, Literal, Optional, Union
 | 
			
		||||
 | 
			
		||||
import barcode
 | 
			
		||||
import qrcode
 | 
			
		||||
@@ -107,8 +108,7 @@ SW_BARCODE_NAMES = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@six.add_metaclass(ABCMeta)
 | 
			
		||||
class Escpos(object):
 | 
			
		||||
class Escpos(object, metaclass=ABCMeta):
 | 
			
		||||
    """ESC/POS Printer object.
 | 
			
		||||
 | 
			
		||||
    This class is the abstract base class for an Esc/Pos-printer. The printer implementations are children of this
 | 
			
		||||
@@ -154,6 +154,10 @@ class Escpos(object):
 | 
			
		||||
        """Open a printer device/connection."""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        """Close a printer device/connection."""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Send raw data to the printer.
 | 
			
		||||
@@ -164,7 +168,7 @@ class Escpos(object):
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def _read(self):
 | 
			
		||||
    def _read(self) -> bytes:
 | 
			
		||||
        """Read from printer.
 | 
			
		||||
 | 
			
		||||
        Returns a NotImplementedError if the instance of the class doesn't override this method.
 | 
			
		||||
@@ -250,7 +254,7 @@ class Escpos(object):
 | 
			
		||||
            header = (
 | 
			
		||||
                GS
 | 
			
		||||
                + b"v0"
 | 
			
		||||
                + six.int2byte(density_byte)
 | 
			
		||||
                + bytes((density_byte,))
 | 
			
		||||
                + self._int_low_high(im.width_bytes, 2)
 | 
			
		||||
                + self._int_low_high(im.height, 2)
 | 
			
		||||
            )
 | 
			
		||||
@@ -263,8 +267,8 @@ class Escpos(object):
 | 
			
		||||
            )
 | 
			
		||||
            tone = b"0"
 | 
			
		||||
            colors = b"1"
 | 
			
		||||
            ym = six.int2byte(1 if high_density_vertical else 2)
 | 
			
		||||
            xm = six.int2byte(1 if high_density_horizontal else 2)
 | 
			
		||||
            ym = b"\x01" if high_density_vertical else b"\x02"
 | 
			
		||||
            xm = b"\x01" if high_density_horizontal else b"\x02"
 | 
			
		||||
            header = tone + xm + ym + colors + img_header
 | 
			
		||||
            raster_data = im.to_raster_format()
 | 
			
		||||
            self._image_send_graphics_data(b"0", b"p", header + raster_data)
 | 
			
		||||
@@ -847,7 +851,7 @@ class Escpos(object):
 | 
			
		||||
        image = my_code.writer._image
 | 
			
		||||
        self.image(image, impl=impl, center=center)
 | 
			
		||||
 | 
			
		||||
    def text(self, txt):
 | 
			
		||||
    def text(self, txt: str) -> None:
 | 
			
		||||
        """Print alpha-numeric text.
 | 
			
		||||
 | 
			
		||||
        The text has to be encoded in the currently selected codepage.
 | 
			
		||||
@@ -856,10 +860,9 @@ class Escpos(object):
 | 
			
		||||
        :param txt: text to be printed
 | 
			
		||||
        :raises: :py:exc:`~escpos.exceptions.TextError`
 | 
			
		||||
        """
 | 
			
		||||
        txt = six.text_type(txt)
 | 
			
		||||
        self.magic.write(txt)
 | 
			
		||||
        self.magic.write(str(txt))
 | 
			
		||||
 | 
			
		||||
    def textln(self, txt=""):
 | 
			
		||||
    def textln(self, txt: str = "") -> None:
 | 
			
		||||
        """Print alpha-numeric text with a newline.
 | 
			
		||||
 | 
			
		||||
        The text has to be encoded in the currently selected codepage.
 | 
			
		||||
@@ -870,7 +873,7 @@ class Escpos(object):
 | 
			
		||||
        """
 | 
			
		||||
        self.text(f"{txt}\n")
 | 
			
		||||
 | 
			
		||||
    def ln(self, count=1):
 | 
			
		||||
    def ln(self, count: int = 1) -> None:
 | 
			
		||||
        """Print a newline or more.
 | 
			
		||||
 | 
			
		||||
        :param count: number of newlines to print
 | 
			
		||||
@@ -881,7 +884,7 @@ class Escpos(object):
 | 
			
		||||
        if count > 0:
 | 
			
		||||
            self.text("\n" * count)
 | 
			
		||||
 | 
			
		||||
    def block_text(self, txt, font="0", columns=None):
 | 
			
		||||
    def block_text(self, txt, font="0", columns=None) -> None:
 | 
			
		||||
        """Print text wrapped to specific columns.
 | 
			
		||||
 | 
			
		||||
        Text has to be encoded in unicode.
 | 
			
		||||
@@ -1132,7 +1135,7 @@ class Escpos(object):
 | 
			
		||||
            try:
 | 
			
		||||
                self._raw(CD_KICK_DEC_SEQUENCE(*pin))
 | 
			
		||||
            except TypeError as err:
 | 
			
		||||
                raise CashDrawerError(err)
 | 
			
		||||
                raise CashDrawerError(str(err))
 | 
			
		||||
 | 
			
		||||
    def linedisplay_select(self, select_display: bool = False) -> None:
 | 
			
		||||
        """Select the line display or the printer.
 | 
			
		||||
@@ -1265,10 +1268,10 @@ class Escpos(object):
 | 
			
		||||
        else:
 | 
			
		||||
            self._raw(PANEL_BUTTON_OFF)
 | 
			
		||||
 | 
			
		||||
    def query_status(self, mode: bytes) -> List[int]:
 | 
			
		||||
    def query_status(self, mode: bytes) -> bytes:
 | 
			
		||||
        """Query the printer for its status.
 | 
			
		||||
 | 
			
		||||
        Returns an array of integers containing it.
 | 
			
		||||
        Returns byte array containing it.
 | 
			
		||||
 | 
			
		||||
        :param mode: Integer that sets the status mode queried to the printer.
 | 
			
		||||
            - RT_STATUS_ONLINE: Printer status.
 | 
			
		||||
@@ -1288,7 +1291,7 @@ class Escpos(object):
 | 
			
		||||
            return False
 | 
			
		||||
        return not (status[0] & RT_MASK_ONLINE)
 | 
			
		||||
 | 
			
		||||
    def paper_status(self):
 | 
			
		||||
    def paper_status(self) -> int:  # could be IntEnum
 | 
			
		||||
        """Query the paper status of the printer.
 | 
			
		||||
 | 
			
		||||
        Returns 2 if there is plenty of paper, 1 if the paper has arrived to
 | 
			
		||||
@@ -1305,6 +1308,8 @@ class Escpos(object):
 | 
			
		||||
            return 1
 | 
			
		||||
        if status[0] & RT_MASK_PAPER == RT_MASK_PAPER:
 | 
			
		||||
            return 2
 | 
			
		||||
        # not reached
 | 
			
		||||
        return 0
 | 
			
		||||
 | 
			
		||||
    def target(self, type: str = "ROLL") -> None:
 | 
			
		||||
        """Select where to print to.
 | 
			
		||||
@@ -1359,7 +1364,7 @@ class Escpos(object):
 | 
			
		||||
        self._raw(BUZZER + six.int2byte(times) + six.int2byte(duration))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EscposIO(object):
 | 
			
		||||
class EscposIO:
 | 
			
		||||
    r"""ESC/POS Printer IO object.
 | 
			
		||||
 | 
			
		||||
    Allows the class to be used together with the `with`-statement. You have to define a printer instance
 | 
			
		||||
@@ -1405,12 +1410,12 @@ class EscposIO(object):
 | 
			
		||||
        """
 | 
			
		||||
        self.params.update(kwargs)
 | 
			
		||||
 | 
			
		||||
    def writelines(self, text, **kwargs):
 | 
			
		||||
    def writelines(self, text: str, **kwargs) -> None:
 | 
			
		||||
        """Print text."""
 | 
			
		||||
        params = dict(self.params)
 | 
			
		||||
        params.update(kwargs)
 | 
			
		||||
 | 
			
		||||
        if isinstance(text, six.text_type):
 | 
			
		||||
        if isinstance(text, str):
 | 
			
		||||
            lines = text.split("\n")
 | 
			
		||||
        elif isinstance(text, list) or isinstance(text, tuple):
 | 
			
		||||
            lines = text
 | 
			
		||||
@@ -1423,23 +1428,22 @@ class EscposIO(object):
 | 
			
		||||
        # TODO flush? or on print? (this should prob rather be handled by the _raw-method)
 | 
			
		||||
        for line in lines:
 | 
			
		||||
            self.printer.set(**params)
 | 
			
		||||
            if isinstance(text, six.text_type):
 | 
			
		||||
                self.printer.text(f"{line}\n")
 | 
			
		||||
            else:
 | 
			
		||||
                self.printer.text(f"{line}\n")
 | 
			
		||||
            self.printer.text(f"{line}\n")
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
    def close(self) -> None:
 | 
			
		||||
        """Close printer.
 | 
			
		||||
 | 
			
		||||
        Called upon closing the `with`-statement.
 | 
			
		||||
        """
 | 
			
		||||
        self.printer.close()
 | 
			
		||||
 | 
			
		||||
    def __enter__(self, **kwargs):
 | 
			
		||||
    def __enter__(self, **kwargs: Any) -> "EscposIO":
 | 
			
		||||
        """Enter context."""
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
    def __exit__(self, type, value, traceback):
 | 
			
		||||
    def __exit__(
 | 
			
		||||
        self, type: type[BaseException], value: BaseException, traceback: TracebackType
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """Cut and close if configured.
 | 
			
		||||
 | 
			
		||||
        If :py:attr:`autocut <escpos.escpos.EscposIO.autocut>` is `True` (set by this class' constructor),
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ Result/Exit codes:
 | 
			
		||||
:license: MIT
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Error(Exception):
 | 
			
		||||
    """Base class for ESC/POS errors.
 | 
			
		||||
@@ -37,7 +39,7 @@ class Error(Exception):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg, status=None):
 | 
			
		||||
    def __init__(self, msg: str, status: Optional[int] = None) -> None:
 | 
			
		||||
        """Initialize Error object."""
 | 
			
		||||
        Exception.__init__(self)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
@@ -45,7 +47,7 @@ class Error(Exception):
 | 
			
		||||
        if status is not None:
 | 
			
		||||
            self.resultcode = status
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of Error."""
 | 
			
		||||
        return self.msg
 | 
			
		||||
 | 
			
		||||
@@ -64,13 +66,13 @@ class BarcodeTypeError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize BarcodeTypeError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 10
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of BarcodeTypeError."""
 | 
			
		||||
        return f"No Barcode type is defined ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -89,13 +91,13 @@ class BarcodeSizeError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize BarcodeSizeError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 20
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of BarcodeSizeError."""
 | 
			
		||||
        return f"Barcode size is out of range ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -114,13 +116,13 @@ class BarcodeCodeError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize BarcodeCodeError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 30
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of BarcodeCodeError."""
 | 
			
		||||
        return f"No Barcode code was supplied ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -137,13 +139,13 @@ class ImageSizeError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize ImageSizeError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 40
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of ImageSizeError."""
 | 
			
		||||
        return f"Image height is longer than 255px and can't be printed ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -160,13 +162,13 @@ class ImageWidthError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize ImageWidthError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 41
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of ImageWidthError."""
 | 
			
		||||
        return f"Image width is too large ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -184,13 +186,13 @@ class TextError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize TextError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 50
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of TextError."""
 | 
			
		||||
        return f"Text string must be supplied to the text() method ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -208,13 +210,13 @@ class CashDrawerError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize CashDrawerError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 60
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of CashDrawerError."""
 | 
			
		||||
        return f"Valid pin must be set to send pulse ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -235,13 +237,13 @@ class TabPosError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize TabPosError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 70
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of TabPosError."""
 | 
			
		||||
        return f"Valid tab positions must be in the range 0 to 16 ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -259,13 +261,13 @@ class CharCodeError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize CharCodeError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 80
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of CharCodeError."""
 | 
			
		||||
        return f"Valid char code must be set ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -283,13 +285,13 @@ class DeviceNotFoundError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize DeviceNotFoundError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 90
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of DeviceNotFoundError."""
 | 
			
		||||
        return f"Device not found ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -307,13 +309,13 @@ class USBNotFoundError(DeviceNotFoundError):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize USBNotFoundError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 91
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of USBNotFoundError."""
 | 
			
		||||
        return f"USB device not found ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -331,13 +333,13 @@ class SetVariableError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize SetVariableError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 100
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of SetVariableError."""
 | 
			
		||||
        return f"Set variable out of range ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -358,13 +360,13 @@ class ConfigNotFoundError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize ConfigNotFoundError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 200
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of ConfigNotFoundError."""
 | 
			
		||||
        return f"Configuration not found ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -382,13 +384,13 @@ class ConfigSyntaxError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize ConfigSyntaxError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 210
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of ConfigSyntaxError."""
 | 
			
		||||
        return f"Configuration syntax is invalid ({self.msg})"
 | 
			
		||||
 | 
			
		||||
@@ -406,12 +408,12 @@ class ConfigSectionMissingError(Error):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, msg=""):
 | 
			
		||||
    def __init__(self, msg: str = "") -> None:
 | 
			
		||||
        """Initialize ConfigSectionMissingError object."""
 | 
			
		||||
        Error.__init__(self, msg)
 | 
			
		||||
        self.msg = msg
 | 
			
		||||
        self.resultcode = 220
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
    def __str__(self) -> str:
 | 
			
		||||
        """Return string representation of ConfigSectionMissingError."""
 | 
			
		||||
        return f"Configuration section is missing ({self.msg})"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,12 @@ This module contains the image format handler :py:class:`EscposImage`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import math
 | 
			
		||||
from typing import Union
 | 
			
		||||
from typing import Iterator, Union
 | 
			
		||||
 | 
			
		||||
from PIL import Image, ImageOps
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EscposImage(object):
 | 
			
		||||
class EscposImage:
 | 
			
		||||
    """
 | 
			
		||||
    Load images in, and output ESC/POS formats.
 | 
			
		||||
 | 
			
		||||
@@ -23,7 +23,7 @@ class EscposImage(object):
 | 
			
		||||
    PIL, rather than spend CPU cycles looping over pixels.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, img_source: Union[Image.Image, str]):
 | 
			
		||||
    def __init__(self, img_source: Union[Image.Image, str]) -> None:
 | 
			
		||||
        """Load in an image.
 | 
			
		||||
 | 
			
		||||
        :param img_source: PIL.Image, or filename to load one from.
 | 
			
		||||
@@ -65,7 +65,7 @@ class EscposImage(object):
 | 
			
		||||
        _, height_pixels = self._im.size
 | 
			
		||||
        return height_pixels
 | 
			
		||||
 | 
			
		||||
    def to_column_format(self, high_density_vertical: bool = True):
 | 
			
		||||
    def to_column_format(self, high_density_vertical: bool = True) -> Iterator[bytes]:
 | 
			
		||||
        """Extract slices of an image as equal-sized blobs of column-format data.
 | 
			
		||||
 | 
			
		||||
        :param high_density_vertical: Printed line height in dots
 | 
			
		||||
@@ -82,7 +82,7 @@ class EscposImage(object):
 | 
			
		||||
            yield (im_bytes)
 | 
			
		||||
            left += line_height
 | 
			
		||||
 | 
			
		||||
    def to_raster_format(self):
 | 
			
		||||
    def to_raster_format(self) -> bytes:
 | 
			
		||||
        """Convert image to raster-format binary."""
 | 
			
		||||
        return self._im.tobytes()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ except ImportError:
 | 
			
		||||
    jaconv = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def encode_katakana(text):
 | 
			
		||||
def encode_katakana(text: str) -> bytes:
 | 
			
		||||
    """I don't think this quite works yet."""
 | 
			
		||||
    encoded = []
 | 
			
		||||
    for char in text:
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ from .constants import CODEPAGE_CHANGE
 | 
			
		||||
from .exceptions import Error
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Encoder(object):
 | 
			
		||||
class Encoder:
 | 
			
		||||
    """Take available code spaces and pick the right one for a given character.
 | 
			
		||||
 | 
			
		||||
    Note: To determine the code page, it needs to do the conversion, and
 | 
			
		||||
@@ -202,7 +202,7 @@ def split_writable_text(encoder, text, encoding):
 | 
			
		||||
    return text, None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MagicEncode(object):
 | 
			
		||||
class MagicEncode:
 | 
			
		||||
    """Help switching to the right code page.
 | 
			
		||||
 | 
			
		||||
    A helper that helps us to automatically switch to the right
 | 
			
		||||
@@ -292,7 +292,7 @@ class MagicEncode(object):
 | 
			
		||||
 | 
			
		||||
    def write_with_encoding(self, encoding, text):
 | 
			
		||||
        """Write the text and inject necessary codepage switches."""
 | 
			
		||||
        if text is not None and type(text) is not six.text_type:
 | 
			
		||||
        if text is not None and type(text) is not str:
 | 
			
		||||
            raise Error(
 | 
			
		||||
                f"The supplied text has to be unicode, but is of type {type(text)}."
 | 
			
		||||
            )
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ class CupsPrinter(Escpos):
 | 
			
		||||
        return is_usable()
 | 
			
		||||
 | 
			
		||||
    @dependency_pycups
 | 
			
		||||
    def __init__(self, printer_name: str = "", *args, **kwargs):
 | 
			
		||||
    def __init__(self, printer_name: str = "", *args, **kwargs) -> None:
 | 
			
		||||
        """Class constructor for CupsPrinter.
 | 
			
		||||
 | 
			
		||||
        :param printer_name: CUPS printer name (Optional)
 | 
			
		||||
@@ -163,11 +163,10 @@ class CupsPrinter(Escpos):
 | 
			
		||||
                return
 | 
			
		||||
        logging.info("CupsPrinter printer enabled")
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Append any command sent in raw format to temporary file.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        self.pending_job = True
 | 
			
		||||
        try:
 | 
			
		||||
@@ -176,8 +175,9 @@ class CupsPrinter(Escpos):
 | 
			
		||||
            self.pending_job = False
 | 
			
		||||
            raise TypeError("Bytes required. Printer job not opened")
 | 
			
		||||
 | 
			
		||||
    def send(self):
 | 
			
		||||
    def send(self) -> None:
 | 
			
		||||
        """Send the print job to the printer."""
 | 
			
		||||
        assert self.device
 | 
			
		||||
        if self.pending_job:
 | 
			
		||||
            # Rewind tempfile
 | 
			
		||||
            self.tmpfile.seek(0)
 | 
			
		||||
@@ -190,7 +190,7 @@ class CupsPrinter(Escpos):
 | 
			
		||||
            )
 | 
			
		||||
        self._clear()
 | 
			
		||||
 | 
			
		||||
    def _clear(self):
 | 
			
		||||
    def _clear(self) -> None:
 | 
			
		||||
        """Finish the print job.
 | 
			
		||||
 | 
			
		||||
        Remove temporary file.
 | 
			
		||||
@@ -198,18 +198,18 @@ class CupsPrinter(Escpos):
 | 
			
		||||
        self.tmpfile.close()
 | 
			
		||||
        self.pending_job = False
 | 
			
		||||
 | 
			
		||||
    def _read(self):
 | 
			
		||||
    def _read(self) -> bytes:
 | 
			
		||||
        """Return a single-item array with the accepting state of the print queue.
 | 
			
		||||
 | 
			
		||||
        states: idle = [3], printing a job = [4], stopped = [5]
 | 
			
		||||
        """
 | 
			
		||||
        printer = self.printers.get(self.printer_name, {})
 | 
			
		||||
        state = printer.get("printer-state")
 | 
			
		||||
        if not state:
 | 
			
		||||
            return []
 | 
			
		||||
        return [state]
 | 
			
		||||
        if not state or state in [4, 5]:
 | 
			
		||||
            return b"8"  # offline
 | 
			
		||||
        return b"0"  # online
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
    def close(self) -> None:
 | 
			
		||||
        """Close CUPS connection.
 | 
			
		||||
 | 
			
		||||
        Send pending job to the printer if needed.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
:copyright: Copyright (c) 2012-2023 Bashlinux and python-escpos
 | 
			
		||||
:license: MIT
 | 
			
		||||
"""
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from ..escpos import Escpos
 | 
			
		||||
 | 
			
		||||
@@ -39,25 +40,24 @@ class Dummy(Escpos):
 | 
			
		||||
        """
 | 
			
		||||
        return is_usable()
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
    def __init__(self, *args, **kwargs) -> None:
 | 
			
		||||
        """Init with empty output list."""
 | 
			
		||||
        Escpos.__init__(self, *args, **kwargs)
 | 
			
		||||
        self._output_list = []
 | 
			
		||||
        self._output_list: List[bytes] = []
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        self._output_list.append(msg)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def output(self):
 | 
			
		||||
    def output(self) -> bytes:
 | 
			
		||||
        """Get the data that was sent to this printer."""
 | 
			
		||||
        return b"".join(self._output_list)
 | 
			
		||||
 | 
			
		||||
    def clear(self):
 | 
			
		||||
    def clear(self) -> None:
 | 
			
		||||
        """Clear the buffer of the printer.
 | 
			
		||||
 | 
			
		||||
        This method can be called if you send the contents to a physical printer
 | 
			
		||||
@@ -65,6 +65,6 @@ class Dummy(Escpos):
 | 
			
		||||
        """
 | 
			
		||||
        del self._output_list[:]
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
    def close(self) -> None:
 | 
			
		||||
        """Close not implemented for Dummy printer."""
 | 
			
		||||
        pass
 | 
			
		||||
 
 | 
			
		||||
@@ -88,12 +88,12 @@ class File(Escpos):
 | 
			
		||||
        if self.device:
 | 
			
		||||
            self.device.flush()
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        assert self.device
 | 
			
		||||
        self.device.write(msg)
 | 
			
		||||
        if self.auto_flush:
 | 
			
		||||
            self.flush()
 | 
			
		||||
 
 | 
			
		||||
@@ -182,12 +182,13 @@ class LP(Escpos):
 | 
			
		||||
        if not self._is_closing:
 | 
			
		||||
            self.open(_close_opened=False)
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Write raw command(s) to the printer.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        assert self.device is not None
 | 
			
		||||
        assert self.device.stdin is not None
 | 
			
		||||
        if self.device.stdin.writable():
 | 
			
		||||
            self.device.stdin.write(msg)
 | 
			
		||||
        else:
 | 
			
		||||
 
 | 
			
		||||
@@ -110,16 +110,17 @@ class Network(Escpos):
 | 
			
		||||
                return
 | 
			
		||||
        logging.info("Network printer enabled")
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        assert self.device
 | 
			
		||||
        self.device.sendall(msg)
 | 
			
		||||
 | 
			
		||||
    def _read(self):
 | 
			
		||||
    def _read(self) -> bytes:
 | 
			
		||||
        """Read data from the TCP socket."""
 | 
			
		||||
        assert self.device
 | 
			
		||||
        return self.device.recv(16)
 | 
			
		||||
 | 
			
		||||
    def close(self) -> None:
 | 
			
		||||
 
 | 
			
		||||
@@ -155,16 +155,17 @@ class Serial(Escpos):
 | 
			
		||||
                return
 | 
			
		||||
        logging.info("Serial printer enabled")
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        assert self.device
 | 
			
		||||
        self.device.write(msg)
 | 
			
		||||
 | 
			
		||||
    def _read(self):
 | 
			
		||||
    def _read(self) -> bytes:
 | 
			
		||||
        """Read the data buffer and return it to the caller."""
 | 
			
		||||
        assert self.device
 | 
			
		||||
        return self.device.read(16)
 | 
			
		||||
 | 
			
		||||
    def close(self) -> None:
 | 
			
		||||
 
 | 
			
		||||
@@ -74,9 +74,9 @@ class Usb(Escpos):
 | 
			
		||||
 | 
			
		||||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
        idVendor: str = "",
 | 
			
		||||
        idProduct: str = "",
 | 
			
		||||
        usb_args: Dict[str, str] = {},
 | 
			
		||||
        idVendor: Optional[int] = None,
 | 
			
		||||
        idProduct: Optional[int] = None,
 | 
			
		||||
        usb_args: Dict[str, Union[str, int]] = {},
 | 
			
		||||
        timeout: Union[int, float] = 0,
 | 
			
		||||
        in_ep: int = 0x82,
 | 
			
		||||
        out_ep: int = 0x01,
 | 
			
		||||
@@ -181,16 +181,17 @@ class Usb(Escpos):
 | 
			
		||||
        except usb.core.USBError as e:
 | 
			
		||||
            logging.error("Could not set configuration: %s", str(e))
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg):
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        assert self.device
 | 
			
		||||
        self.device.write(self.out_ep, msg, self.timeout)
 | 
			
		||||
 | 
			
		||||
    def _read(self):
 | 
			
		||||
    def _read(self) -> bytes:
 | 
			
		||||
        """Read a data buffer and return it to the caller."""
 | 
			
		||||
        assert self.device
 | 
			
		||||
        return self.device.read(self.in_ep, 16)
 | 
			
		||||
 | 
			
		||||
    @dependency_usb
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ class Win32Raw(Escpos):
 | 
			
		||||
        return is_usable()
 | 
			
		||||
 | 
			
		||||
    @dependency_win32print
 | 
			
		||||
    def __init__(self, printer_name: str = "", *args, **kwargs):
 | 
			
		||||
    def __init__(self, printer_name: str = "", *args, **kwargs) -> None:
 | 
			
		||||
        """Initialize default printer."""
 | 
			
		||||
        Escpos.__init__(self, *args, **kwargs)
 | 
			
		||||
        self.printer_name = printer_name
 | 
			
		||||
@@ -148,14 +148,17 @@ class Win32Raw(Escpos):
 | 
			
		||||
        win32print.ClosePrinter(self._device)
 | 
			
		||||
        self._device = False
 | 
			
		||||
 | 
			
		||||
    def _raw(self, msg) -> None:
 | 
			
		||||
    def _raw(self, msg: bytes) -> None:
 | 
			
		||||
        """Print any command sent in raw format.
 | 
			
		||||
 | 
			
		||||
        :param msg: arbitrary code to be printed
 | 
			
		||||
        :type msg: bytes
 | 
			
		||||
        """
 | 
			
		||||
        if self.printer_name is None:
 | 
			
		||||
            raise DeviceNotFoundError("Printer not found")
 | 
			
		||||
        if not self.device:
 | 
			
		||||
            raise DeviceNotFoundError("Printer job not opened")
 | 
			
		||||
        win32print.WritePrinter(self.device, msg)
 | 
			
		||||
        win32print.WritePrinter(self.device, msg)  # type: ignore
 | 
			
		||||
 | 
			
		||||
        # there is a bug in the typeshed
 | 
			
		||||
        # https://github.com/mhammond/pywin32/blob/main/win32/src/win32print/win32print.cpp#L976
 | 
			
		||||
        # https://github.com/python/typeshed/blob/main/stubs/pywin32/win32/win32print.pyi#L27C4-L27C4
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user