mirror of
https://github.com/python-escpos/python-escpos
synced 2025-09-13 09:09:58 +00:00
Compare commits
6 Commits
b85d5b907d
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1349ad85bf | ||
![]() |
11d46fdb66 | ||
![]() |
1a780e8f80 | ||
![]() |
c702204231 | ||
![]() |
00d3a1301f | ||
![]() |
ebd6f88acf |
2
.github/workflows/black.yml
vendored
2
.github/workflows/black.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
||||
black-code-style:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: psf/black@stable
|
||||
with:
|
||||
version: "23.12.0"
|
||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
|
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install packages
|
||||
|
6
.github/workflows/pythonpackage-windows.yml
vendored
6
.github/workflows/pythonpackage-windows.yml
vendored
@@ -12,14 +12,14 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.11', '3.12']
|
||||
python-version: ['3.11', '3.12', '3.13']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5.6.0
|
||||
uses: actions/setup-python@v6.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
6
.github/workflows/pythonpackage.yml
vendored
6
.github/workflows/pythonpackage.yml
vendored
@@ -15,14 +15,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
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:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5.6.0
|
||||
uses: actions/setup-python@v6.0.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
@@ -1,4 +1,4 @@
|
||||
appdirs==1.4.4
|
||||
platformdirs==4.3.8
|
||||
argcomplete==3.0.8
|
||||
blinker==1.6.2
|
||||
click==8.1.3
|
||||
|
@@ -24,6 +24,7 @@ classifiers =
|
||||
Programming Language :: Python :: 3.10
|
||||
Programming Language :: Python :: 3.11
|
||||
Programming Language :: Python :: 3.12
|
||||
Programming Language :: Python :: 3.13
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
Topic :: Software Development :: Libraries :: Python Modules
|
||||
Topic :: Office/Business :: Financial :: Point-Of-Sale
|
||||
@@ -42,7 +43,7 @@ install_requires =
|
||||
python-barcode>=0.15.0,<1
|
||||
setuptools
|
||||
six
|
||||
appdirs
|
||||
platformdirs
|
||||
PyYAML
|
||||
argcomplete
|
||||
importlib_resources
|
||||
|
@@ -13,9 +13,10 @@ from typing import Any, Dict, Optional, Type
|
||||
import importlib_resources
|
||||
import yaml
|
||||
|
||||
logging.basicConfig()
|
||||
logger = logging.getLogger(__name__)
|
||||
if environ.get("ESCPOS_CAPABILITIES_DEBUG", 0):
|
||||
logging.basicConfig()
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
pickle_dir = environ.get("ESCPOS_CAPABILITIES_PICKLE_DIR", mkdtemp())
|
||||
pickle_path = path.join(pickle_dir, f"{platform.python_version()}.capabilities.pickle")
|
||||
# get a temporary file from importlib_resources if no file is specified in env
|
||||
|
@@ -5,7 +5,7 @@ This module contains the implementations of abstract base class :py:class:`Confi
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
import appdirs
|
||||
import platformdirs
|
||||
import yaml
|
||||
|
||||
from . import exceptions, printer
|
||||
@@ -55,7 +55,7 @@ class Config:
|
||||
|
||||
if not config_path:
|
||||
config_path = os.path.join(
|
||||
appdirs.user_config_dir(self._app_name), self._config_file
|
||||
platformdirs.user_config_dir(self._app_name), self._config_file
|
||||
)
|
||||
if isinstance(config_path, pathlib.Path):
|
||||
# store string if posixpath
|
||||
|
@@ -11,6 +11,7 @@ This module contains the abstract base class :py:class:`Escpos`.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import textwrap
|
||||
import time
|
||||
import warnings
|
||||
@@ -108,7 +109,7 @@ SW_BARCODE_NAMES = {
|
||||
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):
|
||||
@@ -920,7 +921,21 @@ class Escpos(object, metaclass=ABCMeta):
|
||||
self.text(textwrap.fill(txt, col_count))
|
||||
|
||||
@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(
|
||||
self,
|
||||
text: str,
|
||||
width: int,
|
||||
align: Alignment = "center",
|
||||
@@ -936,6 +951,10 @@ class Escpos(object, metaclass=ABCMeta):
|
||||
text = f"{text:<{width}}"
|
||||
elif align == "right":
|
||||
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
|
||||
|
||||
@@ -972,7 +991,7 @@ class Escpos(object, metaclass=ABCMeta):
|
||||
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])
|
||||
max_len = max(0, *[len(text_group) for text_group in wrapped])
|
||||
text_colums = []
|
||||
for i in range(max_len):
|
||||
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
|
||||
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)
|
||||
|
||||
if isinstance(widths, int):
|
||||
|
@@ -8,7 +8,7 @@
|
||||
"""
|
||||
import pathlib
|
||||
|
||||
import appdirs
|
||||
import platformdirs
|
||||
import pytest
|
||||
|
||||
import escpos.exceptions
|
||||
@@ -80,7 +80,7 @@ def test_config_load_from_appdir() -> None:
|
||||
|
||||
# generate a dummy config
|
||||
config_file = (
|
||||
pathlib.Path(appdirs.user_config_dir(config.Config._app_name))
|
||||
pathlib.Path(platformdirs.user_config_dir(config.Config._app_name))
|
||||
/ config.Config._config_file
|
||||
)
|
||||
|
||||
|
@@ -33,11 +33,11 @@ def test_add_padding_into_cols(driver) -> None:
|
||||
"""
|
||||
|
||||
output = driver._add_padding_into_cols(
|
||||
text_list=["col1", "col2", "col3"],
|
||||
widths=[6, 6, 6],
|
||||
align=["center", "left", "right"],
|
||||
text_list=["col1", "col2", "col3", "col 4"],
|
||||
widths=[6, 6, 6, 6],
|
||||
align=["center", "left", "right", "justify"],
|
||||
)
|
||||
assert output == [" col1 ", "col2 ", " col3"]
|
||||
assert output == [" col1 ", "col2 ", " col3", "col 4"]
|
||||
|
||||
|
||||
@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]
|
||||
for kwargs in bad_args:
|
||||
with pytest.raises(Exception):
|
||||
with pytest.raises((TypeError, ValueError)):
|
||||
driver.software_columns(**kwargs)
|
||||
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("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:
|
||||
"""
|
||||
GIVEN a dummy printer object
|
||||
|
4
tox.ini
4
tox.ini
@@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
envlist = py38, py39, py310, py311, docs, flake8
|
||||
envlist = py38, py39, py310, py311, py312, py313, docs, flake8
|
||||
|
||||
[gh-actions]
|
||||
python =
|
||||
@@ -11,6 +11,7 @@ python =
|
||||
3.10: py310
|
||||
3.11: py311
|
||||
3.12: py312
|
||||
3.13: py313
|
||||
|
||||
[testenv]
|
||||
deps = jaconv
|
||||
@@ -54,7 +55,6 @@ deps = mypy
|
||||
types-six
|
||||
types-mock
|
||||
types-PyYAML
|
||||
types-appdirs
|
||||
types-Pillow
|
||||
types-pyserial
|
||||
types-pywin32>=306.0.0.6
|
||||
|
Reference in New Issue
Block a user