def _ascii_digits(value: object) -> bool: # Compare against ASCII explicitly: str.isdigit() accepts Arabic-Indic and # superscript digits, which the other two languages would reject. return isinstance(value, str) and value != "" and all("0" <= ch <= "9" for ch in value) def gs1_check_digit(data: str) -> int: """The GS1 mod-10 check digit for `data`, the digits of a GS1 key without its check digit. One rule serves every key length because the weights are counted from the right: 3, 1, 3, 1 ... starting with the digit that will sit next to the check digit. Counting from the left instead only works for EAN-13 and the other even-length data strings. """ if not _ascii_digits(data): raise ValueError("GS1 data must be one or more ASCII digits, received %r" % (data,)) total = 0 weight = 3 for ch in reversed(data): total = (total + (ord(ch) - 48) * weight) % 10 weight = 1 if weight == 3 else 3 return (10 - total) % 10