mirror of
https://github.com/python-escpos/python-escpos
synced 2025-09-13 09:09:58 +00:00
Compare commits
2 Commits
b85d5b907d
...
00d3a1301f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
00d3a1301f | ||
![]() |
ebd6f88acf |
2
.github/workflows/pythonpackage-windows.yml
vendored
2
.github/workflows/pythonpackage-windows.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ['3.11', '3.12']
|
python-version: ['3.11', '3.12', '3.13']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
2
.github/workflows/pythonpackage.yml
vendored
2
.github/workflows/pythonpackage.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
|
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
@@ -24,6 +24,7 @@ classifiers =
|
|||||||
Programming Language :: Python :: 3.10
|
Programming Language :: Python :: 3.10
|
||||||
Programming Language :: Python :: 3.11
|
Programming Language :: Python :: 3.11
|
||||||
Programming Language :: Python :: 3.12
|
Programming Language :: Python :: 3.12
|
||||||
|
Programming Language :: Python :: 3.13
|
||||||
Programming Language :: Python :: Implementation :: CPython
|
Programming Language :: Python :: Implementation :: CPython
|
||||||
Topic :: Software Development :: Libraries :: Python Modules
|
Topic :: Software Development :: Libraries :: Python Modules
|
||||||
Topic :: Office/Business :: Financial :: Point-Of-Sale
|
Topic :: Office/Business :: Financial :: Point-Of-Sale
|
||||||
|
@@ -11,6 +11,7 @@ This module contains the abstract base class :py:class:`Escpos`.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
@@ -108,7 +109,7 @@ SW_BARCODE_NAMES = {
|
|||||||
for name in barcode.PROVIDED_BARCODES
|
for name in barcode.PROVIDED_BARCODES
|
||||||
}
|
}
|
||||||
|
|
||||||
Alignment = Union[Literal["center", "left", "right"], str]
|
Alignment = Union[Literal["center", "left", "right", "justify"], str]
|
||||||
|
|
||||||
|
|
||||||
class Escpos(object, metaclass=ABCMeta):
|
class Escpos(object, metaclass=ABCMeta):
|
||||||
@@ -920,7 +921,21 @@ class Escpos(object, metaclass=ABCMeta):
|
|||||||
self.text(textwrap.fill(txt, col_count))
|
self.text(textwrap.fill(txt, col_count))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
def _justify(txt: str, width: int) -> str:
|
||||||
|
"""Justify-text on left AND right sides by padding spaces.
|
||||||
|
|
||||||
|
code by: Georgina Skibinski https://stackoverflow.com/a/66087666
|
||||||
|
suggested by agordon @https://github.com/python-escpos/python-escpos/pull/652
|
||||||
|
"""
|
||||||
|
prev_txt = txt
|
||||||
|
while (length := width - len(txt)) > 0:
|
||||||
|
txt = re.sub(r"(\s+)", r"\1 ", txt, count=length)
|
||||||
|
if txt == prev_txt:
|
||||||
|
break
|
||||||
|
return txt.rjust(width)
|
||||||
|
|
||||||
def _padding(
|
def _padding(
|
||||||
|
self,
|
||||||
text: str,
|
text: str,
|
||||||
width: int,
|
width: int,
|
||||||
align: Alignment = "center",
|
align: Alignment = "center",
|
||||||
@@ -936,6 +951,10 @@ class Escpos(object, metaclass=ABCMeta):
|
|||||||
text = f"{text:<{width}}"
|
text = f"{text:<{width}}"
|
||||||
elif align == "right":
|
elif align == "right":
|
||||||
text = f"{text:>{width}}"
|
text = f"{text:>{width}}"
|
||||||
|
elif align == "justify":
|
||||||
|
text = self._justify(text, width)
|
||||||
|
else:
|
||||||
|
raise ValueError("Expected a valid alignment: center|left|right|justify")
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
@@ -972,7 +991,7 @@ class Escpos(object, metaclass=ABCMeta):
|
|||||||
textwrap.wrap(text, widths[i], break_long_words=False)
|
textwrap.wrap(text, widths[i], break_long_words=False)
|
||||||
for i, text in enumerate(text_list)
|
for i, text in enumerate(text_list)
|
||||||
]
|
]
|
||||||
max_len = max(*[len(text_group) for text_group in wrapped])
|
max_len = max(0, *[len(text_group) for text_group in wrapped])
|
||||||
text_colums = []
|
text_colums = []
|
||||||
for i in range(max_len):
|
for i in range(max_len):
|
||||||
row = ["" for _ in range(n_cols)]
|
row = ["" for _ in range(n_cols)]
|
||||||
@@ -1013,6 +1032,9 @@ class Escpos(object, metaclass=ABCMeta):
|
|||||||
If the list of alignment items is shorter than the list of strings then
|
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).
|
the last alignment of the list will be applied till the last string (column).
|
||||||
"""
|
"""
|
||||||
|
if not all([text_list, widths, align]):
|
||||||
|
raise TypeError("Value can't be of type None")
|
||||||
|
|
||||||
n_cols = len(text_list)
|
n_cols = len(text_list)
|
||||||
|
|
||||||
if isinstance(widths, int):
|
if isinstance(widths, int):
|
||||||
|
@@ -33,11 +33,11 @@ def test_add_padding_into_cols(driver) -> None:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
output = driver._add_padding_into_cols(
|
output = driver._add_padding_into_cols(
|
||||||
text_list=["col1", "col2", "col3"],
|
text_list=["col1", "col2", "col3", "col 4"],
|
||||||
widths=[6, 6, 6],
|
widths=[6, 6, 6, 6],
|
||||||
align=["center", "left", "right"],
|
align=["center", "left", "right", "justify"],
|
||||||
)
|
)
|
||||||
assert output == [" col1 ", "col2 ", " col3"]
|
assert output == [" col1 ", "col2 ", " col3", "col 4"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("text_list", ["", [], None])
|
@pytest.mark.parametrize("text_list", ["", [], None])
|
||||||
@@ -55,7 +55,7 @@ def test_software_columns_invalid_args(driver, text_list, widths, align) -> None
|
|||||||
|
|
||||||
bad_args = [bad_text_list, bad_widths, bad_align]
|
bad_args = [bad_text_list, bad_widths, bad_align]
|
||||||
for kwargs in bad_args:
|
for kwargs in bad_args:
|
||||||
with pytest.raises(Exception):
|
with pytest.raises((TypeError, ValueError)):
|
||||||
driver.software_columns(**kwargs)
|
driver.software_columns(**kwargs)
|
||||||
driver.close()
|
driver.close()
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ def test_software_columns_invalid_args(driver, text_list, widths, align) -> None
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.parametrize("widths", [[10, 10, 10], [10], 30])
|
@pytest.mark.parametrize("widths", [[10, 10, 10], [10], 30])
|
||||||
@pytest.mark.parametrize("align", [["center", "left", "right"], ["center"], "center"])
|
@pytest.mark.parametrize("align", [["center", "left", "right"], ["center"], "justify"])
|
||||||
def test_software_columns_valid_args(driver, text_list, widths, align) -> None:
|
def test_software_columns_valid_args(driver, text_list, widths, align) -> None:
|
||||||
"""
|
"""
|
||||||
GIVEN a dummy printer object
|
GIVEN a dummy printer object
|
||||||
|
3
tox.ini
3
tox.ini
@@ -1,5 +1,5 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py38, py39, py310, py311, docs, flake8
|
envlist = py38, py39, py310, py311, py312, py313, docs, flake8
|
||||||
|
|
||||||
[gh-actions]
|
[gh-actions]
|
||||||
python =
|
python =
|
||||||
@@ -11,6 +11,7 @@ python =
|
|||||||
3.10: py310
|
3.10: py310
|
||||||
3.11: py311
|
3.11: py311
|
||||||
3.12: py312
|
3.12: py312
|
||||||
|
3.13: py313
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = jaconv
|
deps = jaconv
|
||||||
|
Reference in New Issue
Block a user