From e41cfb5a8c456eca21d7d8737495480703b20998 Mon Sep 17 00:00:00 2001 From: Piotr Wawrzyniak Date: Sat, 6 Jul 2024 21:50:02 +0200 Subject: [PATCH] Optimization of code creation, avoiding to many charset switch. This results in shorter code which according to GS1 spec should not be longer than 165 mm (6.5") 1) For code128, starding encoding set to C 2) Added function that determines whether the char is FNC1 char - defined the same in all three encodings 3) _maybe_switch_charset recognizes that FNC1 char is defined in all three encodings, and avoids changing encodings 4) added testcases for new functionality. --- .gitignore | 1 + barcode/codex.py | 30 ++++++++++++++++++-------- tests/test_Gs1_128.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 tests/test_Gs1_128.py diff --git a/.gitignore b/.gitignore index 33f7bda..844a299 100755 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.kpf *.svg *.db +.idea/* barcode/__pycache* build/* dist/* diff --git a/barcode/codex.py b/barcode/codex.py index ef72187..213a9fb 100755 --- a/barcode/codex.py +++ b/barcode/codex.py @@ -139,7 +139,7 @@ class Code128(Barcode): def __init__(self, code, writer=None) -> None: self.code = code self.writer = writer or self.default_writer() - self._charset = "B" + self._charset = "C" self._buffer = "" check_code(self.code, self.name, code128.ALL) @@ -163,9 +163,15 @@ def _new_charset(self, which): self._charset = which return [code] + # to be redefined in subclass if required + def _is_char_FNC1_CHAR(self, char): + # FNC1 char is defined in GS1-128 specification and it is defined just the same for all encodings + # therefore this sing should be treated in a special way. + return False + def _maybe_switch_charset(self, pos): char = self.code[pos] - next_ = self.code[pos : pos + 10] + next_ = self.code[pos: pos + 10] def look_next(): digits = 0 @@ -178,13 +184,16 @@ def look_next(): codes = [] if self._charset == "C" and not char.isdigit(): - if char in code128.B: - codes = self._new_charset("B") - elif char in code128.A: - codes = self._new_charset("A") - if len(self._buffer) == 1: - codes.append(self._convert(self._buffer[0])) - self._buffer = "" + if self._is_char_FNC1_CHAR(char) and not self._buffer: + return codes + else: + if char in code128.B: + codes = self._new_charset("B") + elif char in code128.A: + codes = self._new_charset("A") + if len(self._buffer) == 1: + codes.append(self._convert(self._buffer[0])) + self._buffer = "" elif self._charset == "B": if look_next(): codes = self._new_charset("C") @@ -275,6 +284,9 @@ def __init__(self, code, writer=None) -> None: def get_fullcode(self): return super().get_fullcode()[1:] + def _is_char_FNC1_CHAR(self, char): + return char == self.FNC1_CHAR + # For pre 0.8 compatibility PZN = PZN7 diff --git a/tests/test_Gs1_128.py b/tests/test_Gs1_128.py new file mode 100644 index 0000000..25e0ac8 --- /dev/null +++ b/tests/test_Gs1_128.py @@ -0,0 +1,50 @@ +import pytest +import sys +import os.path +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +from barcode.codex import Gs1_128 + +FNC1_CHAR = "\xf1" +FNC1 = 102 +START_B = 104 +START_C = 105 +FROM_AC_TO_B = 100 +FROM_AB_TO_C = 99 +FROM_BC_TO_A = 101 +CODE_BUILD_TEST = ( + # '(01)01234567891011(11)200622(17)240622(21)88888888' + ('010123456789101111200622172406222188888888', [START_C, FNC1, 1, 1, 23, 45, 67, 89, 10, 11, + 11, 20, 6, 22, + 17, 24, 6, 22, + 21, 88, 88, 88, 88],), + # '(01)01234567891011(11)200622(17)240622(21)888888888' + ('0101234567891011112006221724062221888888888', [START_C, FNC1, 1, 1, 23, 45, 67, 89, 10, 11, + 11, 20, 6, 22, + 17, 24, 6, 22, + 21, 88, 88, 88, 88, 100, 24],), + # '(01)01234567891011(11)200622(10)12345(21)1234' + ('0101234567891011112006221012345' + FNC1_CHAR + '211234', [START_C, FNC1, 1, 1, 23, 45, 67, 89, 10, 11, + 11, 20, 6, 22, + 10, 12, 34, FROM_AC_TO_B, 21, FNC1, + FROM_AB_TO_C, 21, 12, 34],), + # '(01)01234567891011(11)200622(10)1234(21)1234' + ('010123456789101111200622101234' + FNC1_CHAR + '211234', [START_C, FNC1, 1, 1, 23, 45, 67, 89, 10, 11, + 11, 20, 6, 22, + 10, 12, 34, FNC1, + 21, 12, 34],), + # '(01)01234567891011(11)200622(10)240622(21)888888888' + ('01012345678910111120062210240622' + FNC1_CHAR + '21888888888', [START_C, FNC1, 1, 1, 23, 45, 67, 89, 10, 11, + 11, 20, 6, 22, + 10, 24, 6, 22, FNC1, + 21, 88, 88, 88, 88, 100, 24],), + # '(01)08720299927469(11)240621(17)250621(10)20240621/0001(21)xyz' + ('010872029992746911240621172506211020240621/0001' + FNC1_CHAR + '21xyz', [105, 102, 1, 8, 72, 2, 99, 92, 74, 69, + 11, 24, 6, 21, + 17, 25, 6, 21, + 10, 20, 24, 6, 21, 100, 15, 99, 0, 1, + 102, 21, 100, 88, 89, 90]), +) +@pytest.mark.parametrize('target, answer', CODE_BUILD_TEST) +def test_code_build(target, answer): + gs1_128 = Gs1_128(target) + assert gs1_128._build() == answer