zaz-barcode/source/pythonpath/barcode/upc.py

115 lines
3.0 KiB
Python
Raw Normal View History

2019-09-09 22:42:38 -05:00
"""Module: barcode.upc
:Provided barcodes: UPC-A
"""
2020-10-11 19:48:57 -05:00
__docformat__ = "restructuredtext en"
from functools import reduce
from barcode.base import Barcode
from barcode.charsets import upc as _upc
from barcode.errors import IllegalCharacterError, NumberOfDigitsError
2019-09-09 22:42:38 -05:00
class UniversalProductCodeA(Barcode):
2020-10-11 19:48:57 -05:00
"""Universal Product Code (UPC) barcode.
UPC-A consists of 12 numeric digits.
2019-09-09 22:42:38 -05:00
"""
2020-10-11 19:48:57 -05:00
name = "UPC-A"
2019-09-09 22:42:38 -05:00
digits = 11
def __init__(self, upc, writer=None, make_ean=False):
2020-10-11 19:48:57 -05:00
"""Initializes new UPC-A barcode.
:param str upc: The upc number as string.
:param writer: barcode.writer instance. The writer to render the
barcode (default: SVGWriter).
:param bool make_ean: Indicates if a leading zero should be added to
the barcode. This converts the UPC into a valid European Article
Number (EAN).
"""
2019-09-09 22:42:38 -05:00
self.ean = make_ean
2020-10-11 19:48:57 -05:00
upc = upc[: self.digits]
2019-09-09 22:42:38 -05:00
if not upc.isdigit():
2020-10-11 19:48:57 -05:00
raise IllegalCharacterError("UPC code can only contain numbers.")
2019-09-09 22:42:38 -05:00
if len(upc) != self.digits:
2020-10-11 19:48:57 -05:00
raise NumberOfDigitsError(
"UPC must have {} digits, not {}.".format(self.digits, len(upc))
)
2019-09-09 22:42:38 -05:00
self.upc = upc
2020-10-11 19:48:57 -05:00
self.upc = "{}{}".format(upc, self.calculate_checksum())
2019-09-09 22:42:38 -05:00
self.writer = writer or Barcode.default_writer()
2020-10-11 19:48:57 -05:00
def __str__(self):
2019-09-09 22:42:38 -05:00
if self.ean:
2020-10-11 19:48:57 -05:00
return "0" + self.upc
2019-09-09 22:42:38 -05:00
else:
return self.upc
def get_fullcode(self):
if self.ean:
2020-10-11 19:48:57 -05:00
return "0" + self.upc
2019-09-09 22:42:38 -05:00
else:
return self.upc
def calculate_checksum(self):
"""Calculates the checksum for UPCA/UPC codes
:return: The checksum for 'self.upc'
2020-10-11 19:48:57 -05:00
:rtype: int
2019-09-09 22:42:38 -05:00
"""
2020-10-11 19:48:57 -05:00
def sum_(x, y):
return int(x) + int(y)
upc = self.upc[0 : self.digits]
2019-09-09 22:42:38 -05:00
oddsum = reduce(sum_, upc[::2])
evensum = reduce(sum_, upc[1::2])
check = (evensum + oddsum * 3) % 10
if check == 0:
return 0
else:
return 10 - check
def build(self):
"""Builds the barcode pattern from 'self.upc'
:return: The pattern as string
2020-10-11 19:48:57 -05:00
:rtype: str
2019-09-09 22:42:38 -05:00
"""
code = _upc.EDGE[:]
2020-10-11 19:48:57 -05:00
for _i, number in enumerate(self.upc[0:6]):
code += _upc.CODES["L"][int(number)]
2019-09-09 22:42:38 -05:00
code += _upc.MIDDLE
for number in self.upc[6:]:
2020-10-11 19:48:57 -05:00
code += _upc.CODES["R"][int(number)]
2019-09-09 22:42:38 -05:00
code += _upc.EDGE
return [code]
def to_ascii(self):
"""Returns an ascii representation of the barcode.
2020-10-11 19:48:57 -05:00
:rtype: str
2019-09-09 22:42:38 -05:00
"""
code = self.build()
for i, line in enumerate(code):
2020-10-11 19:48:57 -05:00
code[i] = line.replace("1", "|").replace("0", "_")
return "\n".join(code)
2019-09-09 22:42:38 -05:00
def render(self, writer_options=None, text=None):
2020-10-11 19:48:57 -05:00
options = {"module_width": 0.33}
2019-09-09 22:42:38 -05:00
options.update(writer_options or {})
return Barcode.render(self, options, text)
2020-10-11 19:48:57 -05:00
2019-09-09 22:42:38 -05:00
UPCA = UniversalProductCodeA