def test_parse_nonnumeric_value() -> None: with pytest.raises(ParseError) as exc_info: Gtin.parse("0123456789abc") assert ( str(exc_info.value) == "Failed to parse '0123456789abc' as GTIN: Expected a numerical value." )
def test_parse_gtin_13_with_invalid_check_digit() -> None: with pytest.raises(ParseError) as exc_info: Gtin.parse("5901234123458") assert ( str(exc_info.value) == "Invalid GTIN check digit for '5901234123458': Expected 7, got 8." )
def test_parse_value_with_invalid_length() -> None: with pytest.raises(ParseError) as exc_info: Gtin.parse("123") assert ( str(exc_info.value) == "Failed to parse '123' as GTIN: Expected 8, 12, 13, or 14 digits, got 3." )
def test_fails_when_rcn_region_is_unknown_string() -> None: with pytest.raises(ValueError) as exc_info: Gtin.parse( "2311111112345", rcn_region="foo", # type: ignore ) assert str(exc_info.value) == "'foo' is not a valid RcnRegion"
def test_region_great_britain_fails_with_invalid_price_check_digit() -> None: # The digit 8 in the value below is the price check digit. The correct value is 9. with pytest.raises(ParseError) as exc_info: Gtin.parse("2011122812349", rcn_region=RcnRegion.GREAT_BRITAIN) assert str(exc_info.value) == ( "Invalid price check digit for price data '1234' in RCN '2011122812349': " "Expected 9, got 8.")
def _set_gtin(self: GS1ElementString, *, rcn_region: Optional[RcnRegion] = None) -> None: if self.ai.ai not in ("01", "02"): return self.gtin = Gtin.parse(self.value, rcn_region=rcn_region)
def test_as_gtin_12_fails_for_too_long_values(value: str) -> None: gtin = Gtin.parse(value) with pytest.raises(EncodeError) as exc_info: gtin.as_gtin_12() assert str(exc_info.value) == f"Failed encoding {value!r} as GTIN-12."
def test_gtin_14_with_rcn_prefix_is_not_an_rcn() -> None: # The value below is a GTIN-14 composed of packaging level 1 and a valid RCN-13. gtin = Gtin.parse("12991111111110", rcn_region=None) assert isinstance(gtin, Gtin) assert not isinstance(gtin, Rcn) assert gtin.format == GtinFormat.GTIN_14
def test_parse_gtin_8(value: str) -> None: assert Gtin.parse(value) == Gtin( value=value, format=GtinFormat.GTIN_8, prefix=GS1Prefix(value="00009", usage="GS1 US"), payload="9638507", check_digit=4, )
def test_parse_gtin_13(value: str) -> None: assert Gtin.parse(value) == Gtin( value=value, format=GtinFormat.GTIN_13, prefix=GS1Prefix(value="590", usage="GS1 Poland"), payload="590123412345", check_digit=7, )
def test_parse_gtin_with_unknown_gs1_prefix() -> None: assert Gtin.parse("6712670000276") == Gtin( value="6712670000276", format=GtinFormat.GTIN_13, prefix=None, payload="671267000027", check_digit=6, )
def test_parse_gtin_12_without_leading_zero(value: str) -> None: assert Gtin.parse(value) == Gtin( value=value, format=GtinFormat.GTIN_12, prefix=GS1Prefix(value="061", usage="GS1 US"), payload="61414100003", check_digit=6, )
def test_parse_gtin_12_with_3_leading_zero(value: str) -> None: assert Gtin.parse(value) == Gtin( value=value, format=GtinFormat.GTIN_12, prefix=GS1Prefix(value="00009", usage="GS1 US"), payload="00090291451", check_digit=1, )
def test_rcn_region_can_be_specified_as_string(value: str, rcn_region: RcnRegion) -> None: rcn = Gtin.parse( "0211111111114", rcn_region=value, # type: ignore ) assert isinstance(rcn, Rcn) assert rcn.region == rcn_region
def test_parse_gtin_14() -> None: assert Gtin.parse("98765432109213") == Gtin( value="98765432109213", format=GtinFormat.GTIN_14, prefix=GS1Prefix(value="876", usage="GS1 Netherlands"), payload="9876543210921", check_digit=3, packaging_level=9, )
def test_without_variable_measure_keeps_gtin_unchanged(value: str) -> None: original_gtin = Gtin.parse(value) assert isinstance(original_gtin, Gtin) assert not isinstance(original_gtin, Rcn) stripped_gtin = original_gtin.without_variable_measure() assert isinstance(stripped_gtin, Gtin) assert not isinstance(stripped_gtin, Rcn) assert stripped_gtin.value == original_gtin.value
def test_rcn_without_specified_region() -> None: rcn = Gtin.parse("2991111111113", rcn_region=None) assert isinstance(rcn, Rcn) assert rcn.format == GtinFormat.GTIN_13 assert rcn.usage == RcnUsage.GEOGRAPHICAL assert rcn.region is None assert rcn.weight is None assert rcn.price is None assert rcn.money is None
def test_without_variable_measure(value: str, rcn_region: RcnRegion, expected: str) -> None: original_rcn = Gtin.parse(value, rcn_region=rcn_region) assert isinstance(original_rcn, Rcn) stripped_rcn = original_rcn.without_variable_measure() assert isinstance(stripped_rcn, Rcn) assert stripped_rcn.value == expected assert stripped_rcn.region == original_rcn.region
def test_without_variable_measure_fails_if_rules_are_unknown() -> None: rcn = Gtin.parse("2302148210869", rcn_region=None) assert isinstance(rcn, Rcn) with pytest.raises(EncodeError) as exc_info: rcn.without_variable_measure() assert str(exc_info.value) == ( "Cannot zero out the variable measure part of '2302148210869' " "as the RCN rules for the geographical region None are unknown.")
def test_gtin_parse_may_return_rcn_instance(value: str, format: GtinFormat, usage: RcnUsage) -> None: rcn = Gtin.parse(value, rcn_region=RcnRegion.SWEDEN) assert isinstance(rcn, Rcn) assert rcn.format == format assert rcn.usage == usage if usage == RcnUsage.GEOGRAPHICAL: assert rcn.region == RcnRegion.SWEDEN else: assert rcn.region is None
def test_without_variable_measure_keeps_company_rcn_unchanged( rcn_region: RcnRegion, value: str ) -> None: original_rcn = Gtin.parse(value, rcn_region=rcn_region) assert isinstance(original_rcn, Rcn) stripped_rcn = original_rcn.without_variable_measure() assert isinstance(stripped_rcn, Rcn) assert stripped_rcn.value == original_rcn.value assert stripped_rcn.region == original_rcn.region
def without_variable_measure(self: Rcn) -> Gtin: """Create a new RCN where the variable measure is zeroed out. This provides us with a number which still includes the item reference, but does not vary with weight/price, and can thus be used to lookup the relevant trade item in a database or similar. This has no effect on RCNs intended for use within a company, as the semantics of those numbers vary from company to company. Returns: A new RCN instance with zeros in the variable measure places. Raises: EncodeError: If the rules for variable measures in the region are unknown. """ if self.usage == RcnUsage.COMPANY: return self if self.region in ( RcnRegion.BALTICS, RcnRegion.NORWAY, RcnRegion.SWEDEN, ): measure = "0000" payload = f"{self.value[:-5]}{measure}" check_digit = checksums.numeric_check_digit(payload) value = f"{payload}{check_digit}" return Gtin.parse(value, rcn_region=self.region) elif self.region in (RcnRegion.GREAT_BRITAIN, ): measure = "0000" price_check_digit = checksums.price_check_digit(measure) payload = f"{self.value[:-6]}{price_check_digit}{measure}" check_digit = checksums.numeric_check_digit(payload) value = f"{payload}{check_digit}" return Gtin.parse(value, rcn_region=self.region) else: raise EncodeError( f"Cannot zero out the variable measure part of {self.value!r} as the " f"RCN rules for the geographical region {self.region!r} are unknown." )
def test_without_variable_measure_keeps_nonvariable_rcn_unchanged( rcn_region: RcnRegion, nonvariable_prefixes: List[str] ) -> None: for prefix in nonvariable_prefixes: payload = f"{prefix}1111111111" value = f"{payload}{numeric_check_digit(payload)}" original_rcn = Gtin.parse(value, rcn_region=rcn_region) assert isinstance(original_rcn, Rcn) stripped_rcn = original_rcn.without_variable_measure() assert isinstance(stripped_rcn, Rcn) assert stripped_rcn.value == original_rcn.value assert stripped_rcn.region == original_rcn.region
def test_region_norway( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: TODO: Find specification. rcn = Gtin.parse(value, rcn_region=RcnRegion.NORWAY) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.NORWAY assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_great_britain( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: # https://www.gs1uk.org/how-to-barcode-variable-measure-items rcn = Gtin.parse(value, rcn_region=RcnRegion.GREAT_BRITAIN) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.GREAT_BRITAIN assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_finland( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: # https://gs1.fi/en/instructions/gs1-company-prefix/how-identify-product-gtin rcn = Gtin.parse(value, rcn_region=RcnRegion.FINLAND) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.FINLAND assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_sweden( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: # https://www.gs1.se/en/our-standards/Identify/variable-weight-number1/ rcn = Gtin.parse(value, rcn_region=RcnRegion.SWEDEN) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.SWEDEN assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_denmark( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: # https://www.gs1.dk/om-gs1/overblik-over-gs1-standarder/gtin-13-pris # https://www.gs1.dk/om-gs1/overblik-over-gs1-standarder/gtin-13-vaegt rcn = Gtin.parse(value, rcn_region=RcnRegion.DENMARK) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.DENMARK assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_baltics( value: str, weight: Optional[Decimal], price: Optional[Decimal], money: Optional[Money], ) -> None: # The three Baltic countries share the same rules and allocation pool. # # References: # https://gs1lv.org/img/upload/ENG.Variable%20measure_in_Latvia.pdf rcn = Gtin.parse(value, rcn_region=RcnRegion.BALTICS) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.BALTICS assert rcn.weight == weight assert rcn.price == price assert rcn.money == money
def test_region_germany( value: str, weight: Optional[Decimal], count: Optional[int], price: Optional[Decimal], money: Optional[Money], ) -> None: # References: # https://www.gs1-germany.de/fileadmin/gs1/fachpublikationen/globale-artikelnummer-gtin-in-der-anwendung.pdf # https://san.gs1-germany.de/SAN-4-Konzept rcn = Gtin.parse(value, rcn_region=RcnRegion.GERMANY) assert isinstance(rcn, Rcn) assert rcn.region == RcnRegion.GERMANY assert rcn.weight == weight assert rcn.count == count assert rcn.price == price assert rcn.money == money