Skip to content

Commit

Permalink
now we have a real python package
Browse files Browse the repository at this point in the history
  • Loading branch information
cod3monk committed Sep 27, 2018
1 parent ae9f840 commit 45ed486
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 47 deletions.
39 changes: 0 additions & 39 deletions README.md

This file was deleted.

54 changes: 54 additions & 0 deletions 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 <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^FO330,156^GFA,768,384,8,00003FFFC0000000000600000FF0000000180200C01F8000003008000000600000204080440D10000041080000000C000082420000CC020000840002000102000100200001008000010040000000800002000FF80000010006003F84003E01800C036F8200E100C01402307101FE01202878000E030000A071060200010001504201FC0000007C50821000000106C090A438000001800010A466001E0040115084A183C80070103042107009C044382060104E0800803A20300C40E00700F840380FE03C0003D8001A047021F83C588004027E2021845880020227E021047880020141F82187F8800100C07FFFFFF88001004047FFFFF88000803040FFFFF88000C00880419970800060078001117080001241C00012608000089038C237C08000060401FFF8008000011080000020000000C21040E0044000003863C0010840000006060000104000000180380080400000006000000080000000180000008000000007800001000000000038000600000000000380180000000000003FC000^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^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
129 changes: 129 additions & 0 deletions 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 '<sys.prefix>/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={}
)
6 changes: 6 additions & 0 deletions zpl/__init__.py
@@ -0,0 +1,6 @@
#!/usr/bin/env python

from .label import *
from .printer import *

__version__ = '0.1'
23 changes: 17 additions & 6 deletions label.py → zpl/label.py 100644 → 100755
@@ -1,12 +1,16 @@
#!/usr/bin/env python

from __future__ import division
from __future__ import print_function

#import Image
from PIL import Image
import re
import PIL.ImageOps
import sys
import math
import webbrowser
import os.path
try:
from urllib.request import urlopen
except ImportError:
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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):
Expand All @@ -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)
Expand All @@ -210,3 +217,7 @@ def preview(self, index=0):

print(l.dumpZPL())
l.preview()


if __name__ == "__main__":
__main__()
7 changes: 5 additions & 2 deletions printer.py → zpl/printer.py 100644 → 100755
@@ -1,4 +1,7 @@
#!/bin/env/python
#!/usr/bin/env python

from __future__ import division
from __future__ import print_function

import socket
import re
Expand Down Expand Up @@ -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):
Expand Down
File renamed without changes

0 comments on commit 45ed486

Please sign in to comment.