ean-tools 0.1.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
ean_tools/__init__.py ADDED
File without changes
@@ -0,0 +1,57 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import Optional
4
+
5
+ from ean_tools.barcode_prefixes import get_raw_ean8_prefix_info, get_raw_ean13_prefix_info, get_raw_isbn_prefix_info
6
+
7
+
8
+ class BarcodeType(Enum):
9
+ COUPON_ID = 'COUPON_ID'
10
+ DEMO = 'DEMO'
11
+ GENERAL_MANAGER_NUMBER = 'GENERAL_MANAGER_NUMBER'
12
+ REFUND_RECEIPT = 'REFUND_RECEIPT'
13
+ REGULAR = 'REGULAR'
14
+ RESERVED_FOR_FUTURE = 'RESERVED_FOR_FUTURE'
15
+ RESTRICTED_CIRCULATION = 'RESTRICTED_CIRCULATION'
16
+ UNUSED = 'UNUSED'
17
+
18
+
19
+ @dataclass
20
+ class BarcodeInfo:
21
+ barcode_type: BarcodeType
22
+ description: str
23
+ country: Optional[str]
24
+
25
+
26
+ def get_barcode_info(normalized_barcode: str) -> BarcodeInfo:
27
+ """Retrieves information about a given barcode.
28
+
29
+ Args:
30
+ normalized_barcode (str): The normalized barcode string.
31
+
32
+ Returns:
33
+ BarcodeInfo: An object containing barcode information.
34
+ """
35
+ if len(normalized_barcode) == 13 and (normalized_barcode.startswith('978') or normalized_barcode.startswith('979')):
36
+ barcode_info = get_raw_isbn_prefix_info(normalized_barcode)
37
+ if not barcode_info:
38
+ return BarcodeInfo(BarcodeType.REGULAR, 'ISBN', None)
39
+
40
+ return BarcodeInfo(BarcodeType.REGULAR, barcode_info['description'], barcode_info.get('country'))
41
+
42
+ if len(normalized_barcode) == 8:
43
+ barcode_info = get_raw_ean8_prefix_info(normalized_barcode)
44
+ elif len(normalized_barcode) == 14:
45
+ barcode_info = get_raw_ean13_prefix_info(normalized_barcode[1:])
46
+ else:
47
+ barcode_info = get_raw_ean13_prefix_info(normalized_barcode)
48
+
49
+ if not barcode_info:
50
+ return BarcodeInfo(BarcodeType.RESERVED_FOR_FUTURE, 'Reserved for future use', None)
51
+
52
+ if 'type' in barcode_info:
53
+ barcode_type = BarcodeType[barcode_info['type']]
54
+ else:
55
+ barcode_type = BarcodeType.REGULAR
56
+
57
+ return BarcodeInfo(barcode_type, barcode_info['description'], barcode_info.get('country'))
@@ -0,0 +1,61 @@
1
+ import os
2
+ from typing import Optional
3
+
4
+ import yaml
5
+
6
+ from affix_tree import AffixTree
7
+
8
+ _CURRENT_DIR = os.path.dirname(__file__)
9
+
10
+
11
+ def init_gs1_prefixes() -> AffixTree[dict]:
12
+ with open(os.path.join(_CURRENT_DIR, 'data/gs1-prefixes.yaml')) as gs1_prefixes_file:
13
+ _gs1_prefixes = yaml.load(gs1_prefixes_file.read(), yaml.CBaseLoader)
14
+
15
+ gs1_prefixes = AffixTree()
16
+ for prefix_group in _gs1_prefixes:
17
+ for p in prefix_group.pop('prefixes'):
18
+ gs1_prefixes.add(p, prefix_group)
19
+
20
+ return gs1_prefixes
21
+
22
+
23
+ def init_gs1_8_prefixes() -> AffixTree[dict]:
24
+ with open(os.path.join(_CURRENT_DIR, 'data/gs1-8-prefixes.yaml')) as gs1_8_prefixes_file:
25
+ _gs1_8_prefixes = yaml.load(gs1_8_prefixes_file.read(), yaml.CBaseLoader)
26
+
27
+ gs1_8_prefixes = AffixTree()
28
+ for prefix_group in _gs1_8_prefixes:
29
+ for p in prefix_group.pop('prefixes'):
30
+ gs1_8_prefixes.add(p, prefix_group)
31
+
32
+ return gs1_8_prefixes
33
+
34
+
35
+ def init_isbn_prefixes() -> AffixTree[dict]:
36
+ with open(os.path.join(_CURRENT_DIR, 'data/isbn-prefixes.yaml')) as isbn_prefixes_file:
37
+ _isbn_prefixes = yaml.load(isbn_prefixes_file.read(), yaml.CBaseLoader)
38
+
39
+ isbn_prefixes = AffixTree()
40
+ for prefix_group in _isbn_prefixes:
41
+ for p in prefix_group.pop('prefixes'):
42
+ isbn_prefixes.add(p, prefix_group)
43
+
44
+ return isbn_prefixes
45
+
46
+
47
+ _GS1_8_PREFIXES: AffixTree[dict] = init_gs1_8_prefixes()
48
+ _GS1_PREFIXES: AffixTree[dict] = init_gs1_prefixes()
49
+ _ISBN_PREFIXES: AffixTree[dict] = init_isbn_prefixes()
50
+
51
+
52
+ def get_raw_ean8_prefix_info(barcode: str) -> Optional[dict]:
53
+ return _GS1_8_PREFIXES.find(barcode)
54
+
55
+
56
+ def get_raw_ean13_prefix_info(barcode: str) -> Optional[dict]:
57
+ return _GS1_PREFIXES.find(barcode)
58
+
59
+
60
+ def get_raw_isbn_prefix_info(barcode: str) -> Optional[dict]:
61
+ return _ISBN_PREFIXES.find(barcode)
@@ -0,0 +1,44 @@
1
+ def has_correct_check_digit(normalized_barcode: str) -> bool:
2
+ """Checks if the given barcode has the correct check digit.
3
+
4
+ Args:
5
+ normalized_barcode (str): Normalized barcode string.
6
+
7
+ Returns:
8
+ bool: True if the check digit is correct, False otherwise.
9
+ """
10
+ return get_correct_check_digit(normalized_barcode) == normalized_barcode[-1]
11
+
12
+
13
+ def get_correct_check_digit(normalized_barcode: str) -> str:
14
+ """Calculates the correct check digit for a barcode.
15
+
16
+ Args:
17
+ normalized_barcode (str): Normalized barcode string.
18
+
19
+ Returns:
20
+ str: The correct check digit.
21
+ """
22
+ check_digit = 0
23
+ barcode_length = len(normalized_barcode)
24
+
25
+ i = barcode_length - 2
26
+ while i >= 0:
27
+ weight = 3 if (barcode_length - i) % 2 == 0 else 1
28
+ check_digit += int(normalized_barcode[i]) * weight
29
+ i -= 1
30
+
31
+ return str((10 - (check_digit % 10)) % 10)
32
+
33
+
34
+ def isbn10_has_correct_check_digit(isbn10: str) -> bool:
35
+ """Checks if an ISBN-10 barcode has the correct check digit.
36
+
37
+ Args:
38
+ isbn10 (str): The ISBN-10 barcode string.
39
+
40
+ Returns:
41
+ bool: True if the check digit is correct, False otherwise.
42
+ """
43
+ s = sum((10 - i) * int(c) for i, c in enumerate(isbn10))
44
+ return s % 11 == 0
@@ -0,0 +1,28 @@
1
+ - description: Used to issue Restricted Circulation Numbers within a company
2
+ type: RESTRICTED_CIRCULATION
3
+ prefixes:
4
+ - '0'
5
+ - '2'
6
+ - description: Used to issue GTIN-8s
7
+ prefixes:
8
+ - '1'
9
+ - '3'
10
+ - '4'
11
+ - '5'
12
+ - '6'
13
+ - '7'
14
+ - '8'
15
+ - '90'
16
+ - '91'
17
+ - '92'
18
+ - '93'
19
+ - '94'
20
+ - '95'
21
+ - '96'
22
+ - '970'
23
+ - '971'
24
+ - '972'
25
+ - '973'
26
+ - '974'
27
+ - '975'
28
+ - '976'