1
0
mirror of https://github.com/python-escpos/python-escpos synced 2025-09-13 09:09:58 +00:00

reformat codebase

This commit is contained in:
Patrick Kanzler
2021-10-30 18:15:22 +02:00
parent 109a5d8a92
commit 435f2bba24
41 changed files with 1706 additions and 1398 deletions

View File

@@ -22,17 +22,51 @@ from barcode.writer import ImageWriter
import os
from .constants import ESC, GS, NUL, QR_ECLEVEL_L, QR_ECLEVEL_M, QR_ECLEVEL_H, QR_ECLEVEL_Q
from .constants import QR_MODEL_1, QR_MODEL_2, QR_MICRO, BARCODE_TYPES, BARCODE_HEIGHT, BARCODE_WIDTH
from .constants import (
ESC,
GS,
NUL,
QR_ECLEVEL_L,
QR_ECLEVEL_M,
QR_ECLEVEL_H,
QR_ECLEVEL_Q,
)
from .constants import (
QR_MODEL_1,
QR_MODEL_2,
QR_MICRO,
BARCODE_TYPES,
BARCODE_HEIGHT,
BARCODE_WIDTH,
)
from .constants import BARCODE_FONT_A, BARCODE_FONT_B, BARCODE_FORMATS
from .constants import BARCODE_TXT_OFF, BARCODE_TXT_BTH, BARCODE_TXT_ABV, BARCODE_TXT_BLW
from .constants import (
BARCODE_TXT_OFF,
BARCODE_TXT_BTH,
BARCODE_TXT_ABV,
BARCODE_TXT_BLW,
)
from .constants import TXT_SIZE, TXT_NORMAL
from .constants import SET_FONT
from .constants import LINESPACING_FUNCS, LINESPACING_RESET
from .constants import LINE_DISPLAY_OPEN, LINE_DISPLAY_CLEAR, LINE_DISPLAY_CLOSE
from .constants import CD_KICK_DEC_SEQUENCE, CD_KICK_5, CD_KICK_2, PAPER_FULL_CUT, PAPER_PART_CUT
from .constants import (
CD_KICK_DEC_SEQUENCE,
CD_KICK_5,
CD_KICK_2,
PAPER_FULL_CUT,
PAPER_PART_CUT,
)
from .constants import HW_RESET, HW_SELECT, HW_INIT
from .constants import CTL_VT, CTL_CR, CTL_FF, CTL_LF, CTL_SET_HT, PANEL_BUTTON_OFF, PANEL_BUTTON_ON
from .constants import (
CTL_VT,
CTL_CR,
CTL_FF,
CTL_LF,
CTL_SET_HT,
PANEL_BUTTON_OFF,
PANEL_BUTTON_ON,
)
from .constants import TXT_STYLE
from .constants import RT_STATUS_ONLINE, RT_MASK_ONLINE
from .constants import RT_STATUS_PAPER, RT_MASK_PAPER, RT_MASK_LOWPAPER, RT_MASK_NOPAPER
@@ -50,27 +84,28 @@ from escpos.capabilities import get_profile, BARCODE_B
@six.add_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
class.
"""
device = None
def __init__(self, profile=None, magic_encode_args=None, **kwargs):
""" Initialize ESCPOS Printer
"""Initialize ESCPOS Printer
:param profile: Printer profile"""
self.profile = get_profile(profile)
self.magic = MagicEncode(self, **(magic_encode_args or {}))
def __del__(self):
""" call self.close upon deletion """
"""call self.close upon deletion"""
self.close()
@abstractmethod
def _raw(self, msg):
""" Sends raw data to the printer
"""Sends raw data to the printer
This function has to be individually implemented by the implementations.
@@ -80,14 +115,21 @@ class Escpos(object):
pass
def _read(self):
""" 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.
:raises NotImplementedError
"""
raise NotImplementedError()
def image(self, img_source, high_density_vertical=True, high_density_horizontal=True, impl="bitImageRaster",
fragment_height=960, center=False):
""" Print an image
def image(
self,
img_source,
high_density_vertical=True,
high_density_horizontal=True,
impl="bitImageRaster",
fragment_height=960,
center=False,
):
"""Print an image
You can select whether the printer should print in high density or not. The default value is high density.
When printing in low density, the image will be stretched.
@@ -116,14 +158,16 @@ class Escpos(object):
im = EscposImage(img_source)
try:
if self.profile.profile_data['media']['width']['pixels'] == "Unknown":
print("The media.width.pixel field of the printer profile is not set. " +
"The center flag will have no effect.")
if self.profile.profile_data["media"]["width"]["pixels"] == "Unknown":
print(
"The media.width.pixel field of the printer profile is not set. "
+ "The center flag will have no effect."
)
max_width = int(self.profile.profile_data['media']['width']['pixels'])
max_width = int(self.profile.profile_data["media"]["width"]["pixels"])
if im.width > max_width:
raise ImageWidthError('{} > {}'.format(im.width, max_width))
raise ImageWidthError("{} > {}".format(im.width, max_width))
if center:
im.center(max_width)
@@ -137,41 +181,59 @@ class Escpos(object):
if im.height > fragment_height:
fragments = im.split(fragment_height)
for fragment in fragments:
self.image(fragment,
high_density_vertical=high_density_vertical,
high_density_horizontal=high_density_horizontal,
impl=impl,
fragment_height=fragment_height)
self.image(
fragment,
high_density_vertical=high_density_vertical,
high_density_horizontal=high_density_horizontal,
impl=impl,
fragment_height=fragment_height,
)
return
if impl == "bitImageRaster":
# GS v 0, raster format bit image
density_byte = (0 if high_density_horizontal else 1) + (0 if high_density_vertical else 2)
header = GS + b"v0" + six.int2byte(density_byte) + self._int_low_high(im.width_bytes, 2) +\
self._int_low_high(im.height, 2)
density_byte = (0 if high_density_horizontal else 1) + (
0 if high_density_vertical else 2
)
header = (
GS
+ b"v0"
+ six.int2byte(density_byte)
+ self._int_low_high(im.width_bytes, 2)
+ self._int_low_high(im.height, 2)
)
self._raw(header + im.to_raster_format())
if impl == "graphics":
# GS ( L raster format graphics
img_header = self._int_low_high(im.width, 2) + self._int_low_high(im.height, 2)
tone = b'0'
colors = b'1'
img_header = self._int_low_high(im.width, 2) + self._int_low_high(
im.height, 2
)
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)
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)
self._image_send_graphics_data(b'0', b'2', b'')
self._image_send_graphics_data(b"0", b"p", header + raster_data)
self._image_send_graphics_data(b"0", b"2", b"")
if impl == "bitImageColumn":
# ESC *, column format bit image
density_byte = (1 if high_density_horizontal else 0) + (32 if high_density_vertical else 0)
header = ESC + b"*" + six.int2byte(density_byte) + self._int_low_high(im.width, 2)
density_byte = (1 if high_density_horizontal else 0) + (
32 if high_density_vertical else 0
)
header = (
ESC
+ b"*"
+ six.int2byte(density_byte)
+ self._int_low_high(im.width, 2)
)
outp = [ESC + b"3" + six.int2byte(16)] # Adjust line-feed size
for blob in im.to_column_format(high_density_vertical):
outp.append(header + blob + b"\n")
outp.append(ESC + b"2") # Reset line-feed size
self._raw(b''.join(outp))
self._raw(b"".join(outp))
def _image_send_graphics_data(self, m, fn, data):
"""
@@ -182,11 +244,19 @@ class Escpos(object):
:param data: Data to send
"""
header = self._int_low_high(len(data) + 2, 2)
self._raw(GS + b'(L' + header + m + fn + data)
self._raw(GS + b"(L" + header + m + fn + data)
def qr(self, content, ec=QR_ECLEVEL_L, size=3, model=QR_MODEL_2,
native=False, center=False, impl="bitImageRaster"):
""" Print QR Code for the provided string
def qr(
self,
content,
ec=QR_ECLEVEL_L,
size=3,
model=QR_MODEL_2,
native=False,
center=False,
impl="bitImageRaster",
):
"""Print QR Code for the provided string
:param content: The content of the code. Numeric data will be more efficiently compacted.
:param ec: Error-correction level to use. One of QR_ECLEVEL_L (default), QR_ECLEVEL_M, QR_ECLEVEL_Q or
@@ -206,50 +276,60 @@ class Escpos(object):
if not 1 <= size <= 16:
raise ValueError("Invalid block size (must be 1-16)")
if model not in [QR_MODEL_1, QR_MODEL_2, QR_MICRO]:
raise ValueError("Invalid QR model (must be one of QR_MODEL_1, QR_MODEL_2, QR_MICRO)")
raise ValueError(
"Invalid QR model (must be one of QR_MODEL_1, QR_MODEL_2, QR_MICRO)"
)
if content == "":
# Handle edge case by printing nothing.
return
if not native:
# Map ESC/POS error correction levels to python 'qrcode' library constant and render to an image
if model != QR_MODEL_2:
raise ValueError("Invalid QR model for qrlib rendering (must be QR_MODEL_2)")
raise ValueError(
"Invalid QR model for qrlib rendering (must be QR_MODEL_2)"
)
python_qr_ec = {
QR_ECLEVEL_H: qrcode.constants.ERROR_CORRECT_H,
QR_ECLEVEL_L: qrcode.constants.ERROR_CORRECT_L,
QR_ECLEVEL_M: qrcode.constants.ERROR_CORRECT_M,
QR_ECLEVEL_Q: qrcode.constants.ERROR_CORRECT_Q
QR_ECLEVEL_Q: qrcode.constants.ERROR_CORRECT_Q,
}
qr_code = qrcode.QRCode(version=None, box_size=size, border=1, error_correction=python_qr_ec[ec])
qr_code = qrcode.QRCode(
version=None, box_size=size, border=1, error_correction=python_qr_ec[ec]
)
qr_code.add_data(content)
qr_code.make(fit=True)
qr_img = qr_code.make_image()
im = qr_img._img.convert("RGB")
# Convert the RGB image in printable image
self.text('\n')
self.text("\n")
self.image(im, center=center, impl=impl)
self.text('\n')
self.text('\n')
self.text("\n")
self.text("\n")
return
if center:
raise NotImplementedError("Centering not implemented for native QR rendering")
raise NotImplementedError(
"Centering not implemented for native QR rendering"
)
# Native 2D code printing
cn = b'1' # Code type for QR code
cn = b"1" # Code type for QR code
# Select model: 1, 2 or micro.
self._send_2d_code_data(six.int2byte(65), cn, six.int2byte(48 + model) + six.int2byte(0))
self._send_2d_code_data(
six.int2byte(65), cn, six.int2byte(48 + model) + six.int2byte(0)
)
# Set dot size.
self._send_2d_code_data(six.int2byte(67), cn, six.int2byte(size))
# Set error correction level: L, M, Q, or H
self._send_2d_code_data(six.int2byte(69), cn, six.int2byte(48 + ec))
# Send content & print
self._send_2d_code_data(six.int2byte(80), cn, content.encode('utf-8'), b'0')
self._send_2d_code_data(six.int2byte(81), cn, b'', b'0')
self._send_2d_code_data(six.int2byte(80), cn, content.encode("utf-8"), b"0")
self._send_2d_code_data(six.int2byte(81), cn, b"", b"0")
def _send_2d_code_data(self, fn, cn, data, m=b''):
""" Wrapper for GS ( k, to calculate and send correct data length.
def _send_2d_code_data(self, fn, cn, data, m=b""):
"""Wrapper for GS ( k, to calculate and send correct data length.
:param fn: Function to use.
:param cn: Output code type. Affects available data.
@@ -259,28 +339,32 @@ class Escpos(object):
if len(m) > 1 or len(cn) != 1 or len(fn) != 1:
raise ValueError("cn and fn must be one byte each.")
header = self._int_low_high(len(data) + len(m) + 2, 2)
self._raw(GS + b'(k' + header + cn + fn + m + data)
self._raw(GS + b"(k" + header + cn + fn + m + data)
@staticmethod
def _int_low_high(inp_number, out_bytes):
""" Generate multiple bytes for a number: In lower and higher parts, or more parts as needed.
"""Generate multiple bytes for a number: In lower and higher parts, or more parts as needed.
:param inp_number: Input number
:param out_bytes: The number of bytes to output (1 - 4).
"""
max_input = (256 << (out_bytes * 8) - 1)
max_input = 256 << (out_bytes * 8) - 1
if not 1 <= out_bytes <= 4:
raise ValueError("Can only output 1-4 bytes")
if not 0 <= inp_number <= max_input:
raise ValueError("Number too large. Can only output up to {0} in {1} bytes".format(max_input, out_bytes))
outp = b''
raise ValueError(
"Number too large. Can only output up to {0} in {1} bytes".format(
max_input, out_bytes
)
)
outp = b""
for _ in range(0, out_bytes):
outp += six.int2byte(inp_number % 256)
inp_number //= 256
return outp
def charcode(self, code="AUTO"):
""" Set Character Code Table
"""Set Character Code Table
Sets the control sequence from ``CHARCODE`` in :py:mod:`escpos.constants` as active. It will be sent with
the next text sequence. If you set the variable code to ``AUTO`` it will try to automatically guess the
@@ -318,11 +402,23 @@ class Escpos(object):
return False
bounds, regex = BARCODE_FORMATS[bc]
return any(bound[0] <= len(code) <= bound[1] for bound in bounds) and re_match(regex, code)
return any(bound[0] <= len(code) <= bound[1] for bound in bounds) and re_match(
regex, code
)
def barcode(self, code, bc, height=64, width=3, pos="BELOW", font="A",
align_ct=True, function_type=None, check=True):
""" Print Barcode
def barcode(
self,
code,
bc,
height=64,
width=3,
pos="BELOW",
font="A",
align_ct=True,
function_type=None,
check=True,
):
"""Print Barcode
This method allows to print barcodes. The rendering of the barcode is done by the printer and therefore has to
be supported by the unit. By default, this method will check whether your barcode text is correct, that is
@@ -407,38 +503,46 @@ class Escpos(object):
"""
if function_type is None:
# Choose the function type automatically.
if bc in BARCODE_TYPES['A']:
function_type = 'A'
if bc in BARCODE_TYPES["A"]:
function_type = "A"
else:
if bc in BARCODE_TYPES['B']:
if bc in BARCODE_TYPES["B"]:
if not self.profile.supports(BARCODE_B):
raise BarcodeTypeError((
"Barcode type '{bc} not supported for "
"the current printer profile").format(bc=bc))
function_type = 'B'
raise BarcodeTypeError(
(
"Barcode type '{bc} not supported for "
"the current printer profile"
).format(bc=bc)
)
function_type = "B"
else:
raise BarcodeTypeError((
"Barcode type '{bc} is not valid").format(bc=bc))
raise BarcodeTypeError(
("Barcode type '{bc} is not valid").format(bc=bc)
)
bc_types = BARCODE_TYPES[function_type.upper()]
if bc.upper() not in bc_types.keys():
raise BarcodeTypeError((
"Barcode '{bc}' not valid for barcode function type "
"{function_type}").format(
raise BarcodeTypeError(
(
"Barcode '{bc}' not valid for barcode function type "
"{function_type}"
).format(
bc=bc,
function_type=function_type,
))
)
)
if check and not self.check_barcode(bc, code):
raise BarcodeCodeError((
"Barcode '{code}' not in a valid format for type '{bc}'").format(
code=code,
bc=bc,
))
raise BarcodeCodeError(
("Barcode '{code}' not in a valid format for type '{bc}'").format(
code=code,
bc=bc,
)
)
# Align Bar Code()
if align_ct:
self._raw(TXT_STYLE['align']['center'])
self._raw(TXT_STYLE["align"]["center"])
# Height
if 1 <= height <= 255:
self._raw(BARCODE_HEIGHT + six.int2byte(height))
@@ -478,35 +582,47 @@ class Escpos(object):
if function_type.upper() == "A":
self._raw(NUL)
def soft_barcode(self, barcode_type, data, impl='bitImageColumn',
module_height=5, module_width=0.2, text_distance=1,
center=True):
def soft_barcode(
self,
barcode_type,
data,
impl="bitImageColumn",
module_height=5,
module_width=0.2,
text_distance=1,
center=True,
):
image_writer = ImageWriter()
# Check if barcode type exists
if barcode_type not in barcode.PROVIDED_BARCODES:
raise BarcodeTypeError(
'Barcode type {} not supported by software barcode renderer'
.format(barcode_type))
"Barcode type {} not supported by software barcode renderer".format(
barcode_type
)
)
# Render the barcode to a fake file
barcode_class = barcode.get_barcode_class(barcode_type)
my_code = barcode_class(data, writer=image_writer)
with open(os.devnull, "wb") as nullfile:
my_code.write(nullfile, {
'module_height': module_height,
'module_width': module_width,
'text_distance': text_distance
})
my_code.write(
nullfile,
{
"module_height": module_height,
"module_width": module_width,
"text_distance": text_distance,
},
)
# Retrieve the Pillow image and print it
image = my_code.writer._image
self.image(image, impl=impl, center=center)
def text(self, txt):
""" Print alpha-numeric text
"""Print alpha-numeric text
The text has to be encoded in the currently selected codepage.
The input text has to be encoded in unicode.
@@ -517,7 +633,7 @@ class Escpos(object):
txt = six.text_type(txt)
self.magic.write(txt)
def textln(self, txt=''):
def textln(self, txt=""):
"""Print alpha-numeric text with a newline
The text has to be encoded in the currently selected codepage.
@@ -526,7 +642,7 @@ class Escpos(object):
:param txt: text to be printed with a newline
:raises: :py:exc:`~escpos.exceptions.TextError`
"""
self.text('{}\n'.format(txt))
self.text("{}\n".format(txt))
def ln(self, count=1):
"""Print a newline or more
@@ -535,12 +651,12 @@ class Escpos(object):
:raises: :py:exc:`ValueError` if count < 0
"""
if count < 0:
raise ValueError('Count cannot be lesser than 0')
raise ValueError("Count cannot be lesser than 0")
if count > 0:
self.text('\n' * count)
self.text("\n" * count)
def block_text(self, txt, font="0", columns=None):
""" Text is printed wrapped to specified columns
"""Text is printed wrapped to specified columns
Text has to be encoded in unicode.
@@ -552,10 +668,23 @@ class Escpos(object):
col_count = self.profile.get_columns(font) if columns is None else columns
self.text(textwrap.fill(txt, col_count))
def set(self, align='left', font='a', bold=False, underline=0, width=1,
height=1, density=9, invert=False, smooth=False, flip=False,
double_width=False, double_height=False, custom_size=False):
""" Set text properties by sending them to the printer
def set(
self,
align="left",
font="a",
bold=False,
underline=0,
width=1,
height=1,
density=9,
invert=False,
smooth=False,
flip=False,
double_width=False,
double_height=False,
custom_size=False,
):
"""Set text properties by sending them to the printer
:param align: horizontal position for text, possible values are:
@@ -596,37 +725,41 @@ class Escpos(object):
"""
if custom_size:
if 1 <= width <= 8 and 1 <= height <= 8 and isinstance(width, int) and\
isinstance(height, int):
size_byte = TXT_STYLE['width'][width] + TXT_STYLE['height'][height]
if (
1 <= width <= 8
and 1 <= height <= 8
and isinstance(width, int)
and isinstance(height, int)
):
size_byte = TXT_STYLE["width"][width] + TXT_STYLE["height"][height]
self._raw(TXT_SIZE + six.int2byte(size_byte))
else:
raise SetVariableError()
else:
self._raw(TXT_NORMAL)
if double_width and double_height:
self._raw(TXT_STYLE['size']['2x'])
self._raw(TXT_STYLE["size"]["2x"])
elif double_width:
self._raw(TXT_STYLE['size']['2w'])
self._raw(TXT_STYLE["size"]["2w"])
elif double_height:
self._raw(TXT_STYLE['size']['2h'])
self._raw(TXT_STYLE["size"]["2h"])
else:
self._raw(TXT_STYLE['size']['normal'])
self._raw(TXT_STYLE["size"]["normal"])
self._raw(TXT_STYLE['flip'][flip])
self._raw(TXT_STYLE['smooth'][smooth])
self._raw(TXT_STYLE['bold'][bold])
self._raw(TXT_STYLE['underline'][underline])
self._raw(TXT_STYLE["flip"][flip])
self._raw(TXT_STYLE["smooth"][smooth])
self._raw(TXT_STYLE["bold"][bold])
self._raw(TXT_STYLE["underline"][underline])
self._raw(SET_FONT(six.int2byte(self.profile.get_font(font))))
self._raw(TXT_STYLE['align'][align])
self._raw(TXT_STYLE["align"][align])
if density != 9:
self._raw(TXT_STYLE['density'][density])
self._raw(TXT_STYLE["density"][density])
self._raw(TXT_STYLE['invert'][invert])
self._raw(TXT_STYLE["invert"][invert])
def line_spacing(self, spacing=None, divisor=180):
""" Set line character spacing.
"""Set line character spacing.
If no spacing is given, we reset it to the default.
@@ -646,16 +779,19 @@ class Escpos(object):
if divisor not in LINESPACING_FUNCS:
raise ValueError("divisor must be either 360, 180 or 60")
if (divisor in [360, 180]
and (not(0 <= spacing <= 255))):
raise ValueError("spacing must be a int between 0 and 255 when divisor is 360 or 180")
if divisor == 60 and (not(0 <= spacing <= 85)):
raise ValueError("spacing must be a int between 0 and 85 when divisor is 60")
if divisor in [360, 180] and (not (0 <= spacing <= 255)):
raise ValueError(
"spacing must be a int between 0 and 255 when divisor is 360 or 180"
)
if divisor == 60 and (not (0 <= spacing <= 85)):
raise ValueError(
"spacing must be a int between 0 and 85 when divisor is 60"
)
self._raw(LINESPACING_FUNCS[divisor] + six.int2byte(spacing))
def cut(self, mode='FULL', feed=True):
""" Cut paper.
def cut(self, mode="FULL", feed=True):
"""Cut paper.
Without any arguments the paper will be cut completely. With 'mode=PART' a partial cut will
be attempted. Note however, that not all models can do a partial cut. See the documentation of
@@ -667,28 +803,28 @@ class Escpos(object):
"""
if not feed:
self._raw(GS + b'V' + six.int2byte(66) + b'\x00')
self._raw(GS + b"V" + six.int2byte(66) + b"\x00")
return
self.print_and_feed(6)
mode = mode.upper()
if mode not in ('FULL', 'PART'):
if mode not in ("FULL", "PART"):
raise ValueError("Mode must be one of ('FULL', 'PART')")
if mode == "PART":
if self.profile.supports('paperPartCut'):
if self.profile.supports("paperPartCut"):
self._raw(PAPER_PART_CUT)
elif self.profile.supports('paperFullCut'):
elif self.profile.supports("paperFullCut"):
self._raw(PAPER_FULL_CUT)
elif mode == "FULL":
if self.profile.supports('paperFullCut'):
if self.profile.supports("paperFullCut"):
self._raw(PAPER_FULL_CUT)
elif self.profile.supports('paperPartCut'):
elif self.profile.supports("paperPartCut"):
self._raw(PAPER_PART_CUT)
def cashdraw(self, pin):
""" Send pulse to kick the cash drawer
"""Send pulse to kick the cash drawer
Kick cash drawer on pin 2 or pin 5 according to default parameter.
For non default parameter send a decimal sequence i.e. [27,112,48] or [27,112,0,25,255]
@@ -707,7 +843,7 @@ class Escpos(object):
raise CashDrawerError(err)
def linedisplay_select(self, select_display=False):
""" Selects the line display or the printer
"""Selects the line display or the printer
This method is used for line displays that are daisy-chained between your computer and printer.
If you set `select_display` to true, only the display is selected and if you set it to false,
@@ -722,7 +858,7 @@ class Escpos(object):
self._raw(LINE_DISPLAY_CLOSE)
def linedisplay_clear(self):
""" Clears the line display and resets the cursor
"""Clears the line display and resets the cursor
This method is used for line displays that are daisy-chained between your computer and printer.
"""
@@ -743,7 +879,7 @@ class Escpos(object):
self.linedisplay_select(select_display=False)
def hw(self, hw):
""" Hardware operations
"""Hardware operations
:param hw: hardware action, may be:
@@ -761,12 +897,12 @@ class Escpos(object):
pass
def print_and_feed(self, n=1):
""" Print data in print buffer and feed *n* lines
"""Print data in print buffer and feed *n* lines
if n not in range (0, 255) then ValueError will be raised
if n not in range (0, 255) then ValueError will be raised
:param n: number of n to feed. 0 <= n <= 255. default: 1
:raises ValueError: if not 0 <= n <= 255
:param n: number of n to feed. 0 <= n <= 255. default: 1
:raises ValueError: if not 0 <= n <= 255
"""
if 0 <= n <= 255:
# ESC d n
@@ -775,7 +911,7 @@ class Escpos(object):
raise ValueError("n must be betwen 0 and 255")
def control(self, ctl, count=5, tab_size=8):
""" Feed control sequences
"""Feed control sequences
:param ctl: string for the following control sequences:
@@ -797,9 +933,9 @@ class Escpos(object):
elif ctl.upper() == "CR":
self._raw(CTL_CR)
elif ctl.upper() == "HT":
if not (0 <= count <= 32 and
1 <= tab_size <= 255 and
count * tab_size < 256):
if not (
0 <= count <= 32 and 1 <= tab_size <= 255 and count * tab_size < 256
):
raise TabPosError()
else:
# Set tab positions
@@ -811,7 +947,7 @@ class Escpos(object):
self._raw(CTL_VT)
def panel_buttons(self, enable=True):
""" Controls the panel buttons on the printer (e.g. FEED)
"""Controls the panel buttons on the printer (e.g. FEED)
When enable is set to False the panel buttons on the printer will be disabled. Calling the method with
enable=True or without argument will enable the panel buttons.
@@ -872,11 +1008,11 @@ class Escpos(object):
status = self.query_status(RT_STATUS_PAPER)
if len(status) == 0:
return 2
if (status[0] & RT_MASK_NOPAPER == RT_MASK_NOPAPER):
if status[0] & RT_MASK_NOPAPER == RT_MASK_NOPAPER:
return 0
if (status[0] & RT_MASK_LOWPAPER == RT_MASK_LOWPAPER):
if status[0] & RT_MASK_LOWPAPER == RT_MASK_LOWPAPER:
return 1
if (status[0] & RT_MASK_PAPER == RT_MASK_PAPER):
if status[0] & RT_MASK_PAPER == RT_MASK_PAPER:
return 2
@@ -913,7 +1049,7 @@ class EscposIO(object):
self.autoclose = autoclose
def set(self, **kwargs):
""" Set the printer-parameters
"""Set the printer-parameters
Controls which parameters will be passed to :py:meth:`Escpos.set() <escpos.escpos.Escpos.set()>`.
For more information on the parameters see the :py:meth:`set() <escpos.escpos.Escpos.set()>`-methods
@@ -929,11 +1065,13 @@ class EscposIO(object):
params.update(kwargs)
if isinstance(text, six.text_type):
lines = text.split('\n')
lines = text.split("\n")
elif isinstance(text, list) or isinstance(text, tuple):
lines = text
else:
lines = ["{0}".format(text), ]
lines = [
"{0}".format(text),
]
# TODO check unicode handling
# TODO flush? or on print? (this should prob rather be handled by the _raw-method)
@@ -945,8 +1083,7 @@ class EscposIO(object):
self.printer.text("{0}\n".format(line))
def close(self):
""" called upon closing the `with`-statement
"""
"""called upon closing the `with`-statement"""
self.printer.close()
def __enter__(self, **kwargs):