Merge pull request #136 from python-escpos/feature/mosquito-compatibility

Feature/mosquito compatibility
This commit is contained in:
Patrick Kanzler 2016-06-19 11:46:47 +02:00 committed by GitHub
commit adf73f3790
5 changed files with 157 additions and 8 deletions

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
""" Set of ESC/POS Commands (Constants)
This module contains constants that are described in the esc/pos-documentation.

View File

@ -1,4 +1,5 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
""" Main class
This module contains the abstract base class :py:class:`Escpos`.
@ -31,6 +32,7 @@ class Escpos(object):
class.
"""
device = None
codepage = None
def __init__(self, columns=32):
""" Initialize ESCPOS Printer
@ -38,6 +40,10 @@ class Escpos(object):
:param columns: Text columns used by the printer. Defaults to 32."""
self.columns = columns
def __del__(self):
""" call self.close upon deletion """
self.close()
@abstractmethod
def _raw(self, msg):
""" Sends raw data to the printer
@ -202,48 +208,71 @@ class Escpos(object):
:param code: Name of CharCode
:raises: :py:exc:`~escpos.exceptions.CharCodeError`
"""
# TODO improve this (rather unhandy code)
# TODO check the codepages
if code.upper() == "USA":
self._raw(CHARCODE_PC437)
self.codepage = 'cp437'
elif code.upper() == "JIS":
self._raw(CHARCODE_JIS)
self.codepage = 'cp932'
elif code.upper() == "MULTILINGUAL":
self._raw(CHARCODE_PC850)
self.codepage = 'cp850'
elif code.upper() == "PORTUGUESE":
self._raw(CHARCODE_PC860)
self.codepage = 'cp860'
elif code.upper() == "CA_FRENCH":
self._raw(CHARCODE_PC863)
self.codepage = 'cp863'
elif code.upper() == "NORDIC":
self._raw(CHARCODE_PC865)
self.codepage = 'cp865'
elif code.upper() == "WEST_EUROPE":
self._raw(CHARCODE_WEU)
self.codepage = 'latin_1'
elif code.upper() == "GREEK":
self._raw(CHARCODE_GREEK)
self.codepage = 'cp737'
elif code.upper() == "HEBREW":
self._raw(CHARCODE_HEBREW)
self.codepage = 'cp862'
# elif code.upper() == "LATVIAN": # this is not listed in the constants
# self._raw(CHARCODE_PC755)
# self.codepage = 'cp'
elif code.upper() == "WPC1252":
self._raw(CHARCODE_PC1252)
self.codepage = 'cp1252'
elif code.upper() == "CIRILLIC2":
self._raw(CHARCODE_PC866)
self.codepage = 'cp866'
elif code.upper() == "LATIN2":
self._raw(CHARCODE_PC852)
self.codepage = 'cp852'
elif code.upper() == "EURO":
self._raw(CHARCODE_PC858)
self.codepage = 'cp858'
elif code.upper() == "THAI42":
self._raw(CHARCODE_THAI42)
self.codepage = 'cp874'
elif code.upper() == "THAI11":
self._raw(CHARCODE_THAI11)
self.codepage = 'cp874'
elif code.upper() == "THAI13":
self._raw(CHARCODE_THAI13)
self.codepage = 'cp874'
elif code.upper() == "THAI14":
self._raw(CHARCODE_THAI14)
self.codepage = 'cp874'
elif code.upper() == "THAI16":
self._raw(CHARCODE_THAI16)
self.codepage = 'cp874'
elif code.upper() == "THAI17":
self._raw(CHARCODE_THAI17)
self.codepage = 'cp874'
elif code.upper() == "THAI18":
self._raw(CHARCODE_THAI18)
self.codepage = 'cp874'
else:
raise CharCodeError()
@ -380,13 +409,15 @@ class Escpos(object):
""" Print alpha-numeric text
The text has to be encoded in the currently selected codepage.
.. todo:: rework this in order to proberly handle encoding
The input text has to be encoded in unicode.
:param txt: text to be printed
:raises: :py:exc:`~escpos.exceptions.TextError`
"""
if txt:
if self.codepage:
self._raw(txt.encode(self.codepage))
else:
self._raw(txt.encode())
else:
# TODO: why is it problematic to print an empty string?
@ -395,6 +426,8 @@ class Escpos(object):
def block_text(self, txt, columns=None):
""" Text is printed wrapped to specified columns
Text has to be encoded in unicode.
:param txt: text to be printed
:param columns: amount of columns
:return: None
@ -620,3 +653,89 @@ class Escpos(object):
self._raw(PANEL_BUTTON_ON)
else:
self._raw(PANEL_BUTTON_OFF)
class EscposIO(object):
"""ESC/POS Printer IO object
Allows the class to be used together with the `with`-statement. You have to define a printer instance
and assign it to the EsposIO-class.
This example explains the usage:
.. code-block:: Python
with EscposIO(printer.Serial('/dev/ttyUSB0')) as p:
p.set(font='a', height=2, align='center', text_type='bold')
p.printer.set(align='left')
p.printer.image('logo.gif')
p.writelines('Big line\\n', font='b')
p.writelines('Привет')
p.writelines('BIG TEXT', width=2)
After the `with`-statement the printer automatically cuts the paper if `autocut` is `True`.
"""
def __init__(self, printer, autocut=True, autoclose=True, **kwargs):
"""
:param printer: An EscPos-printer object
:type printer: escpos.Escpos
:param autocut: If True, paper is automatically cut after the `with`-statement *default*: True
:param kwargs: These arguments will be passed to :py:meth:`escpos.Escpos.set()`
"""
self.printer = printer
self.params = kwargs
self.autocut = autocut
self.autoclose = autoclose
def set(self, **kwargs):
""" Set the printer-parameters
Controls which parameters will be passed to :py:meth:`Escpos.set() <escpos.escpos.Escpos.set()>`.
For more information on the parameters see the :py:meth:`set() <escpos.escpos.Escpos.set()>`-methods
documentation. These parameters can also be passed with this class' constructor or the
:py:meth:`~escpos.escpos.EscposIO.writelines()`-method.
:param kwargs: keyword-parameters that will be passed to :py:meth:`Escpos.set() <escpos.escpos.Escpos.set()>`
"""
self.params.update(kwargs)
def writelines(self, text, **kwargs):
params = dict(self.params)
params.update(kwargs)
if isinstance(text, six.text_type):
lines = text.split('\n')
elif isinstance(text, list) or isinstance(text, tuple):
lines = text
else:
lines = ["{0}".format(text), ]
# TODO check unicode handling
# TODO flush? or on print? (this should prob rather be handled by the _raw-method)
for line in lines:
self.printer.set(**params)
if isinstance(text, six.text_type):
self.printer.text(u"{0}\n".format(line))
else:
self.printer.text("{0}\n".format(line))
def close(self):
""" called upon closing the `with`-statement
"""
self.printer.close()
def __enter__(self, **kwargs):
return self
def __exit__(self, type, value, traceback):
"""
If :py:attr:`autocut <escpos.escpos.EscposIO.autocut>` is `True` (set by this class' constructor),
then :py:meth:`printer.cut() <escpos.escpos.Escpos.cut()>` will be called here.
"""
if not (type is not None and issubclass(type, Exception)):
if self.autocut:
self.printer.cut()
if self.autoclose:
self.close()

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
""" ESC/POS Exceptions classes
Result/Exit codes:

View File

@ -1,5 +1,6 @@
#!/usr/bin/python
""" This module contains the implentations of abstract base class :py:class:`Escpos`.
# -*- coding: utf-8 -*-
""" This module contains the implementations of abstract base class :py:class:`Escpos`.
:author: `Manuel F Martinez <manpaz@bashlinux.com>`_ and others
:organization: Bashlinux and `python-escpos <https://github.com/python-escpos>`_
@ -82,7 +83,7 @@ class Usb(Escpos):
"""
self.device.write(self.out_ep, msg, self.interface)
def __del__(self):
def close(self):
""" Release USB interface """
if self.device:
usb.util.dispose_resources(self.device)
@ -147,7 +148,7 @@ class Serial(Escpos):
"""
self.device.write(msg)
def __del__(self):
def close(self):
""" Close Serial interface """
if self.device is not None:
self.device.flush()
@ -207,7 +208,7 @@ class Network(Escpos):
"""
self.device.sendall(msg)
def __del__(self):
def close(self):
""" Close TCP connection """
self.device.shutdown(socket.SHUT_RDWR)
self.device.close()
@ -255,7 +256,7 @@ class File(Escpos):
"""
self.device.write(msg)
def __del__(self):
def close(self):
""" Close system file """
self.device.flush()
self.device.close()
@ -294,3 +295,6 @@ class Dummy(Escpos):
def output(self):
""" Get the data that was sent to this printer """
return b''.join(self._output_list)
def close(self):
pass

View File

@ -0,0 +1,24 @@
#!/usr/bin/python
"""test the facility which enables usage of the with-statement
:author: `Patrick Kanzler <patrick.kanzler@fablab.fau.de>`_
:organization: `python-escpos <https://github.com/python-escpos>`_
:copyright: Copyright (c) 2016 `python-escpos <https://github.com/python-escpos>`_
:license: GNU GPL v3
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import escpos.printer as printer
import escpos.escpos as escpos
import os
def test_with_statement():
"""Use with statement"""
dummy_printer = printer.Dummy()
with escpos.EscposIO(dummy_printer) as p:
p.writelines('Some text.\n')
# TODO extend these tests as they don't really do anything at the moment