From 3a85763d086784f191fd587df9934fe2c48974fd Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 20:59:58 +0100 Subject: [PATCH 1/8] Update pps.py Updates regex, conditional and comment to reflect latest PPS number rules --- stdnum/ie/pps.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stdnum/ie/pps.py b/stdnum/ie/pps.py index e64514cc..98296fc9 100644 --- a/stdnum/ie/pps.py +++ b/stdnum/ie/pps.py @@ -23,10 +23,9 @@ The Personal Public Service number consists of 7 digits, and one or two letters. The first letter is a check character. When present (which should be the case for new numbers as of 2013), -the second letter can be 'A' (for individuals) or 'H' (for -non-individuals, such as limited companies, trusts, partnerships -and unincorporated bodies). Pre-2013 values may have 'W', 'T', -or 'X' as the second letter ; it is ignored by the check. +the second letter can be any letter between A and V. +Pre-2013 values may have 'W' as the second letter which was for +married women; it is ignored by the check. >>> validate('6433435F') # pre-2013 '6433435F' @@ -55,7 +54,7 @@ from stdnum.util import clean -pps_re = re.compile(r'^\d{7}[A-W][AHWTX]?$') +pps_re = re.compile(r'^\d{7}[A-W][A-W]?$') """Regular expression used to check syntax of PPS numbers.""" @@ -71,12 +70,13 @@ def validate(number): number = compact(number) if not pps_re.match(number): raise InvalidFormat() - if len(number) == 9 and number[8] in 'AH': - # new 2013 format + + # If new 2013 format (excludes old format 2nd character W for married woman) + if len(number) == 9 and number[8] in 'ABCDEFGHIJKLMNOPQRSTUV': if number[7] != vat.calc_check_digit(number[:7] + number[8:]): raise InvalidChecksum() else: - # old format, last letter ignored + # old format, last letter ignored if number[7] != vat.calc_check_digit(number[:7]): raise InvalidChecksum() return number From 0bde47909fa6fe25141884f8f96c31e4688d127c Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 21:02:41 +0100 Subject: [PATCH 2/8] Create test_ie_pps.doctest Adds tests --- tests/tests/test_ie_pps.doctest | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/tests/test_ie_pps.doctest diff --git a/tests/tests/test_ie_pps.doctest b/tests/tests/test_ie_pps.doctest new file mode 100644 index 00000000..dd9ed307 --- /dev/null +++ b/tests/tests/test_ie_pps.doctest @@ -0,0 +1,57 @@ +test_ie_pps.doctest - more detailed doctests for stdnum.ie.pps module + +Copyright (C) 2016 Arthur de Jong + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA + + +This file contains more detailed doctests for the stdnum.ie.vat module. It +tries to cover more corner cases and detailed functionality that is not +really useful as module documentation. + +>>> from stdnum.ie import pps + + +Extra tests for length checking and corner cases: + +>>> pps.validate('111222333') # check number should contain letters +Traceback (most recent call last): + ... +InvalidFormat: ... + +>>> pps.validate('1234567ABC') # too long +Traceback (most recent call last): + ... +InvalidFormat: ... + +>>> pps.validate('1234567XX') # invalid letters +Traceback (most recent call last): + ... +InvalidFormat: ... + + +The validate() function should check with new format if last letter is A, B or H. + +>>> pps.validate('1234567FA') +'1234567FA' +>>> pps.validate('1234567WH') +'1234567WH' +>>> pps.validate('1234567OB') +'1234567OB' + +The validate() function should check with old format if last letter is W or T. +>>> pps.validate('1234567TW') +'1234567TW' From 9d33ee86213ea246e5316cf387722e9c39d0f03d Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 21:05:20 +0100 Subject: [PATCH 3/8] Create test_ie_pps.doctest fix tests --- tests/test_ie_pps.doctest | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/test_ie_pps.doctest diff --git a/tests/test_ie_pps.doctest b/tests/test_ie_pps.doctest new file mode 100644 index 00000000..dd9ed307 --- /dev/null +++ b/tests/test_ie_pps.doctest @@ -0,0 +1,57 @@ +test_ie_pps.doctest - more detailed doctests for stdnum.ie.pps module + +Copyright (C) 2016 Arthur de Jong + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA + + +This file contains more detailed doctests for the stdnum.ie.vat module. It +tries to cover more corner cases and detailed functionality that is not +really useful as module documentation. + +>>> from stdnum.ie import pps + + +Extra tests for length checking and corner cases: + +>>> pps.validate('111222333') # check number should contain letters +Traceback (most recent call last): + ... +InvalidFormat: ... + +>>> pps.validate('1234567ABC') # too long +Traceback (most recent call last): + ... +InvalidFormat: ... + +>>> pps.validate('1234567XX') # invalid letters +Traceback (most recent call last): + ... +InvalidFormat: ... + + +The validate() function should check with new format if last letter is A, B or H. + +>>> pps.validate('1234567FA') +'1234567FA' +>>> pps.validate('1234567WH') +'1234567WH' +>>> pps.validate('1234567OB') +'1234567OB' + +The validate() function should check with old format if last letter is W or T. +>>> pps.validate('1234567TW') +'1234567TW' From 25c967247e0540eea7772d434a16092c5ba86934 Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 21:05:37 +0100 Subject: [PATCH 4/8] Delete tests/tests directory delete error --- tests/tests/test_ie_pps.doctest | 57 --------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 tests/tests/test_ie_pps.doctest diff --git a/tests/tests/test_ie_pps.doctest b/tests/tests/test_ie_pps.doctest deleted file mode 100644 index dd9ed307..00000000 --- a/tests/tests/test_ie_pps.doctest +++ /dev/null @@ -1,57 +0,0 @@ -test_ie_pps.doctest - more detailed doctests for stdnum.ie.pps module - -Copyright (C) 2016 Arthur de Jong - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA - - -This file contains more detailed doctests for the stdnum.ie.vat module. It -tries to cover more corner cases and detailed functionality that is not -really useful as module documentation. - ->>> from stdnum.ie import pps - - -Extra tests for length checking and corner cases: - ->>> pps.validate('111222333') # check number should contain letters -Traceback (most recent call last): - ... -InvalidFormat: ... - ->>> pps.validate('1234567ABC') # too long -Traceback (most recent call last): - ... -InvalidFormat: ... - ->>> pps.validate('1234567XX') # invalid letters -Traceback (most recent call last): - ... -InvalidFormat: ... - - -The validate() function should check with new format if last letter is A, B or H. - ->>> pps.validate('1234567FA') -'1234567FA' ->>> pps.validate('1234567WH') -'1234567WH' ->>> pps.validate('1234567OB') -'1234567OB' - -The validate() function should check with old format if last letter is W or T. ->>> pps.validate('1234567TW') -'1234567TW' From afb1e79e8b06be40c1ca95010c7620582d5b9a6c Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 21:10:38 +0100 Subject: [PATCH 5/8] Update test_ie_pps.doctest Updated tests --- tests/test_ie_pps.doctest | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/test_ie_pps.doctest b/tests/test_ie_pps.doctest index dd9ed307..1ac73716 100644 --- a/tests/test_ie_pps.doctest +++ b/tests/test_ie_pps.doctest @@ -43,15 +43,36 @@ Traceback (most recent call last): InvalidFormat: ... -The validate() function should check with new format if last letter is A, B or H. +The validate() function should check with old & new formats +>>> validate('6433435F') # pre-2013 +'6433435F' +>>> validate('6433435FW') # pre-2013 format for married women +'6433435FW' +>>> validate('6433435E') # incorrect check digit +Traceback (most recent call last): + ... +InvalidChecksum: ... + +>>> validate('6433435OA') # 2013 format (personal) +'6433435OA' >>> pps.validate('1234567FA') '1234567FA' +>>> validate('6433435IH') # 2013 format (non-personal) +'6433435IH' >>> pps.validate('1234567WH') '1234567WH' ->>> pps.validate('1234567OB') +>>> pps.validate('1234567OB') # 2013 format 2024 B-range '1234567OB' +>>> validate('6433435VH') # 2013 format (incorrect check) +Traceback (most recent call last): + ... +InvalidChecksum: ... + + + + The validate() function should check with old format if last letter is W or T. >>> pps.validate('1234567TW') '1234567TW' From 462a2440b40c3c5f5e95243d2c6793c95e5cb49b Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 22:25:44 +0100 Subject: [PATCH 6/8] Update pps.py Restrict it back to keep things YAGNI --- stdnum/ie/pps.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stdnum/ie/pps.py b/stdnum/ie/pps.py index 98296fc9..d90d9ba2 100644 --- a/stdnum/ie/pps.py +++ b/stdnum/ie/pps.py @@ -23,7 +23,9 @@ The Personal Public Service number consists of 7 digits, and one or two letters. The first letter is a check character. When present (which should be the case for new numbers as of 2013), -the second letter can be any letter between A and V. +the second letter can be 'A' (for individuals) or 'H' (for +non-individuals, such as limited companies, trusts, partnerships +and unincorporated bodies) Pre-2013 values may have 'W' as the second letter which was for married women; it is ignored by the check. @@ -54,7 +56,7 @@ from stdnum.util import clean -pps_re = re.compile(r'^\d{7}[A-W][A-W]?$') +pps_re = re.compile(r'^\d{7}[A-W][ABHW]?$') """Regular expression used to check syntax of PPS numbers.""" @@ -72,7 +74,7 @@ def validate(number): raise InvalidFormat() # If new 2013 format (excludes old format 2nd character W for married woman) - if len(number) == 9 and number[8] in 'ABCDEFGHIJKLMNOPQRSTUV': + if len(number) == 9 and number[8] in 'ABH': if number[7] != vat.calc_check_digit(number[:7] + number[8:]): raise InvalidChecksum() else: From d332977cc0fa4d3da115bcdd2586351ee6be0df7 Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 22:36:52 +0100 Subject: [PATCH 7/8] Update pps.py Added comment about B-range numbers --- stdnum/ie/pps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/stdnum/ie/pps.py b/stdnum/ie/pps.py index d90d9ba2..565fc845 100644 --- a/stdnum/ie/pps.py +++ b/stdnum/ie/pps.py @@ -28,6 +28,7 @@ and unincorporated bodies) Pre-2013 values may have 'W' as the second letter which was for married women; it is ignored by the check. +As of 2024, B was accepted as a second letter on all new PPS numbers. >>> validate('6433435F') # pre-2013 '6433435F' From 63a4d9ab6b8c979217a8a7e3497e22dd6ef1d625 Mon Sep 17 00:00:00 2001 From: Olly Middleton Date: Wed, 19 Jun 2024 22:38:20 +0100 Subject: [PATCH 8/8] Update test_ie_pps.doctest tidy up --- tests/test_ie_pps.doctest | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/test_ie_pps.doctest b/tests/test_ie_pps.doctest index 1ac73716..e63f1c34 100644 --- a/tests/test_ie_pps.doctest +++ b/tests/test_ie_pps.doctest @@ -64,15 +64,11 @@ InvalidChecksum: ... '1234567WH' >>> pps.validate('1234567OB') # 2013 format 2024 B-range '1234567OB' - >>> validate('6433435VH') # 2013 format (incorrect check) Traceback (most recent call last): ... InvalidChecksum: ... - - - -The validate() function should check with old format if last letter is W or T. +The validate() function should check with old format if last letter is W. >>> pps.validate('1234567TW') '1234567TW'