diff --git a/README.md b/README.md deleted file mode 100644 index d71783d..0000000 --- a/README.md +++ /dev/null @@ -1,39 +0,0 @@ -pyzpl2 -====== - -Python ZPL2 Library generates ZPL2 code which can be sent to Zebra or similar label printers. The library uses only millimeters as units and converts them internally according to printer settings. - -Example use ------------ -```python -l = Label(65,60) -height = 0 -l.origin(0,0) -l.write_text("Problem?", char_height=10, char_width=8, line_width=60, justification='C') -l.endorigin() - -height += 13 -image_width = 55 -l.origin((l.width-image_width)/2, height) -image_height = l.write_graphic(Image.open('trollface-large.png'), image_width) -l.endorigin() - -l.origin(0, height+image_height) -l.write_text('Happy Troloween!', char_height=5, char_width=4, line_width=60, - justification='C') -l.endorigin() - -print l.dumpZPL() -l.preview() -``` -This will display the following preview image, generated using the [Labelary API](http://labelary.com/): -![label preview](http://api.labelary.com/v1/printers/12dpmm/labels/2.362205x1.181102/0/^XA^FO0,0^A0N,120,96^FB720,1,0,C,0^FDProblem?^FS^FO324,156^GFA,384,384,8,00000000000000000003FFFFFF800000000400FF007E0000001802001FF0C0000010103F000030000020420000F08C00004110E100000200000204020101010000840001008081000080200100000100010001E10100410003001F8C01000080060037C2007F00C00E203FE100FFBE201400801D07C0009038FC0102010001506103860001001C907200780001006210621800000183C030421600160040109042F1801800301010721062080038181042103C0D20401920300C21C0008038201A0F20380300DC401A04F013C0075C400C023C103FF64C4002023FA020824C00020123F020827C000100E07FFFFFFC0001004027FFFFFC0000803000FFFFF80000C018404FFFA8000060064041093800003041804109300000090070411360000004400FC13F804000031100000000400000C46000002040000030840E00044000000C0C1FC6084000000180C00020400000006001FF004000000018000000C0000000060000008000000001E0000100000000000F0006000000000000FFF000^FS^FO0,204^A0N,60,48^FB720,1,0,C,0^FDHappy Troloween!^FS^XZ) - -The generated ZPL2 code is: -``` -^XA^FO0,0^A0N,120,96^FB720,1,0,C,0^FDProblem?^FS^FO324,156^GFA,384,384,8,00000000000000000003FFFFFF800000000400FF007E0000001802001FF0C0000010103F000030000020420000F08C00004110E100000200000204020101010000840001008081000080200100000100010001E10100410003001F8C01000080060037C2007F00C00E203FE100FFBE201400801D07C0009038FC0102010001506103860001001C907200780001006210621800000183C030421600160040109042F1801800301010721062080038181042103C0D20401920300C21C0008038201A0F20380300DC401A04F013C0075C400C023C103FF64C4002023FA020824C00020123F020827C000100E07FFFFFFC0001004027FFFFFC0000803000FFFFF80000C018404FFFA8000060064041093800003041804109300000090070411360000004400FC13F804000031100000000400000C46000002040000030840E00044000000C0C1FC6084000000180C00020400000006001FF004000000018000000C0000000060000008000000001E0000100000000000F0006000000000000FFF000^FS^FO0,204^A0N,60,48^FB720,1,0,C,0^FDHappy Troloween!^FS^XZ -``` - -Requirements ------------- -* PIL diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..92fd817 --- /dev/null +++ b/README.rst @@ -0,0 +1,54 @@ +zpl +=== + +Python ZPL2 Library generates ZPL2 code which can be sent to Zebra or similar label printers. The library uses only Millimeter as unit and converts them internally according to printer settings. + +Example use +----------- + +.. code-block:: python + + from zpl import Label + + l = Label(65,60) + height = 0 + l.origin(0,0) + l.write_text("Problem?", char_height=10, char_width=8, line_width=60, + justification='C') + l.endorigin() + + height += 13 + image_width = 55 + l.origin((l.width-image_width)/2, height) + image_height = l.write_graphic(Image.open('trollface-large.png'), + image_width) + l.endorigin() + + l.origin(0, height+image_height) + l.write_text('Happy Troloween!', char_height=5, char_width=4, + line_width=60, + justification='C') + l.endorigin() + + print(l.dumpZPL()) + l.preview() + +This will display the following preview image, generated using the `Labelary API `_: +`label preview `_ + +The generated ZPL2 code is: + +:: + + ^XA^FO0,0^A0N,120,96^FB720,1,0,C,0^FDProblem?^FS^FO330,156^GFA,768,384,8,00003FFFC0000000000600000FF0000000180200C01F8000003008000000600000204080440D10000041080000000C000082420000CC020000840002000102000100200001008000010040000000800002000FF80000010006003F84003E01800C036F8200E100C01402307101FE01202878000E030000A071060200010001504201FC0000007C50821000000106C090A438000001800010A466001E0040115084A183C80070103042107009C044382060104E0800803A20300C40E00700F840380FE03C0003D8001A047021F83C588004027E2021845880020227E021047880020141F82187F8800100C07FFFFFF88001004047FFFFF88000803040FFFFF88000C00880419970800060078001117080001241C00012608000089038C237C08000060401FFF8008000011080000020000000C21040E0044000003863C0010840000006060000104000000180380080400000006000000080000000180000008000000007800001000000000038000600000000000380180000000000003FC000^FS^FO0,204^A0N,60,48^FB720,1,0,C,0^FDHappy Troloween!^FS^XZ + +Installation +------------ +:: + + pip install --user zpl + + +Requirements +------------ +* PIL or Pillow diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..21e3566 --- /dev/null +++ b/setup.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import io +import os +import re +from codecs import open # To use a consistent encoding + +from setuptools import setup, find_packages + +here = os.path.abspath(os.path.dirname(__file__)) + + +# Stolen from pip +def read(*names, **kwargs): + with io.open( + os.path.join(os.path.dirname(__file__), *names), + encoding=kwargs.get("encoding", "utf8") + ) as fp: + return fp.read() + + +# Stolen from pip +def find_version(*file_paths): + version_file = read(*file_paths) + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError("Unable to find version string.") + + +# Get the long description from the relevant file +with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: + long_description = f.read() + +setup( + name='zpl', + + # Versions should comply with PEP440. For a discussion on single-sourcing + # the version across setup.py and the project code, see + # https://packaging.python.org/en/latest/single_source_version.html + version=find_version('zpl', '__init__.py'), + + description='Driver and generator for ZPL2 lables.', + long_description=long_description, + + # The project's main homepage. + url='https://github.com/cod3monk/zpl', + + # Author details + author='Julian Hammer', + author_email='julian.hammer@u-sys.org', + + # Choose your license + license='AGPLv3', + + # See https://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 4 - Beta', + + # Indicate who your project is intended for + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering', + 'Topic :: Software Development', + 'Topic :: Utilities', + + # Pick your license as you wish (should match "license" above) + 'License :: OSI Approved :: GNU Affero General Public License v3', + + # Specify the Python versions you support here. In particular, ensure + # that you indicate whether you support Python 2, Python 3 or both. + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + ], + + # What does your project relate to? + keywords='label printer zebra zpl2 zpl', + + # You can just specify the packages manually here if your project is + # simple. Or you can use find_packages(). + packages=find_packages(exclude=[]), + + # List run-time dependencies here. These will be installed by pip when your + # project is installed. For an analysis of "install_requires" vs pip's + + # what is not found or up-to-date on pypi we get from github: + # dependency_links = ['https://github.com/sympy/sympy/tarball/master#egg=sympy-0.7.7.dev0'], + + # https://packaging.python.org/en/latest/requirements.html + install_requires=[ + 'Pillow' + ], + python_requires='>=2.7', + + # List additional groups of dependencies here (e.g. development dependencies). + # You can install these using the following syntax, for example: + # $ pip install -e .[dev,test] + extras_require={ + }, + + # If there are data files included in your packages that need to be + # installed, specify them here. If using Python 2.6 or less, then these + # have to be included in MANIFEST.in as well. + package_data={ + 'pyzpl2': ['tollface-large.png'], + }, + include_package_data=True, + + # Although 'package_data' is the preferred approach, in some case you may + # need to place data files outside of your packages. + # see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files + # In this case, 'data_file' will be installed into '/my_data' + # data_files=[('my_data', ['data/data_file'])], + + # To provide executable scripts, use entry points in preference to the + # "scripts" keyword. Entry points provide cross-platform support and allow + # pip to create the appropriate form of executable for the target platform. + entry_points={} +) diff --git a/zpl/__init__.py b/zpl/__init__.py new file mode 100755 index 0000000..ee3d8cf --- /dev/null +++ b/zpl/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +from .label import * +from .printer import * + +__version__ = '0.1' diff --git a/label.py b/zpl/label.py old mode 100644 new mode 100755 similarity index 94% rename from label.py rename to zpl/label.py index 7f5aa61..f14598d --- a/label.py +++ b/zpl/label.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +from __future__ import division +from __future__ import print_function + #import Image from PIL import Image import re @@ -7,6 +10,7 @@ import sys import math import webbrowser +import os.path try: from urllib.request import urlopen except ImportError: @@ -88,7 +92,7 @@ def _convert_image(self, image, width, height, compression_type='A'): image = PIL.ImageOps.invert(image.convert('L')).convert('1') if compression_type == "A": - return image.tobytes().hex().upper() + return image.tobytes().encode('hex').upper() # TODO this is not working #elif compression_type == "B": # return image.tostring() @@ -167,7 +171,7 @@ def write_field_number(self, number, name=None, char_height=None, char_width=Non self.code += "^FN%i" % number if name: assert re.match("^[a-zA-Z0-9 ]+$", name), "name may only contain alphanumerical " + \ - "characters and spaces" + "characters and spaces" self.code += '"%s"' % name def dumpZPL(self): @@ -183,24 +187,27 @@ def preview(self, index=0): Not all commands are supported, see http://labelary.com for more information. ''' try: - url = 'http://api.labelary.com/v1/printers/%idpmm/labels/%fx%f/%i/' % (self.dpmm, self.width/25.4, self.height/25.4, index) + url = 'http://api.labelary.com/v1/printers/%idpmm/labels/%fx%f/%i/' % ( + self.dpmm, self.width/25.4, self.height/25.4, index) res = urlopen(url, self.dumpZPL().encode()).read() Image.open(io.BytesIO(res)).show() except IOError: raise Exception("Invalid preview received, mostlikely bad ZPL2 code uploaded.") -if __name__ == "__main__": + +def __main__(): l = Label(30,60) height = 0 l.origin(0,0) l.write_text("Problem?", char_height=10, char_width=8, line_width=60, justification='C') l.endorigin() - height += 13 image_width = 5 l.origin((l.width-image_width)/2, height) - image_height = l.write_graphic(Image.open('trollface-large.png'), image_width) + image_height = l.write_graphic( + Image.open(os.path.join(os.path.dirname(__file__), 'trollface-large.png')), + image_width) l.endorigin() l.origin(0, height+image_height) @@ -210,3 +217,7 @@ def preview(self, index=0): print(l.dumpZPL()) l.preview() + + +if __name__ == "__main__": + __main__() diff --git a/printer.py b/zpl/printer.py old mode 100644 new mode 100755 similarity index 97% rename from printer.py rename to zpl/printer.py index 2da6f99..ad6df5a --- a/printer.py +++ b/zpl/printer.py @@ -1,4 +1,7 @@ -#!/bin/env/python +#!/usr/bin/env python + +from __future__ import division +from __future__ import print_function import socket import re @@ -82,7 +85,7 @@ def get_printer_config(self, reload=False): return self._cfg def get_label_dimensions(self): - length = int(self.get_printer_status()['label_length'])/self.get_dpmm() + length = int(self.get_printer_status()['label_length'])//self.get_dpmm() return (length, width) def get_dpi(self): diff --git a/trollface-large.png b/zpl/trollface-large.png similarity index 100% rename from trollface-large.png rename to zpl/trollface-large.png