File: cli.py

package info (click to toggle)
python-brother-ql 0.9.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 276 kB
  • sloc: python: 1,640; makefile: 4
file content (167 lines) | stat: -rwxr-xr-x 7,780 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env python

# Python standard library
from __future__ import print_function
import logging

# external dependencies
import click

# imports from this very package
from brother_ql.devicedependent import models, label_sizes, label_type_specs, DIE_CUT_LABEL, ENDLESS_LABEL, ROUND_DIE_CUT_LABEL
from brother_ql.backends import available_backends, backend_factory


logger = logging.getLogger('brother_ql')


printer_help = "The identifier for the printer. This could be a string like tcp://192.168.1.21:9100 for a networked printer or usb://0x04f9:0x2015/000M6Z401370 for a printer connected via USB."
@click.group()
@click.option('-b', '--backend', type=click.Choice(available_backends), envvar='BROTHER_QL_BACKEND')
@click.option('-m', '--model', type=click.Choice(models), envvar='BROTHER_QL_MODEL')
@click.option('-p', '--printer', metavar='PRINTER_IDENTIFIER', envvar='BROTHER_QL_PRINTER', help=printer_help)
@click.option('--debug', is_flag=True)
@click.version_option()
@click.pass_context
def cli(ctx, *args, **kwargs):
    """ Command line interface for the brother_ql Python package. """

    backend = kwargs.get('backend', None)
    model = kwargs.get('model', None)
    printer = kwargs.get('printer', None)
    debug = kwargs.get('debug')

    # Store the general CLI options in the context meta dictionary.
    # The name corresponds to the second half of the respective envvar:
    ctx.meta['MODEL'] = model
    ctx.meta['BACKEND'] = backend
    ctx.meta['PRINTER'] = printer

    logging.basicConfig(level='DEBUG' if debug else 'INFO')

@cli.command()
@click.pass_context
def discover(ctx):
    """ find connected label printers """
    backend = ctx.meta.get('BACKEND', 'pyusb')
    discover_and_list_available_devices(backend)

def discover_and_list_available_devices(backend):
    from brother_ql.backends.helpers import discover
    available_devices = discover(backend_identifier=backend)
    from brother_ql.output_helpers import log_discovered_devices, textual_description_discovered_devices
    log_discovered_devices(available_devices)
    print(textual_description_discovered_devices(available_devices))

@cli.group()
@click.pass_context
def info(ctx, *args, **kwargs):
    """ list available labels, models etc. """

@info.command(name='models')
@click.pass_context
def models_cmd(ctx, *args, **kwargs):
    """
    List the choices for --model
    """
    print('Supported models:')
    for model in models: print(" " + model)

@info.command()
@click.pass_context
def labels(ctx, *args, **kwargs):
    """
    List the choices for --label
    """
    from brother_ql.output_helpers import textual_label_description
    print(textual_label_description(label_sizes))

@info.command()
@click.pass_context
def env(ctx, *args, **kwargs):
    """
    print debug info about running environment
    """
    import sys, platform, os, shutil
    from pkg_resources import get_distribution, working_set
    print("\n##################\n")
    print("Information about the running environment of brother_ql.")
    print("(Please provide this information when reporting any issue.)\n")
    # computer
    print("About the computer:")
    for attr in ('platform', 'processor', 'release', 'system', 'machine', 'architecture'):
        print('  * '+attr.title()+':', getattr(platform, attr)())
    # Python
    print("About the installed Python version:")
    py_version = str(sys.version).replace('\n', ' ')
    print("  *", py_version)
    # brother_ql
    print("About the brother_ql package:")
    pkg = get_distribution('brother_ql')
    print("  * package location:", pkg.location)
    print("  * package version: ", pkg.version)
    try:
        cli_loc = shutil.which('brother_ql')
    except:
        cli_loc = 'unknown'
    print("  * brother_ql CLI path:", cli_loc)
    # brother_ql's requirements
    print("About the requirements of brother_ql:")
    fmt = "  {req:14s} | {spec:10s} | {ins_vers:17s}"
    print(fmt.format(req='requirement', spec='requested', ins_vers='installed version'))
    print(fmt.format(req='-' * 14, spec='-'*10, ins_vers='-'*17))
    requirements = list(pkg.requires())
    requirements.sort(key=lambda x: x.project_name)
    for req in requirements:
        proj = req.project_name
        req_pkg = get_distribution(proj)
        spec = ' '.join(req.specs[0]) if req.specs else 'any'
        print(fmt.format(req=proj, spec=spec, ins_vers=req_pkg.version))
    print("\n##################\n")

@cli.command('print', short_help='Print a label')
@click.argument('images', nargs=-1, type=click.File('rb'), metavar='IMAGE [IMAGE] ...')
@click.option('-l', '--label', type=click.Choice(label_sizes), envvar='BROTHER_QL_LABEL', help='The label (size, type - die-cut or endless). Run `brother_ql info labels` for a full list including ideal pixel dimensions.')
@click.option('-r', '--rotate', type=click.Choice(('auto', '0', '90', '180', '270')), default='auto', help='Rotate the image (counterclock-wise) by this amount of degrees.')
@click.option('-t', '--threshold', type=float, default=70.0, help='The threshold value (in percent) to discriminate between black and white pixels.')
@click.option('-d', '--dither', is_flag=True, help='Enable dithering when converting the image to b/w. If set, --threshold is meaningless.')
@click.option('-c', '--compress', is_flag=True, help='Enable compression (if available with the model). Label creation can take slightly longer but the resulting instruction size is normally considerably smaller.')
@click.option('--red', is_flag=True, help='Create a label to be printed on black/red/white tape (only with QL-8xx series on DK-22251 labels). You must use this option when printing on black/red tape, even when not printing red.')
@click.option('--600dpi', 'dpi_600', is_flag=True, help='Print with 600x300 dpi available on some models. Provide your image as 600x600 dpi; perpendicular to the feeding the image will be resized to 300dpi.')
@click.option('--lq', is_flag=True, help='Print with low quality (faster). Default is high quality.')
@click.option('--no-cut', is_flag=True, help="Don't cut the tape after printing the label.")
@click.pass_context
def print_cmd(ctx, *args, **kwargs):
    """ Print a label of the provided IMAGE. """
    backend = ctx.meta.get('BACKEND', 'pyusb')
    model = ctx.meta.get('MODEL')
    printer = ctx.meta.get('PRINTER')
    from brother_ql.conversion import convert
    from brother_ql.backends.helpers import send
    from brother_ql.raster import BrotherQLRaster
    qlr = BrotherQLRaster(model)
    qlr.exception_on_warning = True
    kwargs['cut'] = not kwargs['no_cut']
    del kwargs['no_cut']
    instructions = convert(qlr=qlr, **kwargs)
    send(instructions=instructions, printer_identifier=printer, backend_identifier=backend, blocking=True)

@cli.command(name='analyze', help='interpret a binary file containing raster instructions for the Brother QL-Series printers')
@click.argument('instructions', type=click.File('rb'))
@click.option('-f', '--filename-format', help="Filename format string. Default is: label{counter:04d}.png.")
@click.pass_context
def analyze_cmd(ctx, *args, **kwargs):
    from brother_ql.reader import BrotherQLReader
    br = BrotherQLReader(kwargs.get('instructions'))
    if kwargs.get('filename_format'): br.filename_fmt = kwargs.get('filename_format')
    br.analyse()

@cli.command(name='send', short_help='send an instruction file to the printer')
@click.argument('instructions', type=click.File('rb'))
@click.pass_context
def send_cmd(ctx, *args, **kwargs):
    from brother_ql.backends.helpers import send
    send(instructions=kwargs['instructions'].read(), printer_identifier=ctx.meta.get('PRINTER'), backend_identifier=ctx.meta.get('BACKEND'), blocking=True)

if __name__ == '__main__':
    cli()