# -*- coding: utf-8 -*-
"""UPC module.
:Provided barcodes: UPC-A
"""
from functools import reduce
from .base import Barcode
from .charsets import upc as _upc
from .errors import IllegalCharacterError
from .helpers import sum_chars
[docs]class UPCA(Barcode):
"""Class for UPC-A bar codes.
Args:
code (str): UPC-A bar code.
writer (:py:class:`.writer.BaseWriter`): instance of writer class to render the bar code.
"""
name = 'UPC-A'
digits = 12
def __init__(self, code, writer=None):
super(UniversalProductCodeA, self).__init__(code, writer)
@staticmethod
[docs] def calculate_checksum(code):
"""Calculates the UPC-A checksum.
Args:
code (str): UPC-A code.
Returns:
(int): UPC-A checksum.
"""
sum_odd = reduce(sum_chars, code[::2])
sum_even = reduce(sum_chars, code[1:-1:2])
check = (sum_even + sum_odd * 3) % 10
if check == 0:
return 0
else:
return 10 - check
@staticmethod
[docs] def validate(code):
"""Calculates a UPC-A code checksum.
Args:
code (str): UPC-A code.
Raises:
IllegalCharacterError in case the bar code contains illegal characters.
ValueError in case the bar code exceeds its maximum length or
if the checksum digit doesn't match.
"""
if not code.isdigit():
raise IllegalCharacterError('[0-9]{%d}' % UPCA.digits)
if len(code) != UPCA.digits:
raise ValueError('Bar code %s requires %d digits' % (code, UPCA.digits))
checksum = UPCA.calculate_checksum(code)
if checksum != int(code[-1]):
raise ValueError('Checksum character mismatch %s != %s' % (checksum, code[-1]))
[docs] def build(self):
"""Builds the bar code pattern.
Returns:
(str): the bar code pattern.
"""
code = _upc.EDGE[:]
for _, number in enumerate(self.code[0:6]):
code += _upc.CODES['L'][int(number)]
code += _upc.MIDDLE
for number in self.code[6:]:
code += _upc.CODES['R'][int(number)]
code += _upc.EDGE
return [code]
[docs] def to_ascii(self):
"""Returns an ASCII representation of the bar code.
Returns:
(str): ASCII representation of the bar code.
"""
code = self.build()
for i, line in enumerate(code):
code[i] = line.replace('1', '|').replace('0', '_')
return '\n'.join(code)
[docs] def render(self, writer_options=None):
options = dict(module_width=0.33)
options.update(writer_options or {})
return super(UPCA, self).render(options)
[docs] def get_fullcode(self):
return self._code
UniversalProductCodeA = UPCA