Skip to content

Commit

Permalink
Added rudimentary API docs built with Sphinx
Browse files Browse the repository at this point in the history
  • Loading branch information
LunarEclipse363 committed Jul 20, 2024
1 parent 0f95932 commit 8405b6c
Show file tree
Hide file tree
Showing 19 changed files with 348 additions and 49 deletions.
9 changes: 6 additions & 3 deletions brother_ql/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3

# Python standard library
from __future__ import print_function
Expand All @@ -13,7 +13,7 @@
# imports from this very package
from brother_ql.models import ModelsManager
from brother_ql.labels import LabelsManager
from brother_ql.backends import available_backends, backend_factory
from brother_ql.backends import available_backends


logger = logging.getLogger('brother_ql')
Expand Down Expand Up @@ -140,6 +140,7 @@ def env(ctx: click.Context, *args, **kwargs):
@click.option('-f', '--format', type=click.Choice(('default', 'json', 'raw_bytes', 'raw_base64', 'raw_hex')), default='default', help='Output Format.')
@click.pass_context
def status_cmd(ctx: click.Context, *args, **kwargs):
""" Prints status information from the chosen printer """
from brother_ql.backends.helpers import status as status_fn
try:
status, raw = status_fn(printer_model=ctx.meta.get('MODEL'), printer_identifier=ctx.meta.get('PRINTER'), backend_identifier=ctx.meta.get('BACKEND'))
Expand Down Expand Up @@ -203,9 +204,10 @@ def print_cmd(ctx: click.Context, *args, **kwargs):
@click.option('-f', '--filename-format', help="Filename format string. Default is: label{counter:04d}.png.")
@click.pass_context
def analyze_cmd(ctx: click.Context, *args, **kwargs):
""" Interprets a binary file containing raster instructions for Brother QL-Series printers """
from brother_ql.reader import BrotherQLReader
reader = BrotherQLReader(kwargs['instructions'])
filename_format = kwargs.get('filename_format')
filename_format = kwargs.get('filename_format')
if filename_format is not None:
reader.filename_fmt = filename_format
reader.analyse()
Expand All @@ -214,6 +216,7 @@ def analyze_cmd(ctx: click.Context, *args, **kwargs):
@click.argument('instructions', type=click.File('rb'))
@click.pass_context
def send_cmd(ctx: click.Context, *args, **kwargs):
""" Sends a raw instructions file to the printer """
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)

Expand Down
38 changes: 25 additions & 13 deletions brother_ql/conversion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/env python
"""
This module offers a high-level API for converting images
into a raster instruction file for the printer.
"""

from __future__ import division, unicode_literals
from builtins import str
Expand All @@ -10,23 +13,20 @@

from brother_ql.raster import BrotherQLRaster
from brother_ql.labels import LabelsManager, FormFactor
from brother_ql.models import ModelsManager
from brother_ql import BrotherQLUnsupportedCmd

logger = logging.getLogger(__name__)

logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING)

def convert(qlr: BrotherQLRaster, images: list[str | Image.Image], label: str, **kwargs):
def convert(qlr: BrotherQLRaster, images: list[str | Image.Image], label: str, **kwargs):
r"""Converts one or more images to a raster instruction file.
:param qlr:
An instance of the BrotherQLRaster class
:type qlr: :py:class:`brother_ql.raster.BrotherQLRaster`
:param images:
The images to be converted. They can be filenames or instances of Pillow's Image.
:type images: list(PIL.Image.Image) or list(str) images
:param str label:
:param label:
Type of label the printout should be on.
:param \**kwargs:
See below
Expand All @@ -36,13 +36,21 @@ def convert(qlr: BrotherQLRaster, images: list[str | Image.Image], label: str,
Enable cutting after printing the labels.
* **dither** (``bool``) --
Instead of applying a threshold to the pixel values, approximate grey tones with dithering.
* **compress**
* **red**
* **rotate**
* **dpi_600**
* **hq**
* **threshold**
* **compress** (``bool``) --
Applies packbits compression to the image data in the raster
* **red** (``bool``) --
Enables generation of a red channel for use with supported printer/label combinations
* **rotate** --
Whether to rotate the image ("auto"|0|90|180|270)
* **dpi_600** (``bool``) --
Whether to enable 300x600dpi mode for supported printers (takes 600x600dpi input image)
* **hq** --
???
* **threshold** (``int``) --
The threshold value to determine if a result pixel is black or white (0-255)
"""
# TODO: seems like `hq` or `pquality` is just not used, you should investigate

label_specs = LabelsManager()[label]

dots_printable = label_specs.dots_printable
Expand Down Expand Up @@ -195,7 +203,11 @@ def convert(qlr: BrotherQLRaster, images: list[str | Image.Image], label: str,


def filtered_hsv(im, filter_h, filter_s, filter_v, default_col=(255,255,255)):
""" https://stackoverflow.com/a/22237709/183995 """
"""
https://stackoverflow.com/a/22237709/183995
:meta private:
"""

hsv_im = im.convert('HSV')
H, S, V = 0, 1, 2
Expand Down
7 changes: 7 additions & 0 deletions brother_ql/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
"""
This module contains all the classes of exceptions that may be raised by brother_ql
"""

class BrotherQLError(Exception):
""" Base class for exceptions from this package """
pass

class BrotherQLUnsupportedCmd(BrotherQLError):
""" Raised when a raster command is not supported with a given printer/label combination """
pass

class BrotherQLUnknownModel(BrotherQLError):
""" Unrecognized printer model """
pass

class BrotherQLRasterError(BrotherQLError):
""" Raised when invalid data is passed to functions on ``brother_ql.raster.BrotherQLRaster`` """
pass
15 changes: 12 additions & 3 deletions brother_ql/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,30 @@ class ElementsManager(object):
* can be compared for equality against each other
* have the attribute .identifier
"""
elements = []
element_name = "element"
elements = [] #: list of elements contained by this manager
element_name = "element" #: what an element is

def iter_identifiers(self):
""" Returns an iterator over the identifiers of all the elements in this manager """
for element in self.elements:
yield element.identifier

def iter_elements(self):
""" Returns an iterator over all the element objects in this manager """
for element in self.elements:
yield element

def identifiers(self):
""" Returns a list of the identifiers of all the elements in this manager """
return list(map(lambda e : e.identifier, self.elements))

def get(self, identifier, default=None):
def get(self, identifier: str, default=None):
"""
Returns the element object with the given identifier, or if it doesn't exist, the default value
:param identifier: the identifier to look for
:param default: what to return if the given identifier is not found
"""
return next(filter(lambda l : l.identifier == identifier, self.elements), default)

def __getitem__(self, key):
Expand Down
10 changes: 8 additions & 2 deletions brother_ql/labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class FormFactor(IntEnum):
"""
#: rectangular die-cut labels
DIE_CUT = 1
#: endless (continouse) labels
#: endless (continuous) labels
ENDLESS = 2
#: round die-cut labels
ROUND_DIE_CUT = 3
Expand Down Expand Up @@ -67,6 +67,9 @@ def works_with_model(self, model: str) -> bool:

@property
def name(self) -> str:
"""
Return a formatted, human-readable name for the label
"""
out = ""

if 'x' in self.identifier:
Expand Down Expand Up @@ -114,7 +117,10 @@ def name(self) -> str:
)

class LabelsManager(ElementsManager):
elements = copy.copy(ALL_LABELS)
"""
Class for accessing the list of supported labels
"""
elements = copy.copy(ALL_LABELS) #: :meta private:
element_name = "label"

def find_label_by_size(self, width: int, height: int):
Expand Down
8 changes: 7 additions & 1 deletion brother_ql/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class Model(object):

@property
def name(self) -> str:
"""
Returns the printer identifier (already human-readable)
"""
return self.identifier

ALL_MODELS = [
Expand All @@ -64,5 +67,8 @@ def name(self) -> str:
]

class ModelsManager(ElementsManager):
elements = copy.copy(ALL_MODELS)
"""
Class for accessing the list of supported printer models
"""
elements = copy.copy(ALL_MODELS) #: :meta private:
element_name = 'model'
26 changes: 19 additions & 7 deletions brother_ql/output_helpers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
"""
Module containing helper functions for printing information in a human-readable format
"""

import logging
from typing import Sequence

from brother_ql.labels import FormFactor, LabelsManager

logger = logging.getLogger(__name__)

def textual_label_description(labels_to_include):
def textual_label_description(label_sizes_to_include: Sequence[str]) -> str:
"""
Returns a textual description of labels with the specified sizes
"""
output = "Supported label sizes:\n"
output = ""
fmt = " {label_size:9s} {dots_printable:14s} {label_descr:26s}\n"
output += fmt.format(label_size="Name", dots_printable="Printable px", label_descr="Description")
#output += fmt.format(label_size="", dots_printable="width x height", label_descr="")
for label_size in labels_to_include:
for label_size in label_sizes_to_include:
label = LabelsManager()[label_size]
if label.form_factor in (FormFactor.DIE_CUT, FormFactor.ROUND_DIE_CUT):
dp_fmt = "{0:4d} x {1:4d}"
Expand All @@ -24,13 +32,17 @@ def textual_label_description(labels_to_include):
return output

def log_discovered_devices(available_devices, level=logging.INFO):
for ad in available_devices:
"""
Logs all automatically discovered devices to console.
"""
for dev in available_devices:
result = {'model': 'unknown'}
result.update(ad)
result.update(dev)
logger.log(level, " Found a label printer: {identifier} (model: {model})".format(**result))

def textual_description_discovered_devices(available_devices):
def textual_description_discovered_devices(available_devices) -> str:
# TODO: figure out what is the type of the argument and document it
output = ""
for ad in available_devices:
output += ad['identifier']
for dev in available_devices:
output += dev['identifier']
return output
19 changes: 14 additions & 5 deletions brother_ql/raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from brother_ql.models import Model, ModelsManager

from . import BrotherQLError, BrotherQLUnsupportedCmd, BrotherQLUnknownModel, BrotherQLRasterError
from brother_ql import BrotherQLError, BrotherQLUnsupportedCmd, BrotherQLUnknownModel, BrotherQLRasterError

from io import BytesIO

Expand Down Expand Up @@ -86,6 +86,7 @@ def _unsupported(self, problem):

@property
def two_color_support(self):
""" :meta private: """
return self.model.two_color

def add_initialize(self):
Expand All @@ -112,16 +113,24 @@ def add_invalidate(self):
self.data += b'\x00' * self.num_invalidate_bytes

@property
def mtype(self): return self._mtype
def mtype(self):
""" :meta private: """
return self._mtype

@property
def mwidth(self): return self._mwidth
def mwidth(self):
""" :meta private: """
return self._mwidth

@property
def mlength(self): return self._mlength
def mlength(self):
""" :meta private: """
return self._mlength

@property
def pquality(self): return self._pquality
def pquality(self):
""" :meta private: """
return self._pquality

@mtype.setter
def mtype(self, value):
Expand Down
Loading

0 comments on commit 8405b6c

Please sign in to comment.