mirror of
https://github.com/python-escpos/python-escpos
synced 2025-09-13 09:09:58 +00:00
Compare commits
90 Commits
update-fla
...
v3.0a7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
557991d80b | ||
![]() |
fe08fc1469 | ||
![]() |
6c27222aeb | ||
![]() |
6731057456 | ||
![]() |
f0b1a89c48 | ||
![]() |
fd7bd0710e | ||
![]() |
7ea58625e6 | ||
![]() |
baffd98a22 | ||
![]() |
ecbdd43dff | ||
![]() |
5b6b96d2a0 | ||
![]() |
7aa20a60e3 | ||
![]() |
95ec6d5c08 | ||
![]() |
18c3a5f298 | ||
![]() |
4836dcd486 | ||
![]() |
d9d400da6d | ||
![]() |
fe2e1a6d28 | ||
![]() |
c53575a155 | ||
![]() |
cadf448c38 | ||
![]() |
7c05404ac4 | ||
![]() |
e1e1ccb3f2 | ||
![]() |
32c56e78ea | ||
![]() |
4d106e8659 | ||
![]() |
ddab5318cf | ||
![]() |
9b60e2e3ab | ||
![]() |
34cd1ebde1 | ||
![]() |
a2db415559 | ||
![]() |
4e19b0ca51 | ||
![]() |
a3660a6366 | ||
![]() |
9fa551e6e8 | ||
![]() |
ae0a049efa | ||
![]() |
117d286371 | ||
![]() |
a555a651b4 | ||
![]() |
e350a49cad | ||
![]() |
f49c1dcb89 | ||
![]() |
cc67cb1c1e | ||
![]() |
2ee3ff7f87 | ||
![]() |
ca45d25670 | ||
![]() |
51d1299285 | ||
![]() |
0c0e6b9b4c | ||
![]() |
50437cc9d2 | ||
![]() |
7c7d401f31 | ||
![]() |
fa140c2df5 | ||
![]() |
8b3076871f | ||
![]() |
46429b1092 | ||
![]() |
99ca096f82 | ||
![]() |
2d97c0bbbd | ||
![]() |
6c6fe9bccf | ||
![]() |
c5e46a888d | ||
![]() |
46942820a5 | ||
![]() |
e50e295acc | ||
![]() |
2d7458fa49 | ||
![]() |
a6f635c0d5 | ||
![]() |
2d0f045457 | ||
![]() |
293b8632ff | ||
![]() |
5ff73595b6 | ||
![]() |
4ecab402b8 | ||
![]() |
c56e43da84 | ||
![]() |
88af26f46e | ||
![]() |
9dd966c2a3 | ||
![]() |
a7d959428f | ||
![]() |
8bf0e08659 | ||
![]() |
5ac5a24b50 | ||
![]() |
63252515b5 | ||
![]() |
29a546821b | ||
![]() |
4ddd18279f | ||
![]() |
de761e96e3 | ||
![]() |
ed7bce6932 | ||
![]() |
edd567785c | ||
![]() |
f1054876da | ||
![]() |
490e0657dd | ||
![]() |
b4c32b5a4a | ||
![]() |
40b30225d3 | ||
![]() |
19e3ec6895 | ||
![]() |
df539da854 | ||
![]() |
4534038b39 | ||
![]() |
adf85f7784 | ||
![]() |
aaa8162967 | ||
![]() |
0461adc212 | ||
![]() |
91ff83e506 | ||
![]() |
29ef88f591 | ||
![]() |
7c01a30d6c | ||
![]() |
035c425581 | ||
![]() |
d20646b2a9 | ||
![]() |
206822ac69 | ||
![]() |
dc08792e72 | ||
![]() |
2886075ce9 | ||
![]() |
73fff6291d | ||
![]() |
d5b9d99093 | ||
![]() |
18c51358aa | ||
![]() |
52719c0b7d |
43
.github/workflows/pythonpackage.yml
vendored
Normal file
43
.github/workflows/pythonpackage.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: Python package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: [3.5, 3.6, 3.7, 3.8]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v1
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install flake8 pytest tox tox-gh-actions
|
||||||
|
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
# stop the build if there are Python syntax errors or undefined names
|
||||||
|
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||||
|
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||||
|
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||||
|
- name: Test with tox
|
||||||
|
run: |
|
||||||
|
tox
|
||||||
|
env:
|
||||||
|
ESCPOS_CAPABILITIES_FILE: /home/runner/work/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -29,3 +29,6 @@ test/test-cli-output/
|
|||||||
*.swp
|
*.swp
|
||||||
*.swn
|
*.swn
|
||||||
*.swo
|
*.swo
|
||||||
|
|
||||||
|
# vscode
|
||||||
|
.vscode/settings.json
|
||||||
|
1
.mailmap
1
.mailmap
@@ -12,3 +12,4 @@ Juanmi Taboada <juanmi@juanmitaboada.com> Juanmi Taboada <juanmi@juan
|
|||||||
csoft2k <csoft2k@hotmail.com>
|
csoft2k <csoft2k@hotmail.com>
|
||||||
Sergio Pulgarin <sergio.pulgarin@gmail.com>
|
Sergio Pulgarin <sergio.pulgarin@gmail.com>
|
||||||
reck31 <rakesh.gunduka@gmail.com>
|
reck31 <rakesh.gunduka@gmail.com>
|
||||||
|
Alex Debiasio <alex.debiasio@thinkin.io> <alex.debiasio@studenti.unitn.it>
|
||||||
|
45
.travis.yml
45
.travis.yml
@@ -1,6 +1,7 @@
|
|||||||
language: python
|
language: python
|
||||||
sudo: false
|
sudo: false
|
||||||
cache: pip
|
cache: pip
|
||||||
|
dist: bionic
|
||||||
git:
|
git:
|
||||||
depth: 100000
|
depth: 100000
|
||||||
addons:
|
addons:
|
||||||
@@ -11,36 +12,50 @@ env:
|
|||||||
global:
|
global:
|
||||||
- ESCPOS_CAPABILITIES_FILE=/home/travis/build/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
|
- ESCPOS_CAPABILITIES_FILE=/home/travis/build/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
|
||||||
matrix:
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
include:
|
include:
|
||||||
- python: 2.7
|
- name: "Python 3.7 on Windows"
|
||||||
env: TOXENV=py27
|
os: windows
|
||||||
- python: 3.4
|
language: shell
|
||||||
env: TOXENV=py34
|
before_install:
|
||||||
|
- choco install python
|
||||||
|
- pip install tox codecov 'sphinx>=1.5.1'
|
||||||
|
env:
|
||||||
|
- TOXENV=py37
|
||||||
|
- PATH=/c/Python37:/c/Python37/Scripts:$PATH
|
||||||
|
- ESCPOS_CAPABILITIES_FILE=C:/Users/travis/build/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
|
||||||
|
- name: "Python 3.7 on macOS"
|
||||||
|
os: osx
|
||||||
|
osx_image: xcode10.2
|
||||||
|
language: shell
|
||||||
|
env: TOXENV=py37 ESCPOS_CAPABILITIES_FILE=/Users/travis/build/python-escpos/python-escpos/capabilities-data/dist/capabilities.json
|
||||||
- python: 3.5
|
- python: 3.5
|
||||||
env: TOXENV=py35
|
env: TOXENV=py35
|
||||||
- python: 3.6
|
- python: 3.6
|
||||||
env: TOXENV=py36
|
env: TOXENV=py36
|
||||||
- python: 3.6-dev
|
- python: 3.7
|
||||||
env: TOXENV=py36
|
env: TOXENV=py37
|
||||||
- python: 3.7-dev
|
- python: 3.7-dev
|
||||||
env: TOXENV=py37
|
env: TOXENV=py37
|
||||||
|
- python: 3.8
|
||||||
|
env: TOXENV=py38
|
||||||
|
- python: 3.8-dev
|
||||||
|
env: TOXENV=py38
|
||||||
- python: nightly
|
- python: nightly
|
||||||
env: TOXENV=py37
|
env: TOXENV=py38
|
||||||
- python: pypy
|
|
||||||
env: TOXENV=pypy
|
|
||||||
- python: pypy3
|
- python: pypy3
|
||||||
env: TOXENV=pypy3
|
env: TOXENV=pypy3
|
||||||
- python: 2.7
|
- python: 3.8
|
||||||
env: TOXENV=docs
|
env: TOXENV=docs
|
||||||
- python: 2.7
|
- python: 3.8
|
||||||
env: TOXENV=flake8
|
|
||||||
- python: 3.6
|
|
||||||
env: TOXENV=flake8
|
env: TOXENV=flake8
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- python: 3.6-dev
|
|
||||||
- python: 3.7-dev
|
- python: 3.7-dev
|
||||||
|
- python: 3.8-dev
|
||||||
- python: nightly
|
- python: nightly
|
||||||
- python: pypy3
|
- python: pypy3
|
||||||
|
- os: windows
|
||||||
|
- os: osx
|
||||||
before_install:
|
before_install:
|
||||||
- pip install tox codecov 'sphinx>=1.5.1'
|
- pip install tox codecov 'sphinx>=1.5.1'
|
||||||
- ./doc/generate_authors.sh --check
|
- ./doc/generate_authors.sh --check
|
||||||
@@ -63,4 +78,4 @@ deploy:
|
|||||||
tags: true
|
tags: true
|
||||||
repo: python-escpos/python-escpos
|
repo: python-escpos/python-escpos
|
||||||
branch: master
|
branch: master
|
||||||
condition: $TRAVIS_PYTHON_VERSION = "3.6"
|
condition: $TRAVIS_PYTHON_VERSION = "3.8"
|
||||||
|
16
.vscode/tasks.json
vendored
Normal file
16
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "test with tox",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "tox",
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
AUTHORS
10
AUTHORS
@@ -1,6 +1,10 @@
|
|||||||
Ahmed Tahri
|
Ahmed Tahri
|
||||||
|
akeonly
|
||||||
|
Alexander Bougakov
|
||||||
|
Alex Debiasio
|
||||||
Asuki Kono
|
Asuki Kono
|
||||||
belono
|
belono
|
||||||
|
Brian
|
||||||
Christoph Heuel
|
Christoph Heuel
|
||||||
Cody (Quantified Code Bot)
|
Cody (Quantified Code Bot)
|
||||||
csoft2k
|
csoft2k
|
||||||
@@ -8,20 +12,25 @@ Curtis // mashedkeyboard
|
|||||||
Davis Goglin
|
Davis Goglin
|
||||||
Dean Rispin
|
Dean Rispin
|
||||||
Dmytro Katyukha
|
Dmytro Katyukha
|
||||||
|
Gerard Marull-Paretas
|
||||||
Hark
|
Hark
|
||||||
Joel Lehtonen
|
Joel Lehtonen
|
||||||
|
Justin Vieira
|
||||||
kennedy
|
kennedy
|
||||||
Kristi
|
Kristi
|
||||||
ldos
|
ldos
|
||||||
Lucy Linder
|
Lucy Linder
|
||||||
Manuel F Martinez
|
Manuel F Martinez
|
||||||
|
Maximilian Wagenbach
|
||||||
Michael Billington
|
Michael Billington
|
||||||
Michael Elsdörfer
|
Michael Elsdörfer
|
||||||
mrwunderbar666
|
mrwunderbar666
|
||||||
Nathan Bookham
|
Nathan Bookham
|
||||||
|
Omer Akram
|
||||||
Patrick Kanzler
|
Patrick Kanzler
|
||||||
primax79
|
primax79
|
||||||
Qian Linfeng
|
Qian Linfeng
|
||||||
|
Ramon Poca
|
||||||
reck31
|
reck31
|
||||||
Renato Lorenzi
|
Renato Lorenzi
|
||||||
Romain Porte
|
Romain Porte
|
||||||
@@ -30,4 +39,5 @@ Sergio Pulgarin
|
|||||||
Stephan Sokolow
|
Stephan Sokolow
|
||||||
Thijs Triemstra
|
Thijs Triemstra
|
||||||
Thomas van den Berg
|
Thomas van den Berg
|
||||||
|
Yaisel Hurtado
|
||||||
ysuolmai
|
ysuolmai
|
||||||
|
@@ -1,6 +1,70 @@
|
|||||||
*********
|
*********
|
||||||
Changelog
|
Changelog
|
||||||
*********
|
*********
|
||||||
|
2020-05-09 - Version 3.0a7 - "No Fixed Abode"
|
||||||
|
---------------------------------------------
|
||||||
|
This release is the eight alpha release of the new version 3.0.
|
||||||
|
Please be aware that the API is subject to change until v3.0
|
||||||
|
is released.
|
||||||
|
|
||||||
|
This release also marks the point at which the project transitioned
|
||||||
|
to having only a master-branch (and not an additional development branch).
|
||||||
|
|
||||||
|
changes
|
||||||
|
^^^^^^^
|
||||||
|
- add Exception for NotImplementedError in detach_kernel_driver
|
||||||
|
- update installation information
|
||||||
|
- update and improve documentation
|
||||||
|
- add error handling to image centering flag
|
||||||
|
- update and fix tox and CI environment, preparing drop of support for Python 2
|
||||||
|
|
||||||
|
contributors
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
- Alexander Bougakov
|
||||||
|
- Brian
|
||||||
|
- Yaisel Hurtado
|
||||||
|
- Maximilan Wagenbach
|
||||||
|
- Patrick Kanzler
|
||||||
|
|
||||||
|
2019-06-19 - Version 3.0a6 - "Mistake not..."
|
||||||
|
---------------------------------------------
|
||||||
|
This release is the seventh alpha release of the new version 3.0.
|
||||||
|
Please be aware that the API is subject to change until v3.0 is
|
||||||
|
released.
|
||||||
|
|
||||||
|
changes
|
||||||
|
^^^^^^^
|
||||||
|
- fix inclusion of the capabilities-file
|
||||||
|
- execute CI jobs also on Windows and macOS-targets
|
||||||
|
- improve documentation
|
||||||
|
|
||||||
|
contributors
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
- Patrick Kanzler
|
||||||
|
|
||||||
|
2019-06-16 - Version 3.0a5 - "Lightly Seared On The Reality Grill"
|
||||||
|
------------------------------------------------------------------
|
||||||
|
This release is the sixth alpha release of the new version 3.0. Please
|
||||||
|
be aware that the API is subject to change until v3.0 is released.
|
||||||
|
|
||||||
|
changes
|
||||||
|
^^^^^^^
|
||||||
|
- allow arbitrary USB arguments in USB-class
|
||||||
|
- add Win32Raw-Printer on Windows-platforms
|
||||||
|
- add and improve Windows support of USB-class
|
||||||
|
- use pyyaml safe_load()
|
||||||
|
- improve doc
|
||||||
|
- implement _read method of Network printer class
|
||||||
|
|
||||||
|
contributors
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
- Patrick Kanzler
|
||||||
|
- Gerard Marull-Paretas
|
||||||
|
- Ramon Poca
|
||||||
|
- akeonly
|
||||||
|
- Omer Akram
|
||||||
|
- Justin Vieira
|
||||||
|
|
||||||
2018-05-15 - Version 3.0a4 - "Kakistocrat"
|
2018-05-15 - Version 3.0a4 - "Kakistocrat"
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
This release is the fifth alpha release of the new version 3.0. Please
|
This release is the fifth alpha release of the new version 3.0. Please
|
||||||
|
@@ -56,12 +56,9 @@ Apart from that the travis-log and the check by Landscape will provide you with
|
|||||||
|
|
||||||
GIT
|
GIT
|
||||||
^^^
|
^^^
|
||||||
The master-branch contains code that has been released to PyPi. A release is marked with a tag
|
The master-branch contains the main development of the project. A release to PyPi is marked with a tag
|
||||||
corresponding to the version. Issues are closed when they have been resolved in the development-branch.
|
corresponding to the version. Issues are closed when they have been resolved by merging into the master-branch.
|
||||||
|
When you have a change to make, begin by creating a new branch from the HEAD of `python-escpos/master`.
|
||||||
When you have a change to make, begin by creating a new branch from the HEAD of `python-escpos/development`.
|
|
||||||
Name your branch to indicate what you are trying to achieve. Good branch names might
|
|
||||||
be `improve/text-handling`, `feature/enable-color-printing`.
|
|
||||||
|
|
||||||
Please try to group your commits into logical units. If you need to tidy up your branch, you can make use of a
|
Please try to group your commits into logical units. If you need to tidy up your branch, you can make use of a
|
||||||
git feature called an 'interactive rebase' before making a pull request. A small, self-contained change-set is
|
git feature called an 'interactive rebase' before making a pull request. A small, self-contained change-set is
|
||||||
|
23
INSTALL
23
INSTALL
@@ -1,23 +1,10 @@
|
|||||||
python-escpos
|
python-escpos
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Ensure the library is installed on ${lib_arch}/${python_ver}/site-packages/escpos
|
This library is available over pypi. So for most of the use-cases it should be sufficient to run
|
||||||
|
|
||||||
On CLi you must run:
|
```
|
||||||
# python setup.py build
|
pip install python-escpos --user # add --pre if you want to install pre-releases
|
||||||
# sudo python setup.py install
|
```
|
||||||
|
|
||||||
On Linux, ensure you belongs to the proper group so you can have access to the printer.
|
For more information please read the documentation at https://python-escpos.readthedocs.io/en/latest/user/installation.html
|
||||||
This can be done, by adding yourself to 'dialout' group, this might require to re-login
|
|
||||||
so the changes make effect.
|
|
||||||
|
|
||||||
Then, add the following rule to /etc/udev/rules.d/99-escpos.rules
|
|
||||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0202", MODE="0664", GROUP="dialout"
|
|
||||||
|
|
||||||
and restar udev rules.
|
|
||||||
# sudo service udev restart
|
|
||||||
|
|
||||||
Enjoy !!!
|
|
||||||
And please, don't forget to ALWAYS add Epson.cut() at the end of your printing :)
|
|
||||||
|
|
||||||
Manuel F Martinez <manpaz@bashlinux.com>
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
include *.rst
|
include *.rst
|
||||||
include *.txt
|
include *.txt
|
||||||
include COPYING
|
|
||||||
include LICENSE
|
include LICENSE
|
||||||
include INSTALL
|
include INSTALL
|
||||||
include tox.ini
|
include tox.ini
|
||||||
include capabilities-data/dist/capabilities.json
|
include capabilities-data/dist/capabilities.json
|
||||||
|
include src/escpos/capabilities.json
|
||||||
recursive-include doc *.bat
|
recursive-include doc *.bat
|
||||||
recursive-include doc *.ico
|
recursive-include doc *.ico
|
||||||
recursive-include doc *.py
|
recursive-include doc *.py
|
||||||
|
32
README.rst
32
README.rst
@@ -65,6 +65,38 @@ The basic usage is:
|
|||||||
p.barcode('1324354657687', 'EAN13', 64, 2, '', '')
|
p.barcode('1324354657687', 'EAN13', 64, 2, '', '')
|
||||||
p.cut()
|
p.cut()
|
||||||
|
|
||||||
|
|
||||||
|
Another example based on the Network printer class:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from escpos.printer import Network
|
||||||
|
|
||||||
|
kitchen = Network("192.168.1.100") #Printer IP Address
|
||||||
|
kitchen.text("Hello World\n")
|
||||||
|
kitchen.barcode('1324354657687', 'EAN13', 64, 2, '', '')
|
||||||
|
kitchen.cut()
|
||||||
|
|
||||||
|
Another example based on the Serial printer class:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from escpos.printer import Serial
|
||||||
|
|
||||||
|
""" 9600 Baud, 8N1, Flow Control Enabled """
|
||||||
|
p = Serial(devfile='/dev/tty.usbserial',
|
||||||
|
baudrate=9600,
|
||||||
|
bytesize=8,
|
||||||
|
parity='N',
|
||||||
|
stopbits=1,
|
||||||
|
timeout=1.00,
|
||||||
|
dsrdtr=True)
|
||||||
|
|
||||||
|
p.text("Hello World\n")
|
||||||
|
p.qr("You can readme from your smartphone")
|
||||||
|
p.cut()
|
||||||
|
|
||||||
|
|
||||||
The full project-documentation is available on `Read the Docs <https://python-escpos.readthedocs.io>`_.
|
The full project-documentation is available on `Read the Docs <https://python-escpos.readthedocs.io>`_.
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
|
Submodule capabilities-data updated: 8885283d71...3b5b35cfd3
@@ -2,38 +2,9 @@
|
|||||||
TODO
|
TODO
|
||||||
****
|
****
|
||||||
|
|
||||||
Introduction
|
Open points and issues of the project are tracked in the GitHub issues.
|
||||||
------------
|
Some annotations still remain in the code and should be moved over time
|
||||||
|
into the issue tracker.
|
||||||
python-escpos is the initial idea, from here we can start to build a
|
|
||||||
robust library to get most of the ESC/POS printers working with this
|
|
||||||
library.
|
|
||||||
|
|
||||||
Eventually, this library must be able to cover almost all the defined
|
|
||||||
models detailed in the ESC/POS Command Specification Manual.
|
|
||||||
|
|
||||||
Details
|
|
||||||
-------
|
|
||||||
|
|
||||||
What things are planned to work on?
|
|
||||||
|
|
||||||
Testing
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
* Test on many printers as possible (USB, Serial, Network)
|
|
||||||
* automate testing
|
|
||||||
|
|
||||||
Design
|
|
||||||
~~~~~~
|
|
||||||
|
|
||||||
* Add all those sequences which are not common, but part of the ESC/POS
|
|
||||||
Command Specifications.
|
|
||||||
|
|
||||||
* Port to Python 3
|
|
||||||
* Windows compatibility (hidapi instead libusb?)
|
|
||||||
* PDF417 support
|
|
||||||
|
|
||||||
* use something similar to the `capabilities` in escpos-php
|
|
||||||
|
|
||||||
Todos in the codebase
|
Todos in the codebase
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@@ -44,18 +44,20 @@ to have and the second yields the "Output Endpoint" address.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
Epson = printer.Usb(0x04b8,0x0202)
|
p = printer.Usb(0x04b8,0x0202)
|
||||||
|
|
||||||
By default the "Interface" number is "0" and the "Output Endpoint"
|
By default the "Interface" number is "0" and the "Output Endpoint"
|
||||||
address is "0x01". If you have other values then you can define them on
|
address is "0x01". If you have other values then you can define them on
|
||||||
your instance. So, assuming that we have another printer where in\_ep is
|
your instance. So, assuming that we have another printer, CT-S2000,
|
||||||
on 0x81 and out\_ep=0x02, then the printer definition should look like:
|
manufactured by Citizen (with "Vendor ID" of 2730 and "Product ID" of 0fff)
|
||||||
|
where in\_ep is on 0x81 and out\_ep=0x02, then the printer definition should
|
||||||
|
look like:
|
||||||
|
|
||||||
**Generic USB Printer initialization**
|
**Generic USB Printer initialization**
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
Generic = printer.Usb(0x1a2b,0x1a2b,0,0x81,0x02)
|
p = printer.Usb(0x2730, 0x0fff, 0, 0x81, 0x02)
|
||||||
|
|
||||||
Network printer
|
Network printer
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
@@ -67,7 +69,7 @@ IP by DHCP or you set it manually.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
Epson = printer.Network("192.168.1.99")
|
p = printer.Network("192.168.1.99")
|
||||||
|
|
||||||
Serial printer
|
Serial printer
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
@@ -81,7 +83,10 @@ to.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
Epson = printer.Serial("/dev/tty0")
|
p = printer.Serial("/dev/tty0")
|
||||||
|
|
||||||
|
# on a Windows OS serial devices are typically accessible as COM
|
||||||
|
p = printer.Serial("COM1")
|
||||||
|
|
||||||
Other printers
|
Other printers
|
||||||
^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^
|
||||||
@@ -93,7 +98,7 @@ passing the device node name.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
Epson = printer.File("/dev/usb/lp1")
|
p = printer.File("/dev/usb/lp1")
|
||||||
|
|
||||||
The default is "/dev/usb/lp0", so if the printer is located on that
|
The default is "/dev/usb/lp0", so if the printer is located on that
|
||||||
node, then you don't necessary need to pass the node name.
|
node, then you don't necessary need to pass the node name.
|
||||||
@@ -108,17 +113,17 @@ on a USB interface.
|
|||||||
|
|
||||||
from escpos import *
|
from escpos import *
|
||||||
""" Seiko Epson Corp. Receipt Printer M129 Definitions (EPSON TM-T88IV) """
|
""" Seiko Epson Corp. Receipt Printer M129 Definitions (EPSON TM-T88IV) """
|
||||||
Epson = printer.Usb(0x04b8,0x0202)
|
p = printer.Usb(0x04b8,0x0202)
|
||||||
# Print text
|
# Print text
|
||||||
Epson.text("Hello World\n")
|
p.text("Hello World\n")
|
||||||
# Print image
|
# Print image
|
||||||
Epson.image("logo.gif")
|
p.image("logo.gif")
|
||||||
# Print QR Code
|
# Print QR Code
|
||||||
Epson.qr("You can readme from your smartphone")
|
p.qr("You can readme from your smartphone")
|
||||||
# Print barcode
|
# Print barcode
|
||||||
Epson.barcode('1324354657687','EAN13',64,2,'','')
|
p.barcode('1324354657687','EAN13',64,2,'','')
|
||||||
# Cut paper
|
# Cut paper
|
||||||
Epson.cut()
|
p.cut()
|
||||||
|
|
||||||
Configuration File
|
Configuration File
|
||||||
------------------
|
------------------
|
||||||
|
@@ -3,5 +3,5 @@ formats:
|
|||||||
- epub
|
- epub
|
||||||
requirements_file: doc/requirements.txt
|
requirements_file: doc/requirements.txt
|
||||||
python:
|
python:
|
||||||
version: 2
|
version: 3
|
||||||
setup_py_install: true
|
setup_py_install: true
|
9
setup.py
9
setup.py
@@ -56,7 +56,7 @@ setup(
|
|||||||
platforms='any',
|
platforms='any',
|
||||||
package_dir={"": "src"},
|
package_dir={"": "src"},
|
||||||
packages=find_packages(where="src", exclude=["tests", "tests.*"]),
|
packages=find_packages(where="src", exclude=["tests", "tests.*"]),
|
||||||
package_data={'': ['COPYING', 'src/escpos/capabilities.json']},
|
package_data={'escpos': ['capabilities.json']},
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
@@ -65,15 +65,12 @@ setup(
|
|||||||
'License :: OSI Approved :: MIT License',
|
'License :: OSI Approved :: MIT License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.4',
|
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
|
'Programming Language :: Python :: 3.8',
|
||||||
'Programming Language :: Python :: Implementation :: CPython',
|
'Programming Language :: Python :: Implementation :: CPython',
|
||||||
'Programming Language :: Python :: Implementation :: PyPy',
|
|
||||||
'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',
|
||||||
],
|
],
|
||||||
@@ -102,7 +99,7 @@ setup(
|
|||||||
'nose',
|
'nose',
|
||||||
'scripttest',
|
'scripttest',
|
||||||
'mock',
|
'mock',
|
||||||
'hypothesis!=3.56.9',
|
'hypothesis>4',
|
||||||
'flake8'
|
'flake8'
|
||||||
],
|
],
|
||||||
entry_points={
|
entry_points={
|
||||||
|
@@ -38,7 +38,7 @@ else:
|
|||||||
if full_load:
|
if full_load:
|
||||||
logger.debug('Loading and pickling capabilities')
|
logger.debug('Loading and pickling capabilities')
|
||||||
with open(capabilities_path) as cp, open(pickle_path, 'wb') as pp:
|
with open(capabilities_path) as cp, open(pickle_path, 'wb') as pp:
|
||||||
CAPABILITIES = yaml.load(cp)
|
CAPABILITIES = yaml.safe_load(cp)
|
||||||
pickle.dump(CAPABILITIES, pp, protocol=2)
|
pickle.dump(CAPABILITIES, pp, protocol=2)
|
||||||
|
|
||||||
logger.debug('Finished loading capabilities took %.2fs', time.time() - t0)
|
logger.debug('Finished loading capabilities took %.2fs', time.time() - t0)
|
||||||
|
@@ -106,6 +106,9 @@ class Escpos(object):
|
|||||||
* `graphics`: prints with the `GS ( L`-command
|
* `graphics`: prints with the `GS ( L`-command
|
||||||
* `bitImageColumn`: prints with the `ESC *`-command
|
* `bitImageColumn`: prints with the `ESC *`-command
|
||||||
|
|
||||||
|
When trying to center an image make sure you have initialized the printer with a valid profile, that
|
||||||
|
contains a media width pixel field. Otherwise the centering will have no effect.
|
||||||
|
|
||||||
:param img_source: PIL image or filename to load: `jpg`, `gif`, `png` or `bmp`
|
:param img_source: PIL image or filename to load: `jpg`, `gif`, `png` or `bmp`
|
||||||
:param high_density_vertical: print in high density in vertical direction *default:* True
|
:param high_density_vertical: print in high density in vertical direction *default:* True
|
||||||
:param high_density_horizontal: print in high density in horizontal direction *default:* True
|
:param high_density_horizontal: print in high density in horizontal direction *default:* True
|
||||||
@@ -117,6 +120,10 @@ class Escpos(object):
|
|||||||
im = EscposImage(img_source)
|
im = EscposImage(img_source)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if self.profile.profile_data['media']['width']['pixels'] == "Unknown":
|
||||||
|
print("The media.width.pixel field of the printer profile is not set. " +
|
||||||
|
"The center flag will have no effect.")
|
||||||
|
|
||||||
max_width = int(self.profile.profile_data['media']['width']['pixels'])
|
max_width = int(self.profile.profile_data['media']['width']['pixels'])
|
||||||
|
|
||||||
if im.width > max_width:
|
if im.width > max_width:
|
||||||
@@ -195,6 +202,7 @@ class Escpos(object):
|
|||||||
:param native: True to render the code on the printer, False to render the code as an image and send it to the
|
:param native: True to render the code on the printer, False to render the code as an image and send it to the
|
||||||
printer (Default)
|
printer (Default)
|
||||||
:param center: Centers the code *default:* False
|
:param center: Centers the code *default:* False
|
||||||
|
:param impl: Image-printing-implementation, refer to :meth:`.image()` for details
|
||||||
"""
|
"""
|
||||||
# Basic validation
|
# Basic validation
|
||||||
if ec not in [QR_ECLEVEL_L, QR_ECLEVEL_M, QR_ECLEVEL_H, QR_ECLEVEL_Q]:
|
if ec not in [QR_ECLEVEL_L, QR_ECLEVEL_M, QR_ECLEVEL_H, QR_ECLEVEL_Q]:
|
||||||
@@ -306,8 +314,8 @@ class Escpos(object):
|
|||||||
.. todo:: For fixed-length standards with mandatory checksum (EAN, UPC),
|
.. todo:: For fixed-length standards with mandatory checksum (EAN, UPC),
|
||||||
compute and add the checksum automatically if missing.
|
compute and add the checksum automatically if missing.
|
||||||
|
|
||||||
:param bc: barcode format, see :py:func`~escpos.Escpos.barcode`
|
:param bc: barcode format, see :py:meth:`.barcode()`
|
||||||
:param code: alphanumeric data to be printed as bar code, see :py:func`~escpos.Escpos.barcode`
|
:param code: alphanumeric data to be printed as bar code, see :py:meth:`.barcode()`
|
||||||
:return: bool
|
:return: bool
|
||||||
"""
|
"""
|
||||||
if bc not in BARCODE_FORMATS:
|
if bc not in BARCODE_FORMATS:
|
||||||
@@ -394,7 +402,7 @@ class Escpos(object):
|
|||||||
*default*: A
|
*default*: A
|
||||||
|
|
||||||
:param check: If this parameter is True, the barcode format will be checked to ensure it meets the bc
|
:param check: If this parameter is True, the barcode format will be checked to ensure it meets the bc
|
||||||
requirements as defigned in the esc/pos documentation. See py:func:`~escpos.Escpos.check_barcode`
|
requirements as defigned in the esc/pos documentation. See :py:meth:`.check_barcode()`
|
||||||
for more information. *default*: True.
|
for more information. *default*: True.
|
||||||
|
|
||||||
:raises: :py:exc:`~escpos.exceptions.BarcodeSizeError`,
|
:raises: :py:exc:`~escpos.exceptions.BarcodeSizeError`,
|
||||||
|
@@ -8,15 +8,12 @@
|
|||||||
:license: MIT
|
:license: MIT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import usb.core
|
|
||||||
import usb.util
|
|
||||||
import serial
|
import serial
|
||||||
import socket
|
import socket
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
|
||||||
from .escpos import Escpos
|
from .escpos import Escpos
|
||||||
from .exceptions import USBNotFoundError
|
from .exceptions import USBNotFoundError
|
||||||
@@ -34,41 +31,60 @@ class Usb(Escpos):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, idVendor, idProduct, timeout=0, in_ep=0x82, out_ep=0x01, *args, **kwargs): # noqa: N803
|
def __init__(self, idVendor, idProduct, usb_args=None, timeout=0, in_ep=0x82, out_ep=0x01,
|
||||||
|
*args, **kwargs): # noqa: N803
|
||||||
"""
|
"""
|
||||||
:param idVendor: Vendor ID
|
:param idVendor: Vendor ID
|
||||||
:param idProduct: Product ID
|
:param idProduct: Product ID
|
||||||
|
:param usb_args: Optional USB arguments (e.g. custom_match)
|
||||||
:param timeout: Is the time limit of the USB operation. Default without timeout.
|
:param timeout: Is the time limit of the USB operation. Default without timeout.
|
||||||
:param in_ep: Input end point
|
:param in_ep: Input end point
|
||||||
:param out_ep: Output end point
|
:param out_ep: Output end point
|
||||||
"""
|
"""
|
||||||
Escpos.__init__(self, *args, **kwargs)
|
Escpos.__init__(self, *args, **kwargs)
|
||||||
self.idVendor = idVendor
|
|
||||||
self.idProduct = idProduct
|
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.in_ep = in_ep
|
self.in_ep = in_ep
|
||||||
self.out_ep = out_ep
|
self.out_ep = out_ep
|
||||||
self.open()
|
|
||||||
|
|
||||||
def open(self):
|
usb_args = usb_args or {}
|
||||||
""" Search device on USB tree and set it as escpos device """
|
if idVendor:
|
||||||
self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
|
usb_args['idVendor'] = idVendor
|
||||||
|
if idProduct:
|
||||||
|
usb_args['idProduct'] = idProduct
|
||||||
|
self.open(usb_args)
|
||||||
|
|
||||||
|
def open(self, usb_args):
|
||||||
|
""" Search device on USB tree and set it as escpos device.
|
||||||
|
|
||||||
|
:param usb_args: USB arguments
|
||||||
|
"""
|
||||||
|
self.device = usb.core.find(**usb_args)
|
||||||
if self.device is None:
|
if self.device is None:
|
||||||
raise USBNotFoundError("Device not found or cable not plugged in.")
|
raise USBNotFoundError("Device not found or cable not plugged in.")
|
||||||
|
|
||||||
check_driver = None
|
self.idVendor = self.device.idVendor
|
||||||
|
self.idProduct = self.device.idProduct
|
||||||
|
|
||||||
try:
|
# pyusb has three backends: libusb0, libusb1 and openusb but
|
||||||
check_driver = self.device.is_kernel_driver_active(0)
|
# only libusb1 backend implements the methods is_kernel_driver_active()
|
||||||
except NotImplementedError:
|
# and detach_kernel_driver().
|
||||||
pass
|
# This helps enable this library to work on Windows.
|
||||||
|
if self.device.backend.__module__.endswith("libusb1"):
|
||||||
|
check_driver = None
|
||||||
|
|
||||||
if check_driver is None or check_driver:
|
|
||||||
try:
|
try:
|
||||||
self.device.detach_kernel_driver(0)
|
check_driver = self.device.is_kernel_driver_active(0)
|
||||||
except usb.core.USBError as e:
|
except NotImplementedError:
|
||||||
if check_driver is not None:
|
pass
|
||||||
print("Could not detatch kernel driver: {0}".format(str(e)))
|
|
||||||
|
if check_driver is None or check_driver:
|
||||||
|
try:
|
||||||
|
self.device.detach_kernel_driver(0)
|
||||||
|
except NotImplementedError:
|
||||||
|
pass
|
||||||
|
except usb.core.USBError as e:
|
||||||
|
if check_driver is not None:
|
||||||
|
print("Could not detatch kernel driver: {0}".format(str(e)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.device.set_configuration()
|
self.device.set_configuration()
|
||||||
@@ -219,6 +235,11 @@ class Network(Escpos):
|
|||||||
"""
|
"""
|
||||||
self.device.sendall(msg)
|
self.device.sendall(msg)
|
||||||
|
|
||||||
|
def _read(self):
|
||||||
|
""" Read data from the TCP socket """
|
||||||
|
|
||||||
|
return self.device.recv(16)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
""" Close TCP connection """
|
""" Close TCP connection """
|
||||||
if self.device is not None:
|
if self.device is not None:
|
||||||
@@ -322,3 +343,49 @@ class Dummy(Escpos):
|
|||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
_WIN32PRINT = False
|
||||||
|
try:
|
||||||
|
import win32print
|
||||||
|
|
||||||
|
_WIN32PRINT = True
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if _WIN32PRINT:
|
||||||
|
class Win32Raw(Escpos):
|
||||||
|
def __init__(self, printer_name=None, *args, **kwargs):
|
||||||
|
Escpos.__init__(self, *args, **kwargs)
|
||||||
|
if printer_name is not None:
|
||||||
|
self.printer_name = printer_name
|
||||||
|
else:
|
||||||
|
self.printer_name = win32print.GetDefaultPrinter()
|
||||||
|
self.hPrinter = None
|
||||||
|
|
||||||
|
def open(self, job_name="python-escpos"):
|
||||||
|
if self.printer_name is None:
|
||||||
|
raise Exception("Printer not found")
|
||||||
|
self.hPrinter = win32print.OpenPrinter(self.printer_name)
|
||||||
|
self.current_job = win32print.StartDocPrinter(self.hPrinter, 1, (job_name, None, "RAW"))
|
||||||
|
win32print.StartPagePrinter(self.hPrinter)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if not self.hPrinter:
|
||||||
|
return
|
||||||
|
win32print.EndPagePrinter(self.hPrinter)
|
||||||
|
win32print.EndDocPrinter(self.hPrinter)
|
||||||
|
win32print.ClosePrinter(self.hPrinter)
|
||||||
|
self.hPrinter = None
|
||||||
|
|
||||||
|
def _raw(self, msg):
|
||||||
|
""" Print any command sent in raw format
|
||||||
|
|
||||||
|
:param msg: arbitrary code to be printed
|
||||||
|
:type msg: bytes
|
||||||
|
"""
|
||||||
|
if self.printer_name is None:
|
||||||
|
raise Exception("Printer not found")
|
||||||
|
if self.hPrinter is None:
|
||||||
|
raise Exception("Printer job not opened")
|
||||||
|
win32print.WritePrinter(self.hPrinter, msg)
|
||||||
|
@@ -28,7 +28,6 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
||||||
@settings(use_coverage=False)
|
|
||||||
@given(path=text())
|
@given(path=text())
|
||||||
def test_load_file_printer(mocker, path):
|
def test_load_file_printer(mocker, path):
|
||||||
"""test the loading of the file-printer"""
|
"""test the loading of the file-printer"""
|
||||||
@@ -40,7 +39,6 @@ def test_load_file_printer(mocker, path):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
||||||
@settings(deadline=None, use_coverage=False)
|
|
||||||
@given(txt=text())
|
@given(txt=text())
|
||||||
def test_auto_flush(mocker, txt):
|
def test_auto_flush(mocker, txt):
|
||||||
"""test auto_flush in file-printer"""
|
"""test auto_flush in file-printer"""
|
||||||
@@ -62,7 +60,6 @@ def test_auto_flush(mocker, txt):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
@pytest.mark.skip("this test is broken and has to be fixed or discarded")
|
||||||
@settings(deadline=None, use_coverage=False)
|
|
||||||
@given(txt=text())
|
@given(txt=text())
|
||||||
def test_flush_on_close(mocker, txt):
|
def test_flush_on_close(mocker, txt):
|
||||||
"""test flush on close in file-printer"""
|
"""test flush on close in file-printer"""
|
||||||
|
13
tox.ini
13
tox.ini
@@ -1,5 +1,12 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py27, py34, py35, docs, flake8
|
envlist = py35, py36, py37, py38, docs, flake8
|
||||||
|
|
||||||
|
[gh-actions]
|
||||||
|
python =
|
||||||
|
2.7: py27
|
||||||
|
3.6: py36
|
||||||
|
3.7: py37
|
||||||
|
3.8: py38
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = nose
|
deps = nose
|
||||||
@@ -10,9 +17,9 @@ deps = nose
|
|||||||
pytest!=3.2.0,!=3.3.0
|
pytest!=3.2.0,!=3.3.0
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-mock
|
pytest-mock
|
||||||
hypothesis!=3.56.9
|
hypothesis>4
|
||||||
viivakoodi
|
viivakoodi
|
||||||
commands = py.test --cov escpos
|
commands = pytest --cov escpos
|
||||||
passenv = ESCPOS_CAPABILITIES_PICKLE_DIR ESCPOS_CAPABILITIES_FILE CI TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* CODECOV_*
|
passenv = ESCPOS_CAPABILITIES_PICKLE_DIR ESCPOS_CAPABILITIES_FILE CI TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* CODECOV_*
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
|
Reference in New Issue
Block a user