From 7ad7e49a09b384dd76b35922ee224d601ab3b9fd Mon Sep 17 00:00:00 2001 From: Rafal Praczyk Date: Sun, 9 Aug 2026 12:47:30 +0200 Subject: [PATCH 1/3] perf(stdnum.pl): optimize PESEL & NIP validation checksum algorithms --- stdnum/pl/nip.py | 4 +++- stdnum/pl/pesel.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stdnum/pl/nip.py b/stdnum/pl/nip.py index bfc7506e..622830bc 100644 --- a/stdnum/pl/nip.py +++ b/stdnum/pl/nip.py @@ -48,7 +48,9 @@ def compact(number: str) -> str: def checksum(number: str) -> int: """Calculate the checksum.""" weights = (6, 5, 7, 2, 3, 4, 5, 6, 7, -1) - return sum(w * int(n) for w, n in zip(weights, number)) % 11 + d = [ord(c) - 48 for c in number] + return sum(d[i] * weights[i] for i in range(len(d))) % 11 + def validate(number: str) -> str: diff --git a/stdnum/pl/pesel.py b/stdnum/pl/pesel.py index 38ff544e..a160b1a9 100644 --- a/stdnum/pl/pesel.py +++ b/stdnum/pl/pesel.py @@ -92,10 +92,12 @@ def calc_check_digit(number: str) -> str: """Calculate the check digit for organisations. The number passed should not have the check digit included.""" weights = (1, 3, 7, 9, 1, 3, 7, 9, 1, 3) - check = sum(w * int(n) for w, n in zip(weights, number)) + d = [ord(c) - 48 for c in number[:10]] + check = sum(d[i] * weights[i] for i in range(len(d))) return str((10 - check) % 10) + def validate(number: str) -> str: """Check if the number is a valid national identification number. This checks the length, formatting and check digit.""" From bcd59d1f8764f1daf03924808364d58e36fe61a3 Mon Sep 17 00:00:00 2001 From: Rafal Praczyk Date: Sun, 9 Aug 2026 12:51:08 +0200 Subject: [PATCH 2/3] style: fix flake8 E303 blank line spacing --- stdnum/pl/nip.py | 1 - stdnum/pl/pesel.py | 1 - 2 files changed, 2 deletions(-) diff --git a/stdnum/pl/nip.py b/stdnum/pl/nip.py index 622830bc..cda58baa 100644 --- a/stdnum/pl/nip.py +++ b/stdnum/pl/nip.py @@ -52,7 +52,6 @@ def checksum(number: str) -> int: return sum(d[i] * weights[i] for i in range(len(d))) % 11 - def validate(number: str) -> str: """Check if the number is a valid VAT number. This checks the length, formatting and check digit.""" diff --git a/stdnum/pl/pesel.py b/stdnum/pl/pesel.py index a160b1a9..51ef19c7 100644 --- a/stdnum/pl/pesel.py +++ b/stdnum/pl/pesel.py @@ -97,7 +97,6 @@ def calc_check_digit(number: str) -> str: return str((10 - check) % 10) - def validate(number: str) -> str: """Check if the number is a valid national identification number. This checks the length, formatting and check digit.""" From c9af059b0a4fb52ca81169fb44c2628ad01ac5e4 Mon Sep 17 00:00:00 2001 From: Rafal Praczyk Date: Fri, 14 Aug 2026 23:45:34 +0200 Subject: [PATCH 3/3] perf(pl): use zero-allocation in-place accumulator loop for checksums --- stdnum/pl/nip.py | 10 +++++++--- stdnum/pl/pesel.py | 11 +++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/stdnum/pl/nip.py b/stdnum/pl/nip.py index cda58baa..537356d8 100644 --- a/stdnum/pl/nip.py +++ b/stdnum/pl/nip.py @@ -45,11 +45,15 @@ def compact(number: str) -> str: return number +_weights = (6, 5, 7, 2, 3, 4, 5, 6, 7, -1) + + def checksum(number: str) -> int: """Calculate the checksum.""" - weights = (6, 5, 7, 2, 3, 4, 5, 6, 7, -1) - d = [ord(c) - 48 for c in number] - return sum(d[i] * weights[i] for i in range(len(d))) % 11 + total = 0 + for w, n in zip(_weights, number): + total += w * (ord(n) - 48) + return total % 11 def validate(number: str) -> str: diff --git a/stdnum/pl/pesel.py b/stdnum/pl/pesel.py index 51ef19c7..e7d1fb33 100644 --- a/stdnum/pl/pesel.py +++ b/stdnum/pl/pesel.py @@ -88,13 +88,16 @@ def get_gender(number: str) -> str: return 'M' +_weights = (1, 3, 7, 9, 1, 3, 7, 9, 1, 3) + + def calc_check_digit(number: str) -> str: """Calculate the check digit for organisations. The number passed should not have the check digit included.""" - weights = (1, 3, 7, 9, 1, 3, 7, 9, 1, 3) - d = [ord(c) - 48 for c in number[:10]] - check = sum(d[i] * weights[i] for i in range(len(d))) - return str((10 - check) % 10) + total = 0 + for w, n in zip(_weights, number): + total += w * (ord(n) - 48) + return str((10 - total) % 10) def validate(number: str) -> str: