diff --git a/src/escpos/capabilities.py b/src/escpos/capabilities.py index 816c6e9..6e375bc 100644 --- a/src/escpos/capabilities.py +++ b/src/escpos/capabilities.py @@ -15,6 +15,9 @@ class NotSupported(Exception): pass +BARCODE_B = 'barcodeB' + + class BaseProfile(object): """This respresents a printer profile. @@ -43,6 +46,11 @@ class BaseProfile(object): font = self.get_font(font) return self.fonts[six.text_type(font)]['columns'] + def supports(self, feature): + """Return true/false for the given feature. + """ + return self.features.get(feature) + def get_profile(name=None, **kwargs): """Get the profile by name; if no name is given, return the @@ -84,10 +92,11 @@ def clean(s): # For users, who want to provide their profile class Profile(get_profile_class('default')): - def __init__(self, columns=None): - super(Profile, self).__init() + def __init__(self, columns=None, features={}): + super(Profile, self).__init__() self.columns = columns + self.features = features def get_columns(self, font): if self.columns is not None: diff --git a/src/escpos/escpos.py b/src/escpos/escpos.py index 70e5ca1..50e59f8 100644 --- a/src/escpos/escpos.py +++ b/src/escpos/escpos.py @@ -23,7 +23,7 @@ from .exceptions import * from abc import ABCMeta, abstractmethod # abstract base class support from escpos.image import EscposImage -from escpos.capabilities import get_profile +from escpos.capabilities import get_profile, BARCODE_B @six.add_metaclass(ABCMeta) @@ -293,7 +293,8 @@ class Escpos(object): else: raise CharCodeError() - def barcode(self, code, bc, height=64, width=3, pos="BELOW", font="A", align_ct=True, function_type="A"): + def barcode(self, code, bc, height=64, width=3, pos="BELOW", font="A", + align_ct=True, function_type=None): """ Print Barcode This method allows to print barcodes. The rendering of the barcode is done by the printer and therefore has to @@ -364,14 +365,40 @@ class Escpos(object): issued. :type align_ct: bool - :param function_type: Choose between ESCPOS function type A or B, depending on printer support and desired - barcode. + :param function_type: Choose between ESCPOS function type A or B, + depending on printer support and desired barcode. If not given, + the printer will attempt to automatically choose the correct + function based on the current profile. *default*: A :raises: :py:exc:`~escpos.exceptions.BarcodeSizeError`, :py:exc:`~escpos.exceptions.BarcodeTypeError`, :py:exc:`~escpos.exceptions.BarcodeCodeError` """ + if function_type is None: + # Choose the function type automatically. + if bc in BARCODE_TYPES['A']: + function_type = 'A' + else: + 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' + else: + 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 type '{bc}' not valid for barcode function type " + "{function_type}").format( + bc=bc, + function_type=function_type, + )) + # Align Bar Code() if align_ct: self._raw(TXT_ALIGN_CT) @@ -400,14 +427,6 @@ class Escpos(object): else: # DEFAULT POSITION: BELOW self._raw(BARCODE_TXT_BLW) - bc_types = BARCODE_TYPES[function_type.upper()] - if bc.upper() not in bc_types.keys(): - # TODO: Raise a better error, or fix the message of this error type - raise BarcodeTypeError("Barcode type {bc} not valid for barcode function type {function_type}".format( - bc=bc, - function_type=function_type, - )) - self._raw(bc_types[bc.upper()]) if function_type.upper() == "B": diff --git a/test/test_function_barcode.py b/test/test_function_barcode.py new file mode 100644 index 0000000..4205eba --- /dev/null +++ b/test/test_function_barcode.py @@ -0,0 +1,34 @@ +#!/usr/bin/python +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import escpos.printer as printer +from escpos.constants import BARCODE_TYPE_A, BARCODE_TYPE_B +from escpos.capabilities import Profile, BARCODE_B +from escpos.exceptions import BarcodeTypeError +import pytest + + +@pytest.mark.parametrize("bctype,data,expected", [ + ('EAN13', '4006381333931', + b'\x1ba\x01\x1dh@\x1dw\x03\x1df\x00\x1dH\x02\x1dk\x024006381333931\x00') +]) +def test_barcode(bctype, data, expected): + instance = printer.Dummy() + instance.barcode(data, bctype) + assert instance.output == expected + + +@pytest.mark.parametrize("bctype,supports_b", [ + ('invalid', True), + ('CODE128', False), +]) +def test_lacks_support(bctype, supports_b): + profile = Profile(features={BARCODE_B: supports_b}) + instance = printer.Dummy(profile=profile) + with pytest.raises(BarcodeTypeError): + instance.barcode('test', bctype) + + assert instance.output == '' \ No newline at end of file