This commit is contained in:
Alexandre Detiste 2023-12-10 02:49:26 +01:00
parent 35565d5564
commit 6aec41fbd8
16 changed files with 116 additions and 97 deletions

View File

@ -93,7 +93,7 @@ class NotSupported(Exception):
BARCODE_B = "barcodeB" BARCODE_B = "barcodeB"
class BaseProfile(object): class BaseProfile:
"""This represents a printer profile. """This represents a printer profile.
A printer profile knows about the number of columns, supported A printer profile knows about the number of columns, supported
@ -118,16 +118,18 @@ class BaseProfile(object):
) )
return font return font
def get_columns(self, font): def get_columns(self, font) -> int:
"""Return the number of columns for the given font.""" """Return the number of columns for the given font."""
font = self.get_font(font) font = self.get_font(font)
return self.fonts[str(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 true/false for the given feature."""
return self.features.get(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 the support code pages as a ``{name: index}`` dict."""
return {v: k for k, v in self.codePages.items()} return {v: k for k, v in self.codePages.items()}
@ -164,7 +166,7 @@ def get_profile_class(name: str) -> Type[BaseProfile]:
return CLASS_CACHE[name] return CLASS_CACHE[name]
def clean(s): def clean(s: str) -> str:
"""Clean profile name.""" """Clean profile name."""
# Remove invalid characters # Remove invalid characters
s = re.sub("[^0-9a-zA-Z_]", "", s) s = re.sub("[^0-9a-zA-Z_]", "", s)
@ -183,14 +185,14 @@ class Profile(ProfileBaseClass):
For users, who want to provide their own profile. 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.""" """Initialize profile."""
super(Profile, self).__init__() super(Profile, self).__init__()
self.columns = columns self.columns = columns
self.features = features or {} self.features = features or {}
def get_columns(self, font): def get_columns(self, font) -> int:
"""Get column count of printer.""" """Get column count of printer."""
if self.columns is not None: if self.columns is not None:
return self.columns return self.columns

View File

@ -26,7 +26,7 @@ from . import version
# Must be defined before it's used in DEMO_FUNCTIONS # 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. """Convert string to bool.
Used as a type in argparse so that we get back a proper Used as a type in argparse so that we get back a proper
@ -561,7 +561,7 @@ def generate_parser() -> argparse.ArgumentParser:
return parser return parser
def main(): def main() -> None:
"""Handle main entry point of CLI script. """Handle main entry point of CLI script.
Handles loading of configuration and creating and processing of command Handles loading of configuration and creating and processing of command
@ -619,7 +619,7 @@ def main():
globals()[target_command](**command_arguments) globals()[target_command](**command_arguments)
def demo(printer, **kwargs): def demo(printer, **kwargs) -> None:
"""Print demos. """Print demos.
Called when CLI is passed `demo`. This function Called when CLI is passed `demo`. This function

View File

@ -4,6 +4,7 @@ This module contains the implementations of abstract base class :py:class:`Confi
""" """
import os import os
import pathlib import pathlib
from typing import Optional
import appdirs import appdirs
import yaml import yaml
@ -11,7 +12,7 @@ import yaml
from . import exceptions, printer from . import exceptions, printer
class Config(object): class Config:
"""Configuration handler class. """Configuration handler class.
This class loads configuration from a default or specified directory. It This class loads configuration from a default or specified directory. It
@ -21,7 +22,7 @@ class Config(object):
_app_name = "python-escpos" _app_name = "python-escpos"
_config_file = "config.yaml" _config_file = "config.yaml"
def __init__(self): def __init__(self) -> None:
"""Initialize configuration. """Initialize configuration.
Remember to add anything that needs to be reset between configurations Remember to add anything that needs to be reset between configurations
@ -33,7 +34,7 @@ class Config(object):
self._printer_name = None self._printer_name = None
self._printer_config = None self._printer_config = None
def _reset_config(self): def _reset_config(self) -> None:
"""Clear the loaded configuration. """Clear the loaded configuration.
If we are loading a changed config, we don't want to have leftover If we are loading a changed config, we don't want to have leftover

View File

@ -47,7 +47,7 @@ HW_RESET: bytes = ESC + b"\x3f\x0a\x00" # Reset printer hardware
# Cash Drawer (ESC p <pin> <on time: 2*ms> <off time: 2*ms>) # Cash Drawer (ESC p <pin> <on time: 2*ms> <off time: 2*ms>)
_CASH_DRAWER = ( _CASH_DRAWER = (
lambda m, t1="", t2="": ESC + b"p" + m + six.int2byte(t1) + six.int2byte(t2) lambda m, t1="", t2="": ESC + b"p" + m + bytes((t1, t2))
) )
#: decimal cash drawer kick sequence #: decimal cash drawer kick sequence

View File

@ -15,7 +15,8 @@ import textwrap
import warnings import warnings
from abc import ABCMeta, abstractmethod # abstract base class support from abc import ABCMeta, abstractmethod # abstract base class support
from re import match as re_match from re import match as re_match
from typing import List, Literal, Optional, Union from types import TracebackType
from typing import List, Literal, Optional, Union, Any
import barcode import barcode
import qrcode import qrcode
@ -107,8 +108,7 @@ SW_BARCODE_NAMES = {
} }
@six.add_metaclass(ABCMeta) class Escpos(object, metaclass=ABCMeta):
class Escpos(object):
"""ESC/POS Printer object. """ESC/POS Printer object.
This class is the abstract base class for an Esc/Pos-printer. The printer implementations are children of this This class is the abstract base class for an Esc/Pos-printer. The printer implementations are children of this
@ -164,7 +164,7 @@ class Escpos(object):
""" """
pass pass
def _read(self): def _read(self) -> bytes:
"""Read from printer. """Read from printer.
Returns a NotImplementedError if the instance of the class doesn't override this method. Returns a NotImplementedError if the instance of the class doesn't override this method.
@ -250,7 +250,7 @@ class Escpos(object):
header = ( header = (
GS GS
+ b"v0" + b"v0"
+ six.int2byte(density_byte) + bytes((density_byte,))
+ self._int_low_high(im.width_bytes, 2) + self._int_low_high(im.width_bytes, 2)
+ self._int_low_high(im.height, 2) + self._int_low_high(im.height, 2)
) )
@ -263,8 +263,8 @@ class Escpos(object):
) )
tone = b"0" tone = b"0"
colors = b"1" colors = b"1"
ym = six.int2byte(1 if high_density_vertical else 2) ym = b"1" if high_density_vertical else b"2"
xm = six.int2byte(1 if high_density_horizontal else 2) xm = b"1" if high_density_horizontal else b"2"
header = tone + xm + ym + colors + img_header header = tone + xm + ym + colors + img_header
raster_data = im.to_raster_format() raster_data = im.to_raster_format()
self._image_send_graphics_data(b"0", b"p", header + raster_data) self._image_send_graphics_data(b"0", b"p", header + raster_data)
@ -857,7 +857,7 @@ class Escpos(object):
image = my_code.writer._image image = my_code.writer._image
self.image(image, impl=impl, center=center) self.image(image, impl=impl, center=center)
def text(self, txt): def text(self, txt:str) -> None:
"""Print alpha-numeric text. """Print alpha-numeric text.
The text has to be encoded in the currently selected codepage. The text has to be encoded in the currently selected codepage.
@ -868,7 +868,7 @@ class Escpos(object):
""" """
self.magic.write(str(txt)) self.magic.write(str(txt))
def textln(self, txt=""): def textln(self, txt: str = "") -> None:
"""Print alpha-numeric text with a newline. """Print alpha-numeric text with a newline.
The text has to be encoded in the currently selected codepage. The text has to be encoded in the currently selected codepage.
@ -879,7 +879,7 @@ class Escpos(object):
""" """
self.text("{}\n".format(txt)) self.text("{}\n".format(txt))
def ln(self, count=1): def ln(self, count: int = 1) -> None:
"""Print a newline or more. """Print a newline or more.
:param count: number of newlines to print :param count: number of newlines to print
@ -890,7 +890,7 @@ class Escpos(object):
if count > 0: if count > 0:
self.text("\n" * count) 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. """Print text wrapped to specific columns.
Text has to be encoded in unicode. Text has to be encoded in unicode.
@ -1297,7 +1297,7 @@ class Escpos(object):
return False return False
return not (status[0] & RT_MASK_ONLINE) 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. """Query the paper status of the printer.
Returns 2 if there is plenty of paper, 1 if the paper has arrived to Returns 2 if there is plenty of paper, 1 if the paper has arrived to
@ -1314,6 +1314,8 @@ class Escpos(object):
return 1 return 1
if status[0] & RT_MASK_PAPER == RT_MASK_PAPER: if status[0] & RT_MASK_PAPER == RT_MASK_PAPER:
return 2 return 2
# not reached
return 0
def target(self, type: str = "ROLL") -> None: def target(self, type: str = "ROLL") -> None:
"""Select where to print to. """Select where to print to.
@ -1368,7 +1370,7 @@ class Escpos(object):
self._raw(BUZZER + six.int2byte(times) + six.int2byte(duration)) self._raw(BUZZER + six.int2byte(times) + six.int2byte(duration))
class EscposIO(object): class EscposIO:
r"""ESC/POS Printer IO object. r"""ESC/POS Printer IO object.
Allows the class to be used together with the `with`-statement. You have to define a printer instance Allows the class to be used together with the `with`-statement. You have to define a printer instance
@ -1414,7 +1416,7 @@ class EscposIO(object):
""" """
self.params.update(kwargs) self.params.update(kwargs)
def writelines(self, text, **kwargs): def writelines(self, text: str, **kwargs) -> None:
"""Print text.""" """Print text."""
params = dict(self.params) params = dict(self.params)
params.update(kwargs) params.update(kwargs)
@ -1434,18 +1436,23 @@ class EscposIO(object):
self.printer.set(**params) self.printer.set(**params)
self.printer.text("{0}\n".format(line)) self.printer.text("{0}\n".format(line))
def close(self): def close(self) -> None:
"""Close printer. """Close printer.
Called upon closing the `with`-statement. Called upon closing the `with`-statement.
""" """
self.printer.close() self.printer.close()
def __enter__(self, **kwargs): def __enter__(self, **kwargs: Any) -> 'EscposIO':
"""Enter context.""" """Enter context."""
return self return self
def __exit__(self, type, value, traceback): def __exit__(
self,
type: type[BaseException],
value: BaseException,
traceback: TracebackType
) -> None:
"""Cut and close if configured. """Cut and close if configured.
If :py:attr:`autocut <escpos.escpos.EscposIO.autocut>` is `True` (set by this class' constructor), If :py:attr:`autocut <escpos.escpos.EscposIO.autocut>` is `True` (set by this class' constructor),

View File

@ -26,6 +26,8 @@ Result/Exit codes:
:license: MIT :license: MIT
""" """
from typing import Optional
class Error(Exception): class Error(Exception):
"""Base class for ESC/POS errors. """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.""" """Initialize Error object."""
Exception.__init__(self) Exception.__init__(self)
self.msg = msg self.msg = msg
@ -45,7 +47,7 @@ class Error(Exception):
if status is not None: if status is not None:
self.resultcode = status self.resultcode = status
def __str__(self): def __str__(self) -> str:
"""Return string representation of Error.""" """Return string representation of Error."""
return self.msg return self.msg
@ -64,13 +66,13 @@ class BarcodeTypeError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize BarcodeTypeError object.""" """Initialize BarcodeTypeError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 10 self.resultcode = 10
def __str__(self): def __str__(self) -> str:
"""Return string representation of BarcodeTypeError.""" """Return string representation of BarcodeTypeError."""
return "No Barcode type is defined ({msg})".format(msg=self.msg) return "No Barcode type is defined ({msg})".format(msg=self.msg)
@ -89,13 +91,13 @@ class BarcodeSizeError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize BarcodeSizeError object.""" """Initialize BarcodeSizeError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 20 self.resultcode = 20
def __str__(self): def __str__(self) -> str:
"""Return string representation of BarcodeSizeError.""" """Return string representation of BarcodeSizeError."""
return "Barcode size is out of range ({msg})".format(msg=self.msg) return "Barcode size is out of range ({msg})".format(msg=self.msg)
@ -114,13 +116,13 @@ class BarcodeCodeError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize BarcodeCodeError object.""" """Initialize BarcodeCodeError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 30 self.resultcode = 30
def __str__(self): def __str__(self) -> str:
"""Return string representation of BarcodeCodeError.""" """Return string representation of BarcodeCodeError."""
return "No Barcode code was supplied ({msg})".format(msg=self.msg) return "No Barcode code was supplied ({msg})".format(msg=self.msg)
@ -137,13 +139,13 @@ class ImageSizeError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize ImageSizeError object.""" """Initialize ImageSizeError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 40 self.resultcode = 40
def __str__(self): def __str__(self) -> str:
"""Return string representation of ImageSizeError.""" """Return string representation of ImageSizeError."""
return "Image height is longer than 255px and can't be printed ({msg})".format( return "Image height is longer than 255px and can't be printed ({msg})".format(
msg=self.msg msg=self.msg
@ -162,13 +164,13 @@ class ImageWidthError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize ImageWidthError object.""" """Initialize ImageWidthError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 41 self.resultcode = 41
def __str__(self): def __str__(self) -> str:
"""Return string representation of ImageWidthError.""" """Return string representation of ImageWidthError."""
return "Image width is too large ({msg})".format(msg=self.msg) return "Image width is too large ({msg})".format(msg=self.msg)
@ -186,13 +188,13 @@ class TextError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize TextError object.""" """Initialize TextError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 50 self.resultcode = 50
def __str__(self): def __str__(self) -> str:
"""Return string representation of TextError.""" """Return string representation of TextError."""
return "Text string must be supplied to the text() method ({msg})".format( return "Text string must be supplied to the text() method ({msg})".format(
msg=self.msg msg=self.msg
@ -212,13 +214,13 @@ class CashDrawerError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize CashDrawerError object.""" """Initialize CashDrawerError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 60 self.resultcode = 60
def __str__(self): def __str__(self) -> str:
"""Return string representation of CashDrawerError.""" """Return string representation of CashDrawerError."""
return "Valid pin must be set to send pulse ({msg})".format(msg=self.msg) return "Valid pin must be set to send pulse ({msg})".format(msg=self.msg)
@ -239,13 +241,13 @@ class TabPosError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize TabPosError object.""" """Initialize TabPosError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 70 self.resultcode = 70
def __str__(self): def __str__(self) -> str:
"""Return string representation of TabPosError.""" """Return string representation of TabPosError."""
return "Valid tab positions must be in the range 0 to 16 ({msg})".format( return "Valid tab positions must be in the range 0 to 16 ({msg})".format(
msg=self.msg msg=self.msg
@ -265,13 +267,13 @@ class CharCodeError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize CharCodeError object.""" """Initialize CharCodeError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 80 self.resultcode = 80
def __str__(self): def __str__(self) -> str:
"""Return string representation of CharCodeError.""" """Return string representation of CharCodeError."""
return "Valid char code must be set ({msg})".format(msg=self.msg) return "Valid char code must be set ({msg})".format(msg=self.msg)
@ -289,13 +291,13 @@ class DeviceNotFoundError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize DeviceNotFoundError object.""" """Initialize DeviceNotFoundError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 90 self.resultcode = 90
def __str__(self): def __str__(self) -> str:
"""Return string representation of DeviceNotFoundError.""" """Return string representation of DeviceNotFoundError."""
return f"Device not found ({self.msg})" return f"Device not found ({self.msg})"
@ -313,13 +315,13 @@ class USBNotFoundError(DeviceNotFoundError):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize USBNotFoundError object.""" """Initialize USBNotFoundError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 91 self.resultcode = 91
def __str__(self): def __str__(self) -> str:
"""Return string representation of USBNotFoundError.""" """Return string representation of USBNotFoundError."""
return f"USB device not found ({self.msg})" return f"USB device not found ({self.msg})"
@ -337,13 +339,13 @@ class SetVariableError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize SetVariableError object.""" """Initialize SetVariableError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 100 self.resultcode = 100
def __str__(self): def __str__(self) -> str:
"""Return string representation of SetVariableError.""" """Return string representation of SetVariableError."""
return "Set variable out of range ({msg})".format(msg=self.msg) return "Set variable out of range ({msg})".format(msg=self.msg)
@ -364,13 +366,13 @@ class ConfigNotFoundError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize ConfigNotFoundError object.""" """Initialize ConfigNotFoundError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 200 self.resultcode = 200
def __str__(self): def __str__(self) -> str:
"""Return string representation of ConfigNotFoundError.""" """Return string representation of ConfigNotFoundError."""
return "Configuration not found ({msg})".format(msg=self.msg) return "Configuration not found ({msg})".format(msg=self.msg)
@ -388,13 +390,13 @@ class ConfigSyntaxError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize ConfigSyntaxError object.""" """Initialize ConfigSyntaxError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 210 self.resultcode = 210
def __str__(self): def __str__(self) -> str:
"""Return string representation of ConfigSyntaxError.""" """Return string representation of ConfigSyntaxError."""
return "Configuration syntax is invalid ({msg})".format(msg=self.msg) return "Configuration syntax is invalid ({msg})".format(msg=self.msg)
@ -412,12 +414,12 @@ class ConfigSectionMissingError(Error):
""" """
def __init__(self, msg=""): def __init__(self, msg: str = "") -> None:
"""Initialize ConfigSectionMissingError object.""" """Initialize ConfigSectionMissingError object."""
Error.__init__(self, msg) Error.__init__(self, msg)
self.msg = msg self.msg = msg
self.resultcode = 220 self.resultcode = 220
def __str__(self): def __str__(self) -> str:
"""Return string representation of ConfigSectionMissingError.""" """Return string representation of ConfigSectionMissingError."""
return "Configuration section is missing ({msg})".format(msg=self.msg) return "Configuration section is missing ({msg})".format(msg=self.msg)

View File

@ -10,12 +10,12 @@ This module contains the image format handler :py:class:`EscposImage`.
import math import math
from typing import Union from typing import Union, Iterator
from PIL import Image, ImageOps from PIL import Image, ImageOps
class EscposImage(object): class EscposImage:
""" """
Load images in, and output ESC/POS formats. Load images in, and output ESC/POS formats.
@ -23,7 +23,7 @@ class EscposImage(object):
PIL, rather than spend CPU cycles looping over pixels. 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. """Load in an image.
:param img_source: PIL.Image, or filename to load one from. :param img_source: PIL.Image, or filename to load one from.
@ -65,7 +65,7 @@ class EscposImage(object):
_, height_pixels = self._im.size _, height_pixels = self._im.size
return height_pixels 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. """Extract slices of an image as equal-sized blobs of column-format data.
:param high_density_vertical: Printed line height in dots :param high_density_vertical: Printed line height in dots
@ -82,7 +82,7 @@ class EscposImage(object):
yield (im_bytes) yield (im_bytes)
left += line_height left += line_height
def to_raster_format(self): def to_raster_format(self) -> bytes:
"""Convert image to raster-format binary.""" """Convert image to raster-format binary."""
return self._im.tobytes() return self._im.tobytes()

View File

@ -23,7 +23,7 @@ from .constants import CODEPAGE_CHANGE
from .exceptions import Error from .exceptions import Error
class Encoder(object): class Encoder:
"""Take available code spaces and pick the right one for a given character. """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 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 return text, None
class MagicEncode(object): class MagicEncode:
"""Help switching to the right code page. """Help switching to the right code page.
A helper that helps us to automatically switch to the right A helper that helps us to automatically switch to the right

View File

@ -11,7 +11,7 @@
import functools import functools
import logging import logging
import tempfile import tempfile
from typing import Literal, Optional, Type, Union from typing import Literal, Optional, Type, Union, List
from ..escpos import Escpos from ..escpos import Escpos
from ..exceptions import DeviceNotFoundError from ..exceptions import DeviceNotFoundError
@ -84,7 +84,7 @@ class CupsPrinter(Escpos):
return is_usable() return is_usable()
@dependency_pycups @dependency_pycups
def __init__(self, printer_name: str = "", *args, **kwargs): def __init__(self, printer_name: str = "", *args, **kwargs) -> None:
"""Class constructor for CupsPrinter. """Class constructor for CupsPrinter.
:param printer_name: CUPS printer name (Optional) :param printer_name: CUPS printer name (Optional)
@ -163,7 +163,7 @@ class CupsPrinter(Escpos):
return return
logging.info("CupsPrinter printer enabled") 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. """Append any command sent in raw format to temporary file.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
@ -176,8 +176,9 @@ class CupsPrinter(Escpos):
self.pending_job = False self.pending_job = False
raise TypeError("Bytes required. Printer job not opened") raise TypeError("Bytes required. Printer job not opened")
def send(self): def send(self) -> None:
"""Send the print job to the printer.""" """Send the print job to the printer."""
assert self.device
if self.pending_job: if self.pending_job:
# Rewind tempfile # Rewind tempfile
self.tmpfile.seek(0) self.tmpfile.seek(0)
@ -190,7 +191,7 @@ class CupsPrinter(Escpos):
) )
self._clear() self._clear()
def _clear(self): def _clear(self) -> None:
"""Finish the print job. """Finish the print job.
Remove temporary file. Remove temporary file.
@ -198,7 +199,7 @@ class CupsPrinter(Escpos):
self.tmpfile.close() self.tmpfile.close()
self.pending_job = False self.pending_job = False
def _read(self): def _read(self) -> List[int]:
"""Return a single-item array with the accepting state of the print queue. """Return a single-item array with the accepting state of the print queue.
states: idle = [3], printing a job = [4], stopped = [5] states: idle = [3], printing a job = [4], stopped = [5]
@ -209,7 +210,7 @@ class CupsPrinter(Escpos):
return [] return []
return [state] return [state]
def close(self): def close(self) -> None:
"""Close CUPS connection. """Close CUPS connection.
Send pending job to the printer if needed. Send pending job to the printer if needed.

View File

@ -7,6 +7,7 @@
:copyright: Copyright (c) 2012-2023 Bashlinux and python-escpos :copyright: Copyright (c) 2012-2023 Bashlinux and python-escpos
:license: MIT :license: MIT
""" """
from typing import List
from ..escpos import Escpos from ..escpos import Escpos
@ -39,25 +40,24 @@ class Dummy(Escpos):
""" """
return is_usable() return is_usable()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs) -> None:
"""Init with empty output list.""" """Init with empty output list."""
Escpos.__init__(self, *args, **kwargs) 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. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
:type msg: bytes
""" """
self._output_list.append(msg) self._output_list.append(msg)
@property @property
def output(self): def output(self) -> bytes:
"""Get the data that was sent to this printer.""" """Get the data that was sent to this printer."""
return b"".join(self._output_list) return b"".join(self._output_list)
def clear(self): def clear(self) -> None:
"""Clear the buffer of the printer. """Clear the buffer of the printer.
This method can be called if you send the contents to a physical 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[:] del self._output_list[:]
def close(self): def close(self) -> None:
"""Close not implemented for Dummy printer.""" """Close not implemented for Dummy printer."""
pass pass

View File

@ -88,12 +88,12 @@ class File(Escpos):
if self.device: if self.device:
self.device.flush() self.device.flush()
def _raw(self, msg): def _raw(self, msg: bytes) -> None:
"""Print any command sent in raw format. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
:type msg: bytes
""" """
assert self.device
self.device.write(msg) self.device.write(msg)
if self.auto_flush: if self.auto_flush:
self.flush() self.flush()

View File

@ -182,7 +182,7 @@ class LP(Escpos):
if not self._is_closing: if not self._is_closing:
self.open(_close_opened=False) self.open(_close_opened=False)
def _raw(self, msg): def _raw(self, msg: bytes) -> None:
"""Write raw command(s) to the printer. """Write raw command(s) to the printer.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed

View File

@ -110,16 +110,18 @@ class Network(Escpos):
return return
logging.info("Network printer enabled") logging.info("Network printer enabled")
def _raw(self, msg): def _raw(self, msg: bytes) -> None:
"""Print any command sent in raw format. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
:type msg: bytes :type msg: bytes
""" """
assert self.device
self.device.sendall(msg) self.device.sendall(msg)
def _read(self): def _read(self) -> bytes:
"""Read data from the TCP socket.""" """Read data from the TCP socket."""
assert self.device
return self.device.recv(16) return self.device.recv(16)
def close(self) -> None: def close(self) -> None:

View File

@ -155,16 +155,18 @@ class Serial(Escpos):
return return
logging.info("Serial printer enabled") logging.info("Serial printer enabled")
def _raw(self, msg): def _raw(self, msg) -> None:
"""Print any command sent in raw format. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
:type msg: bytes :type msg: bytes
""" """
assert self.device
self.device.write(msg) self.device.write(msg)
def _read(self): def _read(self) -> bytes:
"""Read the data buffer and return it to the caller.""" """Read the data buffer and return it to the caller."""
assert self.device
return self.device.read(16) return self.device.read(16)
def close(self) -> None: def close(self) -> None:

View File

@ -181,16 +181,18 @@ class Usb(Escpos):
except usb.core.USBError as e: except usb.core.USBError as e:
logging.error("Could not set configuration: %s", str(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. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed
:type msg: bytes :type msg: bytes
""" """
assert self.device
self.device.write(self.out_ep, msg, self.timeout) 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.""" """Read a data buffer and return it to the caller."""
assert self.device
return self.device.read(self.in_ep, 16) return self.device.read(self.in_ep, 16)
@dependency_usb @dependency_usb

View File

@ -76,7 +76,7 @@ class Win32Raw(Escpos):
return is_usable() return is_usable()
@dependency_win32print @dependency_win32print
def __init__(self, printer_name: str = "", *args, **kwargs): def __init__(self, printer_name: str = "", *args, **kwargs) -> None:
"""Initialize default printer.""" """Initialize default printer."""
Escpos.__init__(self, *args, **kwargs) Escpos.__init__(self, *args, **kwargs)
self.printer_name = printer_name self.printer_name = printer_name
@ -148,7 +148,7 @@ class Win32Raw(Escpos):
win32print.ClosePrinter(self._device) win32print.ClosePrinter(self._device)
self._device = False self._device = False
def _raw(self, msg) -> None: def _raw(self, msg: bytes) -> None:
"""Print any command sent in raw format. """Print any command sent in raw format.
:param msg: arbitrary code to be printed :param msg: arbitrary code to be printed