diff --git a/doc/api.rst b/doc/api.rst deleted file mode 100644 index a3b00b1..0000000 --- a/doc/api.rst +++ /dev/null @@ -1,46 +0,0 @@ -escpos package -============== - -Submodules ----------- - -escpos.constants module ------------------------ - -.. automodule:: escpos.constants - :members: - :undoc-members: - :show-inheritance: - -escpos.escpos module --------------------- - -.. automodule:: escpos.escpos - :members: - :undoc-members: - :show-inheritance: - -escpos.exceptions module ------------------------- - -.. automodule:: escpos.exceptions - :members: - :undoc-members: - :show-inheritance: - -escpos.printer module ---------------------- - -.. automodule:: escpos.printer - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: escpos - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/api/constants.rst b/doc/api/constants.rst new file mode 100644 index 0000000..0165d61 --- /dev/null +++ b/doc/api/constants.rst @@ -0,0 +1,10 @@ +Constants +--------- +Module :py:mod:`escpos.constants` + +.. automodule:: escpos.constants + :members: + :inherited-members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/doc/api/escpos.rst b/doc/api/escpos.rst new file mode 100644 index 0000000..2a85256 --- /dev/null +++ b/doc/api/escpos.rst @@ -0,0 +1,10 @@ +Esc/Pos +------- +Module :py:mod:`escpos.escpos` + +.. automodule:: escpos.escpos + :members: + :inherited-members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/doc/api/exceptions.rst b/doc/api/exceptions.rst new file mode 100644 index 0000000..6edb5ea --- /dev/null +++ b/doc/api/exceptions.rst @@ -0,0 +1,9 @@ +Exceptions +---------- +Module :py:mod:`escpos.exceptions` + +.. automodule:: escpos.exceptions + :members: + :inherited-members: + :show-inheritance: + :member-order: bysource \ No newline at end of file diff --git a/doc/api/printer.rst b/doc/api/printer.rst new file mode 100644 index 0000000..98654cb --- /dev/null +++ b/doc/api/printer.rst @@ -0,0 +1,10 @@ +Printer implementations +----------------------- +Module :py:mod:`escpos.printer` + +.. automodule:: escpos.printer + :members: + :inherited-members: + :undoc-members: + :show-inheritance: + :member-order: bysource diff --git a/doc/index.rst b/doc/index.rst index 14cd7be..031189f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -25,8 +25,8 @@ sending my PayPal info so you can donate. Thank you! -User Documentation: -------------------- +User Documentation +------------------ .. toctree:: :maxdepth: 1 @@ -39,13 +39,16 @@ User Documentation: user/todo user/usage -API: ----- +API +--- .. toctree:: :maxdepth: 1 - api + api/escpos + api/printer + api/constants + api/exceptions Indices and tables ================== diff --git a/doc/user/methods.rst b/doc/user/methods.rst index b4ce495..976bde6 100644 --- a/doc/user/methods.rst +++ b/doc/user/methods.rst @@ -2,7 +2,8 @@ Methods ******* -.. note:: **TODO** Merge this page into the API-description. +.. note:: **TODO** Merge this page with the API-description. (Make the API-description more pretty and then + replace this with the API-description.) Escpos class ------------ diff --git a/doc/user/todo.rst b/doc/user/todo.rst index 3777a7d..2a54df8 100644 --- a/doc/user/todo.rst +++ b/doc/user/todo.rst @@ -21,6 +21,7 @@ Testing ~~~~~~~ * Test on many printers as possible (USB, Serial, Network) +* automate testing Design ~~~~~~ @@ -32,4 +33,6 @@ Design * Windows compatibility (hidapi instead libusb?) * PDF417 support +* use something similar to the `capabilities` in escpos-php + diff --git a/escpos/constants.py b/escpos/constants.py index af71c48..67c6e3b 100644 --- a/escpos/constants.py +++ b/escpos/constants.py @@ -1,4 +1,14 @@ -""" ESC/POS Commands (Constants) """ +""" Set of ESC/POS Commands (Constants) + +This module contains constants that are described in the esc/pos-documentation. +Since there is no definitive and unified specification for all esc/pos-like printers the constants could later be +moved to `capabilities` as in `escpos-php by @mike42 `_. + +:author: `Manuel F Martinez `_ and others +:organization: Bashlinux and `python-escpos `_ +:copyright: Copyright (c) 2012 Bashlinux +:license: GNU GPL v3 +""" # Feed control sequences CTL_LF = '\x0a' # Print and line feed diff --git a/escpos/escpos.py b/escpos/escpos.py index 65b673e..1622df3 100644 --- a/escpos/escpos.py +++ b/escpos/escpos.py @@ -1,9 +1,12 @@ #!/usr/bin/python -""" -@author: Manuel F Martinez -@organization: Bashlinux -@copyright: Copyright (c) 2012 Bashlinux -@license: GNU GPL v3 +""" Main class + +This module contains the abstract base class :py:class:`Escpos`. + +:author: `Manuel F Martinez `_ and others +:organization: Bashlinux and `python-escpos `_ +:copyright: Copyright (c) 2012 Bashlinux +:license: GNU GPL v3 """ try: @@ -22,11 +25,14 @@ from .exceptions import * from abc import ABCMeta, abstractmethod # abstract base class support class Escpos(object): - """ ESC/POS Printer object """ + """ ESC/POS Printer object + + This class is the abstract base class for an esc/pos-printer. The printer implementations are children of this + class. + """ __metaclass__ = ABCMeta device = None - def __init__(self, columns=32): """ Initialize ESCPOS Printer @@ -38,6 +44,7 @@ class Escpos(object): """ Sends raw data to the printer This function has to be individually implemented by the implementations. + :param msg: message string to be sent to the printer """ pass @@ -88,7 +95,7 @@ class Escpos(object): """ Parse image and prepare it to a printable format :param im: image data - :raises: ImageSizeError + :raises: :py:exc:`~escpos.exceptions.ImageSizeError` """ pixels = [] pix_line = "" @@ -135,9 +142,11 @@ class Escpos(object): self._print_image(pix_line, img_size) def image(self, path_img): - """ Open image file + """ Open and print an image file - :param path_img: path to image + Prints an image. The image is automatically adjusted in size in order to print it. + + :param path_img: complete filename and path to image of type `jpg`, `gif`, `png` or `bmp` """ im_open = Image.open(path_img) @@ -153,7 +162,10 @@ class Escpos(object): self._convert_image(im) def direct_image(self, image): - """ Send image to printer""" + """ Send image to printer + + :param image: + """ mask = 0x80 i = 0 temp = 0 @@ -188,6 +200,9 @@ class Escpos(object): def qr(self, text): """ Print QR Code for the provided string + Prints a QR-code. The size has been adjusted to version 4, so it is small enough to be + printed but also big enough to be read by a smartphone. + :param text: text to generate a QR-Code from """ qr_code = qrcode.QRCode(version=4, box_size=4, border=1) @@ -202,10 +217,11 @@ class Escpos(object): def charcode(self, code): """ Set Character Code Table - Sends the control sequence from constants.py to the printer with :py:meth:`escpos.printer._raw()`. + Sends the control sequence from :py:mod:`escpos.constants` to the printer + with :py:meth:`escpos.printer.'implementation'._raw()`. :param code: Name of CharCode - :raises: CharCodeError + :raises: :py:exc:`~escpos.exceptions.CharCodeError` """ if code.upper() == "USA": self._raw(CHARCODE_PC437) @@ -255,13 +271,37 @@ class Escpos(object): def barcode(self, code, bc, width, height, pos, font): """ Print Barcode - :param code: data for barcode - :param bc: barcode format, see constants.py + :param code: alphanumeric data to be printed as bar code + :param bc: barcode format, possible values are: + + * UPC-A + * UPC-E + * EAN13 + * EAN8 + * CODE39 + * ITF + * NW7 + + If none is specified, the method raises :py:exc:`~escpos.exceptions.BarcodeTypeError`. :param width: barcode width, has to be between 1 and 255 + *default*: 64 :param height: barcode height, has to be between 2 and 6 - :param pos: position of text in barcode, default when nothing supplied is below - :param font: select font, default is font A - :raises: BarcodeSizeError, BarcodeTypeError, BarcodeCodeError + *default*: 3 + :param pos: where to place the text relative to the barcode, *default*: below + + * ABOVE + * BELOW + * BOTH + * OFF + + :param font: select font (see ESC/POS-documentation, the device often has two fonts), *default*: A + + * A + * B + + :raises: :py:exc:`~escpos.exceptions.BarcodeSizeError`, + :py:exc:`~escpos.exceptions.BarcodeTypeError`, + :py:exc:`~escpos.exceptions.BarcodeCodeError` """ # Align Bar Code() self._raw(TXT_ALIGN_CT) @@ -316,28 +356,51 @@ class Escpos(object): """ Print alpha-numeric text The text has to be encoded in the currently selected codepage. + :param txt: text to be printed - :raises: TextError + :raises: :py:exc:`~escpos.exceptions.TextError` """ if txt: self._raw(txt) else: + # TODO: why is it problematic to print an empty string? raise TextError() def block_text(self, txt, columns=None): - '''Text is printed wrapped to specified columns''' + """ Text is printed wrapped to specified columns + + :param txt: text to be printed + :param columns: amount of columns + :return: None + """ colCount = self.columns if columns == None else columns self.text(textwrap.fill(txt, colCount)) def set(self, align='left', font='a', text_type='normal', width=1, height=1, density=9): """ Set text properties by sending them to the printer - :param align: alignment of text - :param font: font A or B - :param text_type: add bold or underlined - :param width: text width, normal or double width - :param height: text height, normal or double height - :param density: print density + :param align: horizontal position for text, possible values are: + + * CENTER + * LEFT + * RIGHT + + *default*: LEFT + :param font: font type, possible values are A or B, *default*: A + :param text_type: text type, possible values are: + + * B for bold + * U for underlined + * B2 for bold, version 2 + * U2 for underlined, version 2 + * BU for bold and underlined + * BU2 for bold and underlined, version 2 + * NORMAL for normal text + + *default*: NORMAL + :param width: text width, normal (1) or double width (2), *default*: 1 + :param height: text height, normal (1) or double height (2), *default*: 2 + :param density: print density, value from 0-8, if something else is supplied the density remains unchanged """ # Width if height == 2 and width == 2: @@ -420,9 +483,10 @@ class Escpos(object): def cashdraw(self, pin): """ Send pulse to kick the cash drawer - Kick cash drawer on pin 2 or pin 5. - :param pin: pin number - :raises: CashDrawerError + Kick cash drawer on pin 2 or pin 5 according to parameter. + + :param pin: pin number, 2 or 5 + :raises: :py:exc:`~escpos.exceptions.CashDrawerError` """ if pin == 2: self._raw(CD_KICK_2) @@ -434,7 +498,11 @@ class Escpos(object): def hw(self, hw): """ Hardware operations - :param hw: hardware action + :param hw: hardware action, may be: + + * INIT + * SELECT + * RESET """ if hw.upper() == "INIT": self._raw(HW_INIT) @@ -448,7 +516,16 @@ class Escpos(object): def control(self, ctl, pos=4): """ Feed control sequences - :raises: TabPosError + :param ctl: string for the following control sequences: + + * LF *for Line Feed* + * FF *for Form Feed* + * CR *for Carriage Return* + * HT *for Horizontal Tab* + * VT *for Vertical Tab* + + :param pos: integer between 1 and 16, controls the horizontal tab position + :raises: :py:exc:`~escpos.exceptions.TabPosError` """ # Set tab positions if pos < 1 or pos > 16: diff --git a/escpos/exceptions.py b/escpos/exceptions.py index 8235943..bb72e24 100644 --- a/escpos/exceptions.py +++ b/escpos/exceptions.py @@ -1,4 +1,22 @@ -""" ESC/POS Exceptions classes """ +""" ESC/POS Exceptions classes + +Result/Exit codes: + + - `0` = success + - `10` = No Barcode type defined :py:exc:`~escpos.exceptions.BarcodeTypeError` + - `20` = Barcode size values are out of range :py:exc:`~escpos.exceptions.BarcodeSizeError` + - `30` = Barcode text not supplied :py:exc:`~escpos.exceptions.BarcodeCodeError` + - `40` = Image height is too large :py:exc:`~escpos.exceptions.ImageSizeError` + - `50` = No string supplied to be printed :py:exc:`~escpos.exceptions.TextError` + - `60` = Invalid pin to send Cash Drawer pulse :py:exc:`~escpos.exceptions.CashDrawerError` + - `70` = Invalid number of tab positions :py:exc:`~escpos.exceptions.TabPosError` + - `80` = Invalid char code :py:exc:`~escpos.exceptions.CharCodeError` + +:author: `Manuel F Martinez `_ and others +:organization: Bashlinux and `python-escpos `_ +:copyright: Copyright (c) 2012 Bashlinux +:license: GNU GPL v3 +""" class Error(Exception): @@ -13,20 +31,14 @@ class Error(Exception): def __str__(self): return self.msg -# Result/Exit codes -# 0 = success -# 10 = No Barcode type defined -# 20 = Barcode size values are out of range -# 30 = Barcode text not supplied -# 40 = Image height is too large -# 50 = No string supplied to be printed -# 60 = Invalid pin to send Cash Drawer pulse -# 70 = Invalid number of tab positions -# 80 = Invalid char code - class BarcodeTypeError(Error): - """No Barcode type defined """ + """ No Barcode type defined. + + This exception indicates that no known barcode-type has been entered. The barcode-type has to be + one of those specified in :py:meth:`escpos.escpos.Escpos.barcode`. + The returned error code is `10`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -37,7 +49,12 @@ class BarcodeTypeError(Error): class BarcodeSizeError(Error): - """ Barcode size is out of range """ + """ Barcode size is out of range. + + This exception indicates that the values for the barcode size are out of range. + The size of the barcode has to be in the range that is specified in :py:meth:`escpos.escpos.Escpos.barcode`. + The resulting returncode is `20`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -48,7 +65,11 @@ class BarcodeSizeError(Error): class BarcodeCodeError(Error): - """ No Barcode code was supplied """ + """ No Barcode code was supplied. + + No data for the barcode has been supplied in :py:meth:`escpos.escpos.Escpos.barcode`. + The returncode for this exception is `30`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -59,7 +80,10 @@ class BarcodeCodeError(Error): class ImageSizeError(Error): - """ Image height is longer than 255px and can't be printed """ + """ Image height is longer than 255px and can't be printed. + + The returncode for this exception is `40`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -70,7 +94,11 @@ class ImageSizeError(Error): class TextError(Error): - """ Test sting must be supplied to the text() method """ + """ Text string must be supplied to the `text()` method. + + This exception is raised when an empty string is passed to :py:meth:`escpos.escpos.Escpos.text`. + The returncode for this exception is `50`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -81,7 +109,11 @@ class TextError(Error): class CashDrawerError(Error): - """ Valid pin must be set to send pulse """ + """ Valid pin must be set in order to send pulse. + + A valid pin number has to be passed onto the method :py:meth:`escpos.escpos.Escpos.cashdraw`. + The returncode for this exception is `60`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -92,7 +124,11 @@ class CashDrawerError(Error): class TabPosError(Error): - """ Valid tab positions must be in the range 0 to 16 """ + """ Valid tab positions must be in the range 0 to 16. + + This exception is raised by :py:meth:`escpos.escpos.Escpos.control`. + The returncode for this exception is `70`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg @@ -103,11 +139,15 @@ class TabPosError(Error): class CharCodeError(Error): - """ Valid char code must be set """ + """ Valid char code must be set. + + The supplied charcode-name in :py:meth:`escpos.escpos.Escpos.charcode` is unknown. + Ths returncode for this exception is `80`. + """ def __init__(self, msg=""): Error.__init__(self, msg) self.msg = msg - self.resultcode = 70 + self.resultcode = 80 def __str__(self): return "Valid char code must be set" diff --git a/escpos/printer.py b/escpos/printer.py index bf6dbe5..1c3f92f 100644 --- a/escpos/printer.py +++ b/escpos/printer.py @@ -1,9 +1,10 @@ #!/usr/bin/python -""" -@author: Manuel F Martinez -@organization: Bashlinux -@copyright: Copyright (c) 2012 Bashlinux -@license: GNU GPL v3 +""" This module contains the implentations of abstract base class :py:class:`Escpos`. + +:author: `Manuel F Martinez `_ and others +:organization: Bashlinux and `python-escpos `_ +:copyright: Copyright (c) 2012 Bashlinux +:license: GNU GPL v3 """ import usb.core @@ -17,7 +18,10 @@ from .exceptions import * class Usb(Escpos): - """ Define USB printer """ + """ USB printer + + This class describes a printer that natively speaks USB. + """ def __init__(self, idVendor, idProduct, interface=0, in_ep=0x82, out_ep=0x01, *args, **kwargs): """ @@ -62,7 +66,10 @@ class Usb(Escpos): print("Could not set configuration: %s" % str(e)) def _raw(self, msg): - """ Print any command sent in raw format """ + """ Print any command sent in raw format + + :param msg: arbitrary code to be printed + """ self.device.write(self.out_ep, msg, self.interface) def __del__(self): @@ -73,21 +80,24 @@ class Usb(Escpos): class Serial(Escpos): - """ Define Serial printer """ + """ Serial printer + + This class describes a printer that is connected by serial interface. + """ def __init__(self, devfile="/dev/ttyS0", baudrate=9600, bytesize=8, timeout=1, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, - xonxoff=False , dsrdtr=True, *args, **kwargs): + xonxoff=False, dsrdtr=True, *args, **kwargs): """ - @param devfile : Device file under dev filesystem - @param baudrate : Baud rate for serial transmission - @param bytesize : Serial buffer size - @param timeout : Read/Write timeout - @param parity : Parity checking - @param stopbits : Number of stop bits - @param xonxoff : Software flow control - @param dsrdtr : Hardware flow control (False to enable RTS/CTS) + :param devfile: Device file under dev filesystem + :param baudrate: Baud rate for serial transmission + :param bytesize: Serial buffer size + :param timeout: Read/Write timeout + :param parity: Parity checking + :param stopbits: Number of stop bits + :param xonxoff: Software flow control + :param dsrdtr: Hardware flow control (False to enable RTS/CTS) """ Escpos.__init__(self, *args, **kwargs) self.devfile = devfile @@ -114,7 +124,10 @@ class Serial(Escpos): print("Unable to open serial printer on: %s" % self.devfile) def _raw(self, msg): - """ Print any command sent in raw format """ + """ Print any command sent in raw format + + :param msg: arbitrary code to be printed + """ self.device.write(msg) def __del__(self): @@ -124,12 +137,17 @@ class Serial(Escpos): class Network(Escpos): - """ Define Network printer """ + """ Network printer - def __init__(self,host,port=9100, *args, **kwargs): + This class is used to attach to a networked printer. You can also use this in order to attach to a printer that + is forwarded with `netcat`. + """ + + def __init__(self, host, port=9100, *args, **kwargs): """ - @param host : Printer's hostname or IP address - @param port : Port to write to + + :param host : Printer's hostname or IP address + :param port : Port to write to """ Escpos.__init__(self, *args, **kwargs) self.host = host @@ -145,7 +163,10 @@ class Network(Escpos): print("Could not open socket for %s" % self.host) def _raw(self, msg): - """ Print any command sent in raw format """ + """ Print any command sent in raw format + + :param msg: arbitrary code to be printed + """ self.device.send(msg) def __del__(self): @@ -154,11 +175,17 @@ class Network(Escpos): class File(Escpos): - """ Define Generic file printer """ + """ Generic file printer + + This class is used for parallel port printer or other printers that are directly attached to the filesystem. + Note that you should stay away from using USB-to-Parallel-Adapter since they are unreliable + and produce arbitrary errors. + """ def __init__(self, devfile="/dev/usb/lp0", *args, **kwargs): """ - @param devfile : Device file under dev filesystem + + :param devfile : Device file under dev filesystem """ Escpos.__init__(self, *args, **kwargs) self.devfile = devfile @@ -172,11 +199,14 @@ class File(Escpos): print("Could not open the specified file %s" % self.devfile) def flush(self): - """Flush printing content""" + """ Flush printing content """ self.device.flush() def _raw(self, msg): - """ Print any command sent in raw format """ + """ Print any command sent in raw format + + :param msg: arbitrary code to be printed + """ if type(msg) is str: self.device.write(msg.encode()); else: