Compare commits

...

20 Commits
v3.1 ... master

Author SHA1 Message Date
dependabot[bot]
5cdff0b56e
Bump actions/setup-python from 5.1.1 to 5.2.0 (#655)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.1 to 5.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.1.1...v5.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 14:52:10 +02:00
aerialist
f42410603d
Add sleep in sending fragments (#624)
* Add sleep in sending fragments

Adding sleep prevents "USBTimeoutError: [Errno 110] Operation timed out".

* change sorting

* make sleep configurable

* add spelling

---------

Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com>
Co-authored-by: Patrick Kanzler <dev@pkanzler.de>
2024-08-25 00:50:27 +02:00
Patrick Kanzler
22982fbd12
update organize import trigger, update capabilities data, fix mypy (#654)
* update organize import trigger

* update capabilities data

* fix mypy error (jaconv is using a import hack)
2024-08-25 00:21:47 +02:00
Benito López
82386f7496
New feature: Software columns - Part 3: Tests (#651)
* Add test_function_software_columns.py

* Improve coverage
2024-08-24 23:29:00 +02:00
Benito López
99501cc2c1
New feature: Software columns - Part 2: CLI (#649)
* Add software_columns CLI parameter

* Fix sorting

---------

Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com>
2024-07-19 22:23:52 +02:00
Psychpsyo
3aaf203ceb
Fix typo in README (#650) 2024-07-19 22:18:09 +02:00
Benito López
a8753a1121
New feature: Software columns (#645)
* add type hint Alignment

* Add static method padding()

* Add static method truncate()

* Add static method _repeat_last()

* Add private method _rearrange_into_cols()

* Add private method _add_padding_into_cols()

* Add public method software_columns

* Make truncate and padding private staticmethods

* Revert "add type hint Alignment"

This reverts commit 546391cb9c3d246d536cb5abb269ed4d36e175ce.

* Add type hint Alignment

* Fix typo in docstring

---------

Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com>
2024-07-11 17:13:34 +02:00
dependabot[bot]
5af01641d9
Bump actions/setup-python from 5.1.0 to 5.1.1 (#648)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.1.0...v5.1.1)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-11 16:41:42 +02:00
Benito López
fe3cdde424
Clarify set() width and height documentation (#644) 2024-05-24 23:21:54 +02:00
dependabot[bot]
4c02881fe7
Bump jinja2 from 3.1.3 to 3.1.4 in /examples/docker-flask (#642)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.3...3.1.4)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 22:54:24 +02:00
dependabot[bot]
82f5a00b8d
Bump werkzeug from 3.0.1 to 3.0.3 in /examples/docker-flask (#641)
Bumps [werkzeug](https://github.com/pallets/werkzeug) from 3.0.1 to 3.0.3.
- [Release notes](https://github.com/pallets/werkzeug/releases)
- [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/werkzeug/compare/3.0.1...3.0.3)

---
updated-dependencies:
- dependency-name: werkzeug
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 21:40:03 +02:00
Benito López
1e9adb80f3
Fix CLI not working for some connectors Fixes #639 (#640) 2024-04-29 23:50:52 +02:00
dependabot[bot]
640f6089ac
Bump pillow from 10.2.0 to 10.3.0 in /examples/docker-flask (#634)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-03 21:04:35 +02:00
dependabot[bot]
a8a9d0f0ad
Bump codecov/codecov-action from 3 to 4 (#625)
* Bump codecov/codecov-action from 3 to 4

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* add codecov token

* add codecov token

* remove directory config

* adapt excludes

* exclude mypy_cache

* glob

* exclude

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Patrick Kanzler <4189642+patkan@users.noreply.github.com>
Co-authored-by: Patrick Kanzler <dev@pkanzler.de>
2024-04-02 01:23:56 +02:00
dependabot[bot]
f781e28a69
Bump actions/setup-python from 5.0.0 to 5.1.0 (#632)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.0.0...v5.1.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 00:03:22 +02:00
dependabot[bot]
62c234f6f1
Bump pillow from 10.0.1 to 10.2.0 in /examples/docker-flask (#623)
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.0.1 to 10.2.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.0.1...10.2.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 23:25:38 +01:00
dependabot[bot]
4ba98c0017
Bump jinja2 from 3.1.2 to 3.1.3 in /examples/docker-flask (#620)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 12:24:41 +01:00
Wesley Appler
a865b715f3
Fixed lack of spacing for multi-line strings (#619)
Co-authored-by: Wes Appler <wes@lamemakes>
2024-01-11 12:35:03 +01:00
dependabot[bot]
776b8a26ad
Bump capabilities-data from 4006299 to 375135d (#616)
Bumps [capabilities-data](https://github.com/receipt-print-hq/escpos-printer-db) from `4006299` to `375135d`.
- [Commits](4006299c0f...375135d552)

---
updated-dependencies:
- dependency-name: capabilities-data
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 12:37:20 +01:00
Patrick Kanzler
9b0d126da2
prepare for new development (#615) 2023-12-17 23:10:44 +01:00
20 changed files with 312 additions and 27 deletions

View File

@ -19,7 +19,7 @@ jobs:
with: with:
submodules: 'recursive' submodules: 'recursive'
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.0.0 uses: actions/setup-python@v5.2.0
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dependencies - name: Install dependencies
@ -44,12 +44,14 @@ jobs:
env: env:
ESCPOS_CAPABILITIES_FILE: D:\a\python-escpos\python-escpos\capabilities-data\dist\capabilities.json ESCPOS_CAPABILITIES_FILE: D:\a\python-escpos\python-escpos\capabilities-data\dist\capabilities.json
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with: with:
directory: ./coverage/reports/
env_vars: OS,PYTHON env_vars: OS,PYTHON
fail_ci_if_error: true fail_ci_if_error: true
files: ./coverage.xml,!./cache files: ./coverage.xml
exclude: "**/.mypy_cache"
flags: unittests flags: unittests
name: coverage-tox-${{ matrix.python-version }} name: coverage-tox-${{ matrix.python-version }}
verbose: true verbose: true

View File

@ -22,7 +22,7 @@ jobs:
with: with:
submodules: 'recursive' submodules: 'recursive'
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.0.0 uses: actions/setup-python@v5.2.0
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dependencies - name: Install dependencies
@ -54,12 +54,14 @@ jobs:
env: env:
ESCPOS_CAPABILITIES_FILE: /home/runner/work/python-escpos/python-escpos/capabilities-data/dist/capabilities.json ESCPOS_CAPABILITIES_FILE: /home/runner/work/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with: with:
directory: ./coverage/reports/
env_vars: OS,PYTHON env_vars: OS,PYTHON
fail_ci_if_error: true fail_ci_if_error: true
files: ./coverage.xml,!./cache files: ./coverage.xml
exclude: "**/.mypy_cache"
flags: unittests flags: unittests
name: coverage-tox-${{ matrix.python-version }} name: coverage-tox-${{ matrix.python-version }}
verbose: true verbose: true

View File

@ -12,7 +12,7 @@
"editor.formatOnPaste": true, "editor.formatOnPaste": true,
"python.formatting.provider": "black", "python.formatting.provider": "black",
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.organizeImports": true "source.organizeImports": "explicit"
}, },
"python.testing.unittestEnabled": false, "python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true, "python.testing.pytestEnabled": true,

View File

@ -1,6 +1,18 @@
Changelog Changelog
========= =========
202x-xx-xx - Version 3.x - ""
-------------------------------------------
changes
^^^^^^^
contributors
^^^^^^^^^^^^
2023-12-17 - Version 3.1 - "Rubric Of Ruin" 2023-12-17 - Version 3.1 - "Rubric Of Ruin"
------------------------------------------- -------------------------------------------
This is the minor release of the new version 3.1. This is the minor release of the new version 3.1.

View File

@ -100,4 +100,4 @@ Disclaimer
None of the vendors cited in this project agree or endorse any of the None of the vendors cited in this project agree or endorse any of the
patterns or implementations. patterns or implementations.
Its names are used only to maintain context. Their names are used only to maintain context.

@ -1 +1 @@
Subproject commit 4006299c0fa82bc4d4c297663628346ce3eff6c5 Subproject commit e3bf6056ee75cf70ffaccb925081fffa7ad6ced5

View File

@ -91,6 +91,7 @@ docstrings
ean ean
Ean Ean
encodable encodable
Errno
fff fff
fullimage fullimage
io io
@ -124,6 +125,7 @@ Todo
traceback traceback
udev udev
usb usb
USBTimeoutError
usec usec
virtualenvs virtualenvs
whitespaces whitespaces

View File

@ -213,6 +213,14 @@ If something is wrong, an ``CharCodeError`` will be raised.
After you have manually set the codepage the printer won't change it anymore. After you have manually set the codepage the printer won't change it anymore.
You can revert to normal behavior by setting charcode to ``AUTO``. You can revert to normal behavior by setting charcode to ``AUTO``.
Resolving bus timeout issues during printing images
---------------------------------------------------
If an error message such as "USBTimeoutError: [Errno 110] Operation timed out" occurs,
setting a sleep time between printing fragments can help.
This can be done with the :meth:`.set_sleep_in_fragment()` method.
Advanced Usage: Print from binary blob Advanced Usage: Print from binary blob
-------------------------------------- --------------------------------------

View File

@ -4,9 +4,9 @@ blinker==1.6.2
click==8.1.3 click==8.1.3
Flask==2.3.2 Flask==2.3.2
itsdangerous==2.1.2 itsdangerous==2.1.2
Jinja2==3.1.2 Jinja2==3.1.4
MarkupSafe==2.1.2 MarkupSafe==2.1.2
Pillow==10.0.1 Pillow==10.3.0
pycups==2.0.1 pycups==2.0.1
pypng==0.20220715.0 pypng==0.20220715.0
pyserial==3.5 pyserial==3.5
@ -17,4 +17,4 @@ PyYAML==6.0
qrcode==7.4.2 qrcode==7.4.2
six==1.16.0 six==1.16.0
typing_extensions==4.5.0 typing_extensions==4.5.0
Werkzeug==3.0.1 Werkzeug==3.0.3

View File

@ -209,6 +209,38 @@ ESCPOS_COMMANDS: List[Dict[str, Any]] = [
}, },
], ],
}, },
{
"parser": {
"name": "software_columns",
"help": "Print a list of texts arranged into columns",
},
"defaults": {
"func": "software_columns",
},
"arguments": [
{
"option_strings": ("--text_list",),
"help": "list of texts to print",
"nargs": "+",
"type": str,
"required": True,
},
{
"option_strings": ("--widths",),
"help": "list of column widths",
"nargs": "+",
"type": int,
"required": True,
},
{
"option_strings": ("--align",),
"help": "list of column alignments",
"nargs": "+",
"type": str,
"required": True,
},
],
},
{ {
"parser": { "parser": {
"name": "cut", "name": "cut",

View File

@ -76,7 +76,18 @@ class Config:
if "printer" in config: if "printer" in config:
self._printer_config = config["printer"] self._printer_config = config["printer"]
self._printer_name = self._printer_config.pop("type").title() printer_name = self._printer_config.pop("type")
class_names = {
"usb": "Usb",
"serial": "Serial",
"network": "Network",
"file": "File",
"dummy": "Dummy",
"cupsprinter": "CupsPrinter",
"lp": "LP",
"win32raw": "Win32Raw",
}
self._printer_name = class_names.get(printer_name.lower(), printer_name)
if not self._printer_name or not hasattr(printer, self._printer_name): if not self._printer_name or not hasattr(printer, self._printer_name):
raise exceptions.ConfigSyntaxError( raise exceptions.ConfigSyntaxError(

View File

@ -12,6 +12,7 @@ This module contains the abstract base class :py:class:`Escpos`.
from __future__ import annotations from __future__ import annotations
import textwrap import textwrap
import time
import warnings import warnings
from abc import ABCMeta, abstractmethod # abstract base class support from abc import ABCMeta, abstractmethod # abstract base class support
from re import match as re_match from re import match as re_match
@ -107,6 +108,8 @@ SW_BARCODE_NAMES = {
for name in barcode.PROVIDED_BARCODES for name in barcode.PROVIDED_BARCODES
} }
Alignment = Union[Literal["center", "left", "right"], str]
class Escpos(object, metaclass=ABCMeta): class Escpos(object, metaclass=ABCMeta):
"""ESC/POS Printer object. """ESC/POS Printer object.
@ -121,6 +124,9 @@ class Escpos(object, metaclass=ABCMeta):
# object -> The connection object (Usb(), Serial(), Network(), etc.) # object -> The connection object (Usb(), Serial(), Network(), etc.)
_device: Union[Literal[False], Literal[None], object] = False _device: Union[Literal[False], Literal[None], object] = False
# sleep time in fragments:
_sleep_in_fragment_ms: int = 0
def __init__(self, profile=None, magic_encode_args=None, **kwargs) -> None: def __init__(self, profile=None, magic_encode_args=None, **kwargs) -> None:
"""Initialize ESCPOS Printer. """Initialize ESCPOS Printer.
@ -176,6 +182,21 @@ class Escpos(object, metaclass=ABCMeta):
""" """
raise NotImplementedError() raise NotImplementedError()
def set_sleep_in_fragment(self, sleep_time_ms: int) -> None:
"""Configures the currently active sleep time after sending a fragment.
If during printing an image an issue like "USBTimeoutError: [Errno 110]
Operation timed out" occurs, setting this value to roughly 300
milliseconds can help resolve the issue.
:param sleep_time_ms: sleep time in milliseconds
"""
self._sleep_in_fragment_ms = sleep_time_ms
def _sleep_in_fragment(self) -> None:
"""Sleeps the preconfigured time after sending a fragment."""
time.sleep(self._sleep_in_fragment_ms / 1000)
def image( def image(
self, self,
img_source, img_source,
@ -244,6 +265,7 @@ class Escpos(object, metaclass=ABCMeta):
impl=impl, impl=impl,
fragment_height=fragment_height, fragment_height=fragment_height,
) )
self._sleep_in_fragment()
return return
if impl == "bitImageRaster": if impl == "bitImageRaster":
@ -897,6 +919,115 @@ class Escpos(object, metaclass=ABCMeta):
col_count = self.profile.get_columns(font) if columns is None else columns col_count = self.profile.get_columns(font) if columns is None else columns
self.text(textwrap.fill(txt, col_count)) self.text(textwrap.fill(txt, col_count))
@staticmethod
def _padding(
text: str,
width: int,
align: Alignment = "center",
) -> str:
"""Add fill space to meet the width.
The align parameter sets the alignment of the text in space.
"""
align = align.lower()
if align == "center":
text = f"{text:^{width}}"
elif align == "left":
text = f"{text:<{width}}"
elif align == "right":
text = f"{text:>{width}}"
return text
@staticmethod
def _truncate(text: str, width: int, placeholder: str = ".") -> str:
"""Truncate an string at a max width or leave it untouched.
Add a placeholder at the end of the output text if it has been truncated.
"""
ph_len = len(placeholder)
max_len = width - ph_len
return f"{text[:max_len]}{placeholder}" if len(text) > width else text
@staticmethod
def _repeat_last(iterable, max_iterations: int = 1000):
"""Iterate over the items of a list repeating the last one until max_iterations."""
i = 0
while i < max_iterations:
try:
yield iterable[i]
except IndexError:
yield iterable[-1]
i += 1
def _rearrange_into_cols(self, text_list: list, widths: list[int]) -> list:
"""Wrap and convert a list of strings into an array of text columns.
Set the width of each column by passing a list of widths.
Wrap if possible and|or truncate strings longer than its column width.
Reorder the wrapped items into an array of text columns.
"""
n_cols = len(text_list)
wrapped = [
textwrap.wrap(text, widths[i], break_long_words=False)
for i, text in enumerate(text_list)
]
max_len = max(*[len(text_group) for text_group in wrapped])
text_colums = []
for i in range(max_len):
row = ["" for _ in range(n_cols)]
for j, item in enumerate(wrapped):
if i in range(len(item)):
row[j] = self._truncate(item[i], widths[j])
text_colums.append(row)
return text_colums
def _add_padding_into_cols(
self,
text_list: list[str],
widths: list[int],
align: list[Alignment],
) -> list:
"""Add padding, width and alignment into the items of a list of strings."""
return [
self._padding(text, widths[i], align[i]) for i, text in enumerate(text_list)
]
def software_columns(
self,
text_list: list,
widths: Union[list[int], int],
align: Union[list[Alignment], Alignment],
) -> None:
"""Print a list of strings arranged horizontally in columns.
:param text_list: list of strings, each item in the list will be printed as a column.
:param widths: width of each column by passing a list of widths,
or a single total width to arrange columns of the same size.
If the list of width items is shorter than the list of strings then
the last width of the list will be applied till the last string (column).
:param align: alignment of the text into each column by passing a list of alignments,
or a single alignment for all the columns.
If the list of alignment items is shorter than the list of strings then
the last alignment of the list will be applied till the last string (column).
"""
n_cols = len(text_list)
if isinstance(widths, int):
widths = [round(widths / n_cols)]
widths = list(self._repeat_last(widths, max_iterations=n_cols))
if isinstance(align, str):
align = [align]
align = list(self._repeat_last(align, max_iterations=n_cols))
columns = self._rearrange_into_cols(text_list, widths)
for row in columns:
padded = self._add_padding_into_cols(row, widths, align)
self.textln("".join(padded))
def set( def set(
self, self,
align: Optional[str] = None, align: Optional[str] = None,
@ -934,8 +1065,8 @@ class Escpos(object, metaclass=ABCMeta):
:param double_width: doubles the width of the text :param double_width: doubles the width of the text
:param custom_size: uses custom size specified by width and height :param custom_size: uses custom size specified by width and height
parameters. Cannot be used with double_width or double_height. parameters. Cannot be used with double_width or double_height.
:param width: text width multiplier when custom_size is used, decimal range 1-8 :param width: requires custom_size=True, text width multiplier when custom_size is used, decimal range 1-8
:param height: text height multiplier when custom_size is used, decimal range 1-8 :param height: requires custom_size=True, text height multiplier when custom_size is used, decimal range 1-8
:param density: print density, value from 0-8, if something else is supplied the density remains unchanged :param density: print density, value from 0-8, if something else is supplied the density remains unchanged
:param invert: True enables white on black printing :param invert: True enables white on black printing
:param smooth: True enables text smoothing. Effective on 4x4 size text and larger :param smooth: True enables text smoothing. Effective on 4x4 size text and larger

View File

@ -4,7 +4,10 @@
I doubt that this currently works correctly. I doubt that this currently works correctly.
""" """
import types
import typing
jaconv: typing.Optional[types.ModuleType]
try: try:
import jaconv import jaconv
except ImportError: except ImportError:

View File

@ -0,0 +1,80 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""tests for software_columns
:author: Benito López and the python-escpos developers
:organization: `python-escpos <https://github.com/python-escpos>`_
:copyright: Copyright (c) 2024 `python-escpos <https://github.com/python-escpos>`_
:license: MIT
"""
import pytest
def test_rearrange_into_cols(driver) -> None:
"""
GIVEN a list of columnable text
WHEN the column width is different for each column and some strings exceed the max width
THEN check the strings are properly wrapped, truncated and rearranged into some columns
"""
output = driver._rearrange_into_cols(
text_list=["fits", "row1 row2", "truncate and wrap"], widths=[4, 5, 6]
)
assert output == [["fits", "row1", "trunc."], ["", "row2", "and"], ["", "", "wrap"]]
def test_add_padding_into_cols(driver) -> None:
"""
GIVEN a list of strings
WHEN adding padding and different alignments to each string
THEN check the strings are correctly padded and aligned
"""
output = driver._add_padding_into_cols(
text_list=["col1", "col2", "col3"],
widths=[6, 6, 6],
align=["center", "left", "right"],
)
assert output == [" col1 ", "col2 ", " col3"]
@pytest.mark.parametrize("text_list", ["", [], None])
@pytest.mark.parametrize("widths", [30.5, "30", None])
@pytest.mark.parametrize("align", ["invalid_align_name", "", None])
def test_software_columns_invalid_args(driver, text_list, widths, align) -> None:
"""
GIVEN a dummy printer object
WHEN non valid params are passed
THEN check raise exception
"""
bad_text_list = {"text_list": text_list, "widths": 5, "align": "left"}
bad_widths = {"text_list": ["valid"], "widths": widths, "align": "left"}
bad_align = {"text_list": ["valid"], "widths": 5, "align": align}
bad_args = [bad_text_list, bad_widths, bad_align]
for kwargs in bad_args:
with pytest.raises(Exception):
driver.software_columns(**kwargs)
driver.close()
@pytest.mark.parametrize(
"text_list",
[
["col1", "col2", "col3"],
["wrap this string", "wrap this string", "wrap this string"],
["truncate_this_string", "truncate_this_string", "truncate_this_string"],
],
)
@pytest.mark.parametrize("widths", [[10, 10, 10], [10], 30])
@pytest.mark.parametrize("align", [["center", "left", "right"], ["center"], "center"])
def test_software_columns_valid_args(driver, text_list, widths, align) -> None:
"""
GIVEN a dummy printer object
WHEN valid params are passed
THEN check no errors
"""
driver.software_columns(text_list=text_list, widths=widths, align=align)
driver.close()

View File

@ -7,7 +7,8 @@
:copyright: Copyright (c) 2016 `python-escpos <https://github.com/python-escpos>`_ :copyright: Copyright (c) 2016 `python-escpos <https://github.com/python-escpos>`_
:license: MIT :license: MIT
""" """
import types
import typing
import hypothesis.strategies as st import hypothesis.strategies as st
import pytest import pytest
@ -111,6 +112,7 @@ class TestMagicEncode:
assert driver.output == b"\x1bt\x00? ist teuro." assert driver.output == b"\x1bt\x00? ist teuro."
jaconv: typing.Optional[types.ModuleType]
try: try:
import jaconv import jaconv
except ImportError: except ImportError: