rewrite cli
This commit is contained in:
parent
81b3c1a63a
commit
99291abd10
519
escpos/cli.py
519
escpos/cli.py
|
@ -1,213 +1,364 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""A simple command-line interface for common python-escpos functionality
|
|
||||||
|
|
||||||
Usage: python -m escpos.cli --help
|
|
||||||
|
|
||||||
Dependencies:
|
|
||||||
- DavisGoglin/python-escpos or better
|
|
||||||
- A file named weather.png (for the 'test' subcommand)
|
|
||||||
|
|
||||||
Reasons for using the DavisGoglin/python-escpos fork:
|
|
||||||
- image() accepts a PIL.Image object rather than requiring me to choose
|
|
||||||
between writing a temporary file to disk or calling a "private" method.
|
|
||||||
- fullimage() allows me to print images of arbitrary length using slicing.
|
|
||||||
|
|
||||||
How to print unsupported barcodes:
|
|
||||||
barcode -b 'BARCODE' -e 'code39' -E | convert -density 200% eps:- code.png
|
|
||||||
python test_escpos.py --images code.png
|
|
||||||
|
|
||||||
Copyright (C) 2014 Stephan Sokolow (deitarion/SSokolow)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
__author__ = "Stephan Sokolow (deitarion/SSokolow)"
|
import argparse
|
||||||
__license__ = "MIT"
|
import sys
|
||||||
|
import serial
|
||||||
import re
|
|
||||||
|
|
||||||
from escpos import printer
|
from escpos import printer
|
||||||
|
from escpos import constants
|
||||||
|
|
||||||
epson = printer.Usb(0x0416, 0x5011)
|
parser = argparse.ArgumentParser(
|
||||||
# TODO: Un-hardcode this
|
description='CLI for python-escpos',
|
||||||
|
epilog='To see help for escpos commands, run with a destination defined.',
|
||||||
|
)
|
||||||
|
dest_subparsers = parser.add_subparsers(
|
||||||
|
title='Destination',
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_dest_file = dest_subparsers.add_parser('file', help='Print to a file')
|
||||||
|
parser_dest_file.set_defaults(func=printer.File)
|
||||||
|
parser_dest_file.add_argument(
|
||||||
|
'--devfile',
|
||||||
|
help='Destination file',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_dest_network = dest_subparsers.add_parser('network', help='Print to a network device')
|
||||||
|
parser_dest_network.set_defaults(func=printer.Network)
|
||||||
|
parser_dest_network.add_argument(
|
||||||
|
'--host',
|
||||||
|
help='Destination host',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
parser_dest_network.add_argument(
|
||||||
|
'--port',
|
||||||
|
help='Destination port',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_network.add_argument(
|
||||||
|
'--timeout',
|
||||||
|
help='Timeout in seconds',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_dest_usb = dest_subparsers.add_parser('usb', help='Print to a usb device')
|
||||||
|
parser_dest_usb.set_defaults(func=printer.Usb)
|
||||||
|
parser_dest_usb.add_argument(
|
||||||
|
'--idVendor',
|
||||||
|
help='USB Vendor ID',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
parser_dest_usb.add_argument(
|
||||||
|
'--idProduct',
|
||||||
|
help='USB Device ID',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
parser_dest_usb.add_argument(
|
||||||
|
'--interface',
|
||||||
|
help='USB device interface',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_usb.add_argument(
|
||||||
|
'--in_ep',
|
||||||
|
help='Input end point',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_usb.add_argument(
|
||||||
|
'--out_ep',
|
||||||
|
help='Output end point',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_dest_serial = dest_subparsers.add_parser(
|
||||||
|
'serial',
|
||||||
|
help='Print to a serial device'
|
||||||
|
)
|
||||||
|
parser_dest_serial.set_defaults(func=printer.Serial)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--devfile',
|
||||||
|
help='Device file'
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--baudrate',
|
||||||
|
help='Baudrate for serial transmission',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--bytesize',
|
||||||
|
help='Serial byte size',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--timeout',
|
||||||
|
help='Read/Write timeout in seconds',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--parity',
|
||||||
|
help='Parity checking',
|
||||||
|
choices=[serial.PARITY_NONE, serial.PARITY_EVEN, serial.PARITY_ODD, serial.PARITY_MARK, serial.PARITY_SPACE],
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--stopbits',
|
||||||
|
help='Number of stopbits',
|
||||||
|
choices=[serial.STOPBITS_ONE, serial.STOPBITS_ONE_POINT_FIVE, serial.STOPBITS_TWO],
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--xonxoff',
|
||||||
|
help='Software flow control',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
parser_dest_serial.add_argument(
|
||||||
|
'--dsrdtr',
|
||||||
|
help='Hardware flow control (False to enable RTS,CTS)',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _print_text_file(path):
|
cmd_parser = argparse.ArgumentParser(
|
||||||
"""Print the given text file"""
|
description='Parser for escpos commands',
|
||||||
epson.set(align='left')
|
usage='{previous command parts} {espos command} ...',
|
||||||
with open(path, 'rU') as fobj:
|
)
|
||||||
for line in fobj:
|
|
||||||
epson.text(line)
|
|
||||||
|
|
||||||
|
command_subparsers = cmd_parser.add_subparsers(
|
||||||
|
title='ESCPOS Command',
|
||||||
|
)
|
||||||
|
|
||||||
def _print_image_file(path):
|
# From here on func needs to be a string, since we don't have a printer to work on yet
|
||||||
"""Print the given image file."""
|
parser_command_qr = command_subparsers.add_parser('qr', help='Print a QR code')
|
||||||
epson.fullimage(path, histeq=False, width=384)
|
parser_command_qr.set_defaults(func='qr')
|
||||||
|
parser_command_qr.add_argument(
|
||||||
|
'--text',
|
||||||
|
help='Text to print as a qr code',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_command_barcode = command_subparsers.add_parser('barcode', help='Print a barcode')
|
||||||
|
parser_command_barcode.set_defaults(func='barcode')
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--code',
|
||||||
|
help='Barcode data to print',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--bc',
|
||||||
|
help='Barcode format',
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--height',
|
||||||
|
help='Barcode height in px',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--width',
|
||||||
|
help='Barcode width',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--pos',
|
||||||
|
help='Label position',
|
||||||
|
choices=['BELOW', 'ABOVE', 'BOTH', 'OFF']
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--font',
|
||||||
|
help='Label font',
|
||||||
|
choices=['A', 'B']
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--align_ct',
|
||||||
|
help='Align barcode center',
|
||||||
|
type=bool,
|
||||||
|
)
|
||||||
|
parser_command_barcode.add_argument(
|
||||||
|
'--function_type',
|
||||||
|
help='ESCPOS function type',
|
||||||
|
choices=['A', 'B']
|
||||||
|
)
|
||||||
|
|
||||||
def print_files(args):
|
parser_command_text = command_subparsers.add_parser('text', help='Print plain text')
|
||||||
"""The 'print' subcommand"""
|
parser_command_text.set_defaults(func='text')
|
||||||
for path in args.paths:
|
parser_command_text.add_argument(
|
||||||
if args.images:
|
'--txt',
|
||||||
_print_image_file(path)
|
help='Text to print',
|
||||||
else:
|
required=True
|
||||||
_print_text_file(path)
|
)
|
||||||
epson.cut()
|
|
||||||
|
|
||||||
# {{{ 'echo' Subcommand
|
parser_command_block_text = command_subparsers.add_parser('block_text', help='Print wrapped text')
|
||||||
|
parser_command_block_text.set_defaults(func='block_text')
|
||||||
|
parser_command_block_text.add_argument(
|
||||||
|
'--txt',
|
||||||
|
help='block_text to print',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
parser_command_block_text.add_argument(
|
||||||
|
'--columns',
|
||||||
|
help='Number of columns',
|
||||||
|
type=int,
|
||||||
|
)
|
||||||
|
|
||||||
KNOWN_BARCODE_TYPES = ['UPC-A', 'UPC-E', 'EAN13', 'ITF']
|
parser_command_cut = command_subparsers.add_parser('cut', help='Cut the paper')
|
||||||
re_barcode_escape = re.compile(r'^%(?P<type>\S+)\s(?P<data>[0-9X]+)$')
|
parser_command_cut.set_defaults(func='cut')
|
||||||
|
parser_command_cut.add_argument(
|
||||||
|
'--mode',
|
||||||
|
help='Type of cut',
|
||||||
|
choices=['FULL', 'PART']
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_command_cashdraw = command_subparsers.add_parser('cashdraw', help='Kick the cash drawer')
|
||||||
|
parser_command_cashdraw.set_defaults(func='cashdraw')
|
||||||
|
parser_command_cashdraw.add_argument(
|
||||||
|
'--pin',
|
||||||
|
help='Which PIN to kick',
|
||||||
|
choices=[2, 5]
|
||||||
|
)
|
||||||
|
|
||||||
def echo(args): # pylint: disable=unused-argument
|
parser_command_image = command_subparsers.add_parser('image', help='Print an image')
|
||||||
"""TTY-like line-by-line keyboard-to-printer echo loop."""
|
parser_command_image.set_defaults(func='image')
|
||||||
try:
|
parser_command_image.add_argument(
|
||||||
while True:
|
'--path_img',
|
||||||
line = raw_input()
|
help='Path to image',
|
||||||
match = re_barcode_escape.match(line)
|
required=True
|
||||||
if match and match.group('type') in KNOWN_BARCODE_TYPES:
|
)
|
||||||
bctype, data = match.groups()
|
|
||||||
epson.barcode(data, bctype, 48, 2, '', '')
|
|
||||||
epson.set(align='left')
|
|
||||||
else:
|
|
||||||
epson.text('{0}\n'.format(line))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
epson.cut()
|
|
||||||
|
|
||||||
# }}}
|
parser_command_fullimage = command_subparsers.add_parser('fullimage', help='Print an fullimage')
|
||||||
# {{{ 'test' Subcommand
|
parser_command_fullimage.set_defaults(func='fullimage')
|
||||||
|
parser_command_fullimage.add_argument(
|
||||||
|
'--img',
|
||||||
|
help='Path to img',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
parser_command_fullimage.add_argument(
|
||||||
|
'--max_height',
|
||||||
|
help='Max height of image in px',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_fullimage.add_argument(
|
||||||
|
'--width',
|
||||||
|
help='Max width of image in px',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_fullimage.add_argument(
|
||||||
|
'--histeq',
|
||||||
|
help='Equalize the histrogram',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
parser_command_fullimage.add_argument(
|
||||||
|
'--bandsize',
|
||||||
|
help='Size of bands to divide into when printing',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
|
||||||
from PIL import Image, ImageDraw
|
# Not supported
|
||||||
|
# parser_command_direct_image = command_subparsers.add_parser('direct_direct_image', help='Print an direct_image')
|
||||||
|
# parser_command_direct_image.set_defaults(func='direct_image')
|
||||||
|
|
||||||
|
parser_command_charcode = command_subparsers.add_parser('charcode', help='Set character code table')
|
||||||
|
parser_command_charcode.set_defaults(func='charcode')
|
||||||
|
parser_command_charcode.add_argument(
|
||||||
|
'--code',
|
||||||
|
help='Character code',
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
def _stall_test(width, height):
|
parser_command_set = command_subparsers.add_parser('set', help='Set text properties')
|
||||||
"""Generate a pattern to detect print glitches due to vertical stalling."""
|
parser_command_set.set_defaults(func='set')
|
||||||
img = Image.new('1', (width, height))
|
parser_command_set.add_argument(
|
||||||
for pos in [(x, y) for y in range(0, height) for x in range(0, width)]:
|
'--align',
|
||||||
img.putpixel(pos, not sum(pos) % 10)
|
help='Horizontal alignment',
|
||||||
return img
|
choices=['left', 'center', 'right']
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--font',
|
||||||
|
help='Font choice',
|
||||||
|
choices=['left', 'center', 'right']
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--text_type',
|
||||||
|
help='Text properties',
|
||||||
|
choices=['B', 'U', 'U2', 'BU', 'BU2', 'NORMAL']
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--width',
|
||||||
|
help='Width multiplier',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--height',
|
||||||
|
help='Height multiplier',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--density',
|
||||||
|
help='Print density',
|
||||||
|
type=int
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--invert',
|
||||||
|
help='White on black printing',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--smooth',
|
||||||
|
help='Text smoothing. Effective on >= 4x4 text',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
parser_command_set.add_argument(
|
||||||
|
'--flip',
|
||||||
|
help='Text smoothing. Effective on >= 4x4 text',
|
||||||
|
type=bool
|
||||||
|
)
|
||||||
|
|
||||||
|
parser_command_hw = command_subparsers.add_parser('hw', help='Hardware operations')
|
||||||
|
parser_command_hw.set_defaults(func='hw')
|
||||||
|
parser_command_hw.add_argument(
|
||||||
|
'--hw',
|
||||||
|
help='Operation',
|
||||||
|
choices=['INIT', 'SELECT', 'RESET'],
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
def _test_basic():
|
parser_command_control = command_subparsers.add_parser('control', help='Control sequences')
|
||||||
"""The original test code from python-escpos's Usage wiki page"""
|
parser_command_control.set_defaults(func='control')
|
||||||
epson.set(align='left')
|
parser_command_control.add_argument(
|
||||||
# Print text
|
'--ctl',
|
||||||
epson.text("TODO:\n") # pylint: disable=fixme
|
help='Control sequence',
|
||||||
epson.text("[ ] Task 1\n")
|
choices=['LF', 'FF', 'CR', 'HT', 'VT'],
|
||||||
epson.text("[ ] Task 2\n")
|
required=True
|
||||||
# Print image
|
)
|
||||||
# TODO: Bundle an image so this can be used
|
parser_command_control.add_argument(
|
||||||
# epson.image("weather.png")
|
'--pos',
|
||||||
# Print QR Code (must have a white border to be scanned)
|
help='Horizontal tab position (1-4)',
|
||||||
epson.set(align='center')
|
type=int
|
||||||
epson.text("Scan to recall TODO list") # pylint: disable=fixme
|
)
|
||||||
epson.qr("http://www.example.com/")
|
|
||||||
# Print barcode
|
|
||||||
epson.barcode('1234567890128', 'EAN13', 32, 2, '', '')
|
|
||||||
# Cut paper
|
|
||||||
epson.cut()
|
|
||||||
|
|
||||||
|
parser_command_panel_buttons = command_subparsers.add_parser('panel_buttons', help='Disables panel buttons')
|
||||||
|
parser_command_panel_buttons.set_defaults(func='panel_buttons')
|
||||||
|
parser_command_panel_buttons.add_argument(
|
||||||
|
'--enable',
|
||||||
|
help='Feed button enabled',
|
||||||
|
type=bool,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
def _test_barcodes():
|
# Get arguments along with function to pass them to
|
||||||
"""Print test barcodes for all ESCPOS-specified formats."""
|
args, rest = parser.parse_known_args()
|
||||||
for name, data in (
|
|
||||||
# pylint: disable=bad-continuation
|
|
||||||
('UPC-A', '123456789012\x00'),
|
|
||||||
('UPC-E', '02345036\x00'),
|
|
||||||
('EAN13', '1234567890128\x00'),
|
|
||||||
('EAN8', '12345670\x00'),
|
|
||||||
('CODE39', 'BARCODE12345678\x00'),
|
|
||||||
('ITF', '123456\x00'),
|
|
||||||
('CODABAR', 'A40156B'),
|
|
||||||
# TODO: CODE93 and CODE128
|
|
||||||
):
|
|
||||||
# TODO: Fix the library to restore old alignment somehow
|
|
||||||
epson.set(align='center')
|
|
||||||
epson.text('\n{0}\n'.format(name))
|
|
||||||
epson.barcode(data, name, 64, 2, '', '')
|
|
||||||
|
|
||||||
|
# filter out function name and non passed arguments
|
||||||
|
func_args = dict((k, v) for k, v in vars(args).iteritems() if v and k != 'func')
|
||||||
|
|
||||||
def _test_patterns(width=384, height=255):
|
# define a printer
|
||||||
"""Print a set of test patterns for raster image output."""
|
p = args.func(**func_args)
|
||||||
# Test our guess of the paper width
|
|
||||||
img = Image.new('1', (width, height), color=1)
|
|
||||||
draw = ImageDraw.Draw(img)
|
|
||||||
draw.polygon(((0, 0), img.size, (0, img.size[1])), fill=0)
|
|
||||||
epson.image(img)
|
|
||||||
del draw, img
|
|
||||||
|
|
||||||
# Test the consistency of printing large data and whether stall rate is
|
if not rest:
|
||||||
# affected by data rate
|
cmd_parser.print_help()
|
||||||
epson.image(_stall_test(width, height))
|
sys.exit(1)
|
||||||
epson.image(_stall_test(width / 2, height))
|
|
||||||
|
|
||||||
|
cmd_args = cmd_parser.parse_args(rest)
|
||||||
|
|
||||||
def test(args):
|
# filter out function name and non passed arguments
|
||||||
"""The 'test' subcommand"""
|
func_args = dict((k, v) for k, v in vars(cmd_args).iteritems() if v and k != 'func')
|
||||||
if args.barcodes:
|
|
||||||
_test_barcodes()
|
|
||||||
elif args.patterns:
|
|
||||||
_test_patterns()
|
|
||||||
else:
|
|
||||||
_test_basic()
|
|
||||||
|
|
||||||
|
# print command with args
|
||||||
# }}}
|
getattr(p, cmd_args.func)(**func_args)
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Wrapped in a function for import and entry point compatibility"""
|
|
||||||
# pylint: disable=bad-continuation
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Command-line interface to python-escpos")
|
|
||||||
subparsers = parser.add_subparsers(title='subcommands')
|
|
||||||
|
|
||||||
echo_parser = subparsers.add_parser('echo', help='Echo the keyboard to '
|
|
||||||
'the printer line-by-line (Exit with Ctrl+C)')
|
|
||||||
echo_parser.set_defaults(func=echo)
|
|
||||||
|
|
||||||
print_parser = subparsers.add_parser('print', help='Print the given files')
|
|
||||||
print_parser.add_argument('--images', action='store_true',
|
|
||||||
help="Provided files are images rather than text files.")
|
|
||||||
print_parser.add_argument('paths', metavar='path', nargs='+')
|
|
||||||
print_parser.set_defaults(func=print_files)
|
|
||||||
|
|
||||||
test_parser = subparsers.add_parser('test', help='Print test patterns')
|
|
||||||
test_modes = test_parser.add_mutually_exclusive_group()
|
|
||||||
test_modes.add_argument('--barcodes', action='store_true',
|
|
||||||
help="Test supported barcode types (Warning: Some printers must be "
|
|
||||||
"reset after attempting an unsupported barcode type.)")
|
|
||||||
test_modes.add_argument('--patterns', action='store_true',
|
|
||||||
help="Print test patterns")
|
|
||||||
test_parser.set_defaults(func=test)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
args.func(args)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
# vim: set sw=4 sts=4 :
|
|
||||||
|
|
Loading…
Reference in New Issue