From df31020d4daee6b8a71d5bdf9b34853cf293917d Mon Sep 17 00:00:00 2001 From: Philipp Klaus Date: Sat, 12 Jan 2019 22:05:04 +0100 Subject: [PATCH] Revert dataclasses based replacement for devicedependent There is a big problem with this commit - it only works with: * Python 3.5 and later due to type hints being introduced with PEP-484 https://www.python.org/dev/peps/pep-0484/ lead to syntax errors on earlier versions. * (even worse) only with Python 3.6+ due to PEP 526 variable annotations (introduced in 3.6) needed by dataclasses too. We aim, however, at Python 2.7 compatibility with this project. So after all, I reverse the commit and will implement the changes in a different way. --- brother_ql/devicedependent.py | 241 +++++++++++++++++++++++----------- brother_ql/helpers.py | 41 ------ brother_ql/labels.py | 109 --------------- brother_ql/models.py | 62 --------- setup.py | 3 - 5 files changed, 163 insertions(+), 293 deletions(-) delete mode 100644 brother_ql/helpers.py delete mode 100644 brother_ql/labels.py delete mode 100644 brother_ql/models.py diff --git a/brother_ql/devicedependent.py b/brother_ql/devicedependent.py index 4990a2a..246af43 100644 --- a/brother_ql/devicedependent.py +++ b/brother_ql/devicedependent.py @@ -1,94 +1,179 @@ -""" -Deprecated Module brother_ql.devicedependent -This module held constants and settings that were specific to -different QL-series printer models and to different label types. +models = [ + 'QL-500', + 'QL-550', + 'QL-560', + 'QL-570', + 'QL-580N', + 'QL-650TD', + 'QL-700', + 'QL-710W', + 'QL-720NW', + 'QL-800', + 'QL-810W', + 'QL-820NWB', + 'QL-1050', + 'QL-1060N', +] -The content is now split into two modules: +min_max_length_dots = { + 'default': (295, 11811), -* brother_ql.models -* brother_ql.labels + # Those are using the default: + # QL-500 QL-550 QL-560 QL-650TD -Please import directly from them as this module will be removed in a future version. -""" + 'QL-1050': (295, 35433), + 'QL-1060N': (295, 35433), -import logging + 'QL-570': (150, 11811), + 'QL-580N': (150, 11811), + 'QL-700': (150, 11811), + 'QL-710W': (150, 11811), + 'QL-720NW': (150, 11811), + 'QL-800': (150, 11811), + 'QL-810W': (150, 11811), + 'QL-820NWB':(150, 11811), +} -logger = logging.getLogger(__name__) +min_max_feed = { + 'default': (35, 1500), +} -logger.warn("deprecation warning: brother_ql.devicedependent is deprecated and will be removed in a future release") -## These module level variables were available here before. -# Concerning labels -DIE_CUT_LABEL = None -ENDLESS_LABEL = None -ROUND_DIE_CUT_LABEL = None -label_type_specs = {} -label_sizes = [] -# And concerning printer models -models = [] -min_max_length_dots = {} -min_max_feed = {} -number_bytes_per_row = {} -right_margin_addition = {} -modesetting = [] -cuttingsupport = [] -expandedmode = [] -compressionsupport = [] -two_color_support = [] +label_sizes = [ + "12", + "29", + "38", + "50", + "54", + "62", + "102", + "17x54", + "17x87", + "23x23", + "29x42", + "29x90", + "39x90", + "39x48", + "52x29", + "62x29", + "62x100", + "102x51", + "102x152", + "d12", + "d24", + "d58", +] -## Let's recreate them using the improved data structures -## in brother_ql.models and brother_ql.labels +# label_types +DIE_CUT_LABEL = 1 +ENDLESS_LABEL = 2 +ROUND_DIE_CUT_LABEL = 3 -def _populate_model_legacy_structures(): - from brother_ql.models import ModelsManager - global models - global min_max_length_dots, min_max_feed, number_bytes_per_row, right_margin_addition - global modesetting, cuttingsupport, expandedmode, compressionsupport, two_color_support +label_type_specs = { + # (width, length) + "12": {'tape_size': ( 12, 0), 'dots_total': ( 142, 0), 'dots_printable': ( 106, 0), 'right_margin_dots': 29, 'feed_margin': 35}, + "29": {'tape_size': ( 29, 0), 'dots_total': ( 342, 0), 'dots_printable': ( 306, 0), 'right_margin_dots': 6, 'feed_margin': 35}, + "38": {'tape_size': ( 38, 0), 'dots_total': ( 449, 0), 'dots_printable': ( 413, 0), 'right_margin_dots': 12, 'feed_margin': 35}, + "50": {'tape_size': ( 50, 0), 'dots_total': ( 590, 0), 'dots_printable': ( 554, 0), 'right_margin_dots': 12, 'feed_margin': 35}, + "54": {'tape_size': ( 54, 0), 'dots_total': ( 636, 0), 'dots_printable': ( 590, 0), 'right_margin_dots': 0, 'feed_margin': 35}, + "62": {'tape_size': ( 62, 0), 'dots_total': ( 732, 0), 'dots_printable': ( 696, 0), 'right_margin_dots': 12, 'feed_margin': 35}, + "102": {'tape_size': (102, 0), 'dots_total': (1200, 0), 'dots_printable': (1164, 0), 'right_margin_dots': 12, 'feed_margin': 35}, + "17x54": {'tape_size': ( 17, 54), 'dots_total': ( 201, 636), 'dots_printable': ( 165, 566), 'right_margin_dots': 0, 'feed_margin': 0}, + "17x87": {'tape_size': ( 17, 87), 'dots_total': ( 201, 1026), 'dots_printable': ( 165, 956), 'right_margin_dots': 0, 'feed_margin': 0}, + "23x23": {'tape_size': ( 23, 23), 'dots_total': ( 272, 272), 'dots_printable': ( 202, 202), 'right_margin_dots': 42, 'feed_margin': 0}, + "29x42": {'tape_size': ( 29, 42), 'dots_total': ( 342, 495), 'dots_printable': ( 306, 425), 'right_margin_dots': 6, 'feed_margin': 0}, + "29x90": {'tape_size': ( 29, 90), 'dots_total': ( 342, 1061), 'dots_printable': ( 306, 991), 'right_margin_dots': 6, 'feed_margin': 0}, + "39x90": {'tape_size': ( 38, 90), 'dots_total': ( 449, 1061), 'dots_printable': ( 413, 991), 'right_margin_dots': 12, 'feed_margin': 0}, + "39x48": {'tape_size': ( 39, 48), 'dots_total': ( 461, 565), 'dots_printable': ( 425, 495), 'right_margin_dots': 6, 'feed_margin': 0}, + "52x29": {'tape_size': ( 52, 29), 'dots_total': ( 614, 341), 'dots_printable': ( 578, 271), 'right_margin_dots': 0, 'feed_margin': 0}, + "62x29": {'tape_size': ( 62, 29), 'dots_total': ( 732, 341), 'dots_printable': ( 696, 271), 'right_margin_dots': 12, 'feed_margin': 0}, + "62x100": {'tape_size': ( 62, 100), 'dots_total': ( 732, 1179), 'dots_printable': ( 696, 1109), 'right_margin_dots': 12, 'feed_margin': 0}, + "102x51": {'tape_size': (102, 51), 'dots_total': (1200, 596), 'dots_printable': (1164, 526), 'right_margin_dots': 12, 'feed_margin': 0}, + "102x152":{'tape_size': (102, 153), 'dots_total': (1200, 1804), 'dots_printable': (1164, 1660), 'right_margin_dots': 12, 'feed_margin': 0}, + "d12": {'tape_size': ( 12, 12), 'dots_total': ( 142, 142), 'dots_printable': ( 94, 94), 'right_margin_dots':113, 'feed_margin': 35}, + "d24": {'tape_size': ( 24, 24), 'dots_total': ( 284, 284), 'dots_printable': ( 236, 236), 'right_margin_dots': 42, 'feed_margin': 0}, + "d58": {'tape_size': ( 58, 58), 'dots_total': ( 688, 688), 'dots_printable': ( 618, 618), 'right_margin_dots': 51, 'feed_margin': 0}, +} - for model in ModelsManager().iter_elements(): - models.append(model.identifier) - min_max_length_dots[model.identifier] = model.min_max_length_dots - min_max_feed[model.identifier] = model.min_max_feed - number_bytes_per_row[model.identifier] = model.number_bytes_per_row - right_margin_addition[model.identifier] = model.additional_offset_r - if model.mode_setting: modesetting.append(model.identifier) - if model.cutting: cuttingsupport.append(model.identifier) - if model.expanded_mode: expandedmode.append(model.identifier) - if model.compression: compressionsupport.append(model.identifier) - if model.two_color: two_color_support.append(model.identifier) +for key in label_type_specs: + # kind + if 'x' in key: + label_type_specs[key]['kind'] = DIE_CUT_LABEL + elif key.startswith('d'): + label_type_specs[key]['kind'] = ROUND_DIE_CUT_LABEL + else: + label_type_specs[key]['kind'] = ENDLESS_LABEL -def _populate_label_legacy_structures(): - """ - We contain this code inside a function so that the imports - we do in here are not visible at the module level. - """ - global DIE_CUT_LABEL, ENDLESS_LABEL, ROUND_DIE_CUT_LABEL - global label_sizes, label_type_specs + # restrict_printers + if '102' in key: + label_type_specs[key]['restrict_printers'] = ['QL-1060N', 'QL-1050'] + else: + label_type_specs[key]['restrict_printers'] = [] - from brother_ql.labels import FormFactor - DIE_CUT_LABEL = FormFactor.DIE_CUT - ENDLESS_LABEL = FormFactor.ENDLESS - ROUND_DIE_CUT_LABEL = FormFactor.ROUND_DIE_CUT + # name + if 'x' in key: + label_type_specs[key]['name'] = '{0}mm x {1}mm die-cut'.format(*label_type_specs[key]['tape_size']) + elif key.startswith('d'): + label_type_specs[key]['name'] = '{0}mm round die-cut'.format(label_type_specs[key]['tape_size'][0]) + else: + label_type_specs[key]['name'] = '{0}mm endless'.format(label_type_specs[key]['tape_size'][0]) - from brother_ql.labels import LabelsManager - lm = LabelsManager() - label_sizes = list(lm.iter_identifiers()) - for label in lm.iter_elements(): - l = {} - l['name'] = label.name - l['kind'] = label.form_factor - l['color'] = label.color - l['tape_size'] = label.tape_size - l['dots_total'] = label.dots_total - l['dots_printable'] = label.dots_printable - l['right_margin_dots'] = label.offset_r - l['feed_margin'] = label.feed_margin - l['restrict_printers'] = label.restricted_to_models - label_type_specs[label.identifier] = l +number_bytes_per_row = { + 'default': 90, + 'QL-1050': 162, + 'QL-1060N': 162, +} -def _populate_all_legacy_structures(): - _populate_label_legacy_structures() - _populate_model_legacy_structures() +right_margin_addition = { + 'default': 0, + 'QL-1050': 44, + 'QL-1060N': 44, +} -_populate_all_legacy_structures() +modesetting = [ + 'QL-580N', + 'QL-650TD', + 'QL-1050', + 'QL-1060N', + 'QL-710W', + 'QL-720NW', + 'QL-800', + 'QL-810W', + 'QL-820NWB', +] + +cuttingsupport = [ + 'QL-550', + 'QL-560', + 'QL-570', + 'QL-580N', + 'QL-650TD', + 'QL-700', + 'QL-1050', + 'QL-1060N', + 'QL-710W', + 'QL-720NW', + 'QL-800', + 'QL-810W', + 'QL-820NWB', +] + +expandedmode = cuttingsupport + +compressionsupport = [ + 'QL-580N', + 'QL-650TD', + 'QL-1050', + 'QL-1060N', + 'QL-710W', + 'QL-720NW', + 'QL-810W', + 'QL-820NWB', +] + +two_color_support = [ + 'QL-800', + 'QL-810W', + 'QL-820NWB', +] diff --git a/brother_ql/helpers.py b/brother_ql/helpers.py deleted file mode 100644 index 089967e..0000000 --- a/brother_ql/helpers.py +++ /dev/null @@ -1,41 +0,0 @@ - -import logging - -logger = logging.getLogger(__name__) - -class ElementsManager(object): - """ - A class managing a collection of 'elements'. - Those elements are expected to be objects that - * can be compared for equality against each other - * have the attribute .identifier - """ - DEFAULT_ELEMENTS = [] - ELEMENT_NAME = "element" - - def __init__(self, elements=None): - if elements: - self._elements = elements - else: - self._elements = self.DEFAULT_ELEMENTS - - def register(self, element, pos=-1): - if element not in self._elements: - if pos == -1: pos = len(self._labels) - self._labels.insert(len(self._labels), label) - else: - logger.warn("Won't register %s as it's already present: %s", self.ELEMENT_NAME, element) - - def deregister(self, element): - if element in self._elements: - self._elements.remove(element) - else: - logger.warn("Trying to deregister a %s that's not registered currently: %s", self.ELEMENT_NAME, label) - - def iter_identifiers(self): - for element in self._elements: - yield element.identifier - - def iter_elements(self): - for element in self._elements: - yield element diff --git a/brother_ql/labels.py b/brother_ql/labels.py deleted file mode 100644 index 8c6bd88..0000000 --- a/brother_ql/labels.py +++ /dev/null @@ -1,109 +0,0 @@ - -from dataclasses import dataclass, field -from typing import List, Tuple -from enum import Enum - -import copy - -from brother_ql.helpers import ElementsManager - -class FormFactor(Enum): - """ - Enumeration representing the form factor of a label. - The labels for the Brother QL series are supplied either as die-cut (pre-sized), or for more flexibility the - continuous label tapes offer the ability to vary the label length. - """ - #: rectangular die-cut labels - DIE_CUT = 1 - #: endless (continouse) labels - ENDLESS = 2 - #: round die-cut labels - ROUND_DIE_CUT = 3 - -class Color(Enum): - """ - Enumeration representing the colors to be printed on a label. Most labels only support printing black on white. - Some newer ones can also print in black and red on white. - """ - #: The label can be printed in black & white. - BLACK_WHITE = 0 - #: The label can be printed in black, white & red. - BLACK_RED_WHITE = 1 - -@dataclass -class Label: - """ - This class represents a label. All specifics of a certain label - and what the rasterizer needs to take care of depending on the - label choosen, should be contained in this class. - """ - #: A string identifier given to each label that can be selected. Eg. '29'. - identifier: str - #: The tape size of a single label (width, lenght) in mm. For endless labels, the length is 0 by definition. - tape_size: Tuple[int, int] - #: The type of label - form_factor: FormFactor - #: The total area (width, length) of the label in dots (@300dpi). - dots_total: Tuple[int, int] - #: The printable area (width, length) of the label in dots (@300dpi). - dots_printable: Tuple[int, int] - #: The required offset from the right side of the label in dots to obtain a centered printout. - offset_r: int - #: An additional amount of feeding when printing the label. - #: This is non-zero for some smaller label sizes and for endless labels. - feed_margin: int = 0 - #: If a label can only be printed with certain label printers, this member variable lists the allowed ones. - #: Otherwise it's an empty list. - restricted_to_models: List[str] = field(default_factory=list) - #: Some labels allow printing in red, most don't. - color: Color = Color.BLACK_WHITE - - def works_with_model(self, model) -> bool: - """ - Method to determine if certain label can be printed by the specified printer model. - """ - if self.restricted_to_models and model not in models: return False - else: return True - - @property - def name(self) -> str: - out = "" - if 'x' in self.identifier: - out = '{0}mm x {1}mm die-cut'.format(*self.tape_size) - elif self.identifier.startswith('d'): - out = '{0}mm round die-cut'.format(self.tape_size[0]) - else: - out = '{0}mm endless'.format(self.tape_size[0]) - if self.color == Color.BLACK_RED_WHITE: - out += ' (black/red/white)' - return out - -ALL_LABELS = ( - Label("12", ( 12, 0), FormFactor.ENDLESS, ( 142, 0), ( 106, 0), 29 , feed_margin=35), - Label("29", ( 29, 0), FormFactor.ENDLESS, ( 342, 0), ( 306, 0), 6 , feed_margin=35), - Label("38", ( 38, 0), FormFactor.ENDLESS, ( 449, 0), ( 413, 0), 12 , feed_margin=35), - Label("50", ( 50, 0), FormFactor.ENDLESS, ( 590, 0), ( 554, 0), 12 , feed_margin=35), - Label("54", ( 54, 0), FormFactor.ENDLESS, ( 636, 0), ( 590, 0), 0 , feed_margin=35), - Label("62", ( 62, 0), FormFactor.ENDLESS, ( 732, 0), ( 696, 0), 12 , feed_margin=35), - Label("62red", ( 62, 0), FormFactor.ENDLESS, ( 732, 0), ( 696, 0), 12 , feed_margin=35, color=Color.BLACK_RED_WHITE), - Label("102", (102, 0), FormFactor.ENDLESS, (1200, 0), (1164, 0), 12 , feed_margin=35, restricted_to_models=['QL-1050', 'QL-1060N']), - Label("17x54", ( 17, 54), FormFactor.DIE_CUT, ( 201, 636), ( 165, 566), 0 ), - Label("17x87", ( 17, 87), FormFactor.DIE_CUT, ( 201, 1026), ( 165, 956), 0 ), - Label("23x23", ( 23, 23), FormFactor.DIE_CUT, ( 272, 272), ( 202, 202), 42 ), - Label("29x42", ( 29, 42), FormFactor.DIE_CUT, ( 342, 495), ( 306, 425), 6 ), - Label("29x90", ( 29, 90), FormFactor.DIE_CUT, ( 342, 1061), ( 306, 991), 6 ), - Label("39x90", ( 38, 90), FormFactor.DIE_CUT, ( 449, 1061), ( 413, 991), 12 ), - Label("39x48", ( 39, 48), FormFactor.DIE_CUT, ( 461, 565), ( 425, 495), 6 ), - Label("52x29", ( 52, 29), FormFactor.DIE_CUT, ( 614, 341), ( 578, 271), 0 ), - Label("62x29", ( 62, 29), FormFactor.DIE_CUT, ( 732, 341), ( 696, 271), 12 ), - Label("62x100", ( 62, 100), FormFactor.DIE_CUT, ( 732, 1179), ( 696, 1109), 12 ), - Label("102x51", (102, 51), FormFactor.DIE_CUT, (1200, 596), (1164, 526), 12 , restricted_to_models=['QL-1050', 'QL-1060N']), - Label("102x152",(102, 153), FormFactor.DIE_CUT, (1200, 1804), (1164, 1660), 12 , restricted_to_models=['QL-1050', 'QL-1060N']), - Label("d12", ( 12, 12), FormFactor.ROUND_DIE_CUT, ( 142, 142), ( 94, 94), 113 , feed_margin=35), - Label("d24", ( 24, 24), FormFactor.ROUND_DIE_CUT, ( 284, 284), ( 236, 236), 42 ), - Label("d58", ( 58, 58), FormFactor.ROUND_DIE_CUT, ( 688, 688), ( 618, 618), 51 ), -) - -class LabelsManager(ElementsManager): - DEFAULT_ELEMENTS = copy.copy(ALL_LABELS) - ELEMENT_NAME = "label" diff --git a/brother_ql/models.py b/brother_ql/models.py deleted file mode 100644 index e2ceee1..0000000 --- a/brother_ql/models.py +++ /dev/null @@ -1,62 +0,0 @@ -from dataclasses import dataclass -from typing import Tuple - -import copy - -from brother_ql.helpers import ElementsManager - -@dataclass -class Model: - """ - This class represents a printer model. All specifics of a certain model - and the opcodes it supports should be contained in this class. - """ - #: A string identifier given to each model implemented. Eg. 'QL-500'. - identifier: str - #: Minimum and maximum number of rows or 'dots' that can be printed. - #: Together with the dpi this gives the minimum and maximum length - #: for continuous tape printing. - min_max_length_dots: Tuple[int, int] - #: The minimum and maximum amount of feeding a label - min_max_feed: Tuple[int, int] = (35, 1500) - number_bytes_per_row: int = 90 - #: The required additional offset from the right side - additional_offset_r: int = 0 - #: Support for the 'mode setting' opcode - mode_setting: bool = True - #: Model has a cutting blade to automatically cut labels - cutting: bool = True - #: Model has support for the 'expanded mode' opcode. - #: (So far, all models that have cutting support do). - expanded_mode: bool = True - #: Model has support for compressing the transmitted raster data. - #: Some models with only USB connectivity don't support compression. - compression: bool = True - #: Support for two color printing (black/red/white) - #: available only on some newer models. - two_color: bool = False - - @property - def name(self) -> str: - return self.identifier - -ALL_MODELS = [ - Model('QL-500', (295, 11811), compression=False, mode_setting=False, expanded_mode=False, cutting=False), - Model('QL-550', (295, 11811), compression=False, mode_setting=False), - Model('QL-560', (295, 11811), compression=False, mode_setting=False), - Model('QL-570', (150, 11811), compression=False, mode_setting=False), - Model('QL-580N', (150, 11811)), - Model('QL-650TD', (295, 11811)), - Model('QL-700', (150, 11811), compression=False, mode_setting=False), - Model('QL-710W', (150, 11811)), - Model('QL-720NW', (150, 11811)), - Model('QL-800', (150, 11811), two_color=True, compression=False), - Model('QL-810W', (150, 11811), two_color=True), - Model('QL-820NWB',(150, 11811), two_color=True), - Model('QL-1050', (295, 35433), number_bytes_per_row=162, additional_offset_r=44), - Model('QL-1060N', (295, 35433), number_bytes_per_row=162, additional_offset_r=44), -] - -class ModelsManager(ElementsManager): - DEFAULT_ELEMENTS = copy.copy(ALL_MODELS) - ELEMENTS_NAME = 'model' diff --git a/setup.py b/setup.py index 1a162d0..edfd252 100644 --- a/setup.py +++ b/setup.py @@ -43,9 +43,6 @@ setup(name='brother_ql', "packbits", "pillow>=3.3.0", "pyusb", - 'dataclasses;python_version<"3.7"', - 'typing;python_version<"3.5"', - 'enum34;python_version<"3.4"', ], extras_require = { #'brother_ql_analyse': ["matplotlib",],