PyPaf 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. pypaf-0.1.0/LICENSE.txt +21 -0
  2. pypaf-0.1.0/PKG-INFO +72 -0
  3. pypaf-0.1.0/README.md +57 -0
  4. pypaf-0.1.0/pyproject.toml +29 -0
  5. pypaf-0.1.0/setup.cfg +4 -0
  6. pypaf-0.1.0/src/PyPaf.egg-info/PKG-INFO +72 -0
  7. pypaf-0.1.0/src/PyPaf.egg-info/SOURCES.txt +35 -0
  8. pypaf-0.1.0/src/PyPaf.egg-info/dependency_links.txt +1 -0
  9. pypaf-0.1.0/src/PyPaf.egg-info/top_level.txt +1 -0
  10. pypaf-0.1.0/src/paf/__init__.py +6 -0
  11. pypaf-0.1.0/src/paf/attribute.py +66 -0
  12. pypaf-0.1.0/src/paf/lineable.py +27 -0
  13. pypaf-0.1.0/src/paf/paf.py +33 -0
  14. pypaf-0.1.0/src/paf/premises/__init__.py +0 -0
  15. pypaf-0.1.0/src/paf/premises/common.py +38 -0
  16. pypaf-0.1.0/src/paf/premises/rule000.py +16 -0
  17. pypaf-0.1.0/src/paf/premises/rule001.py +16 -0
  18. pypaf-0.1.0/src/paf/premises/rule010.py +46 -0
  19. pypaf-0.1.0/src/paf/premises/rule011.py +16 -0
  20. pypaf-0.1.0/src/paf/premises/rule101.py +30 -0
  21. pypaf-0.1.0/src/paf/premises/rule110.py +20 -0
  22. pypaf-0.1.0/src/paf/premises/rule111.py +18 -0
  23. pypaf-0.1.0/src/paf/premises_extender.py +25 -0
  24. pypaf-0.1.0/src/paf/thoroughfare_locality.py +51 -0
  25. pypaf-0.1.0/src/paf/version.py +3 -0
  26. pypaf-0.1.0/tests/test_exception_i.py +31 -0
  27. pypaf-0.1.0/tests/test_exception_ii.py +29 -0
  28. pypaf-0.1.0/tests/test_exception_iii.py +30 -0
  29. pypaf-0.1.0/tests/test_mainfile.py +55 -0
  30. pypaf-0.1.0/tests/test_po_box.py +28 -0
  31. pypaf-0.1.0/tests/test_rule_1.py +29 -0
  32. pypaf-0.1.0/tests/test_rule_2.py +30 -0
  33. pypaf-0.1.0/tests/test_rule_3.py +109 -0
  34. pypaf-0.1.0/tests/test_rule_4.py +31 -0
  35. pypaf-0.1.0/tests/test_rule_5.py +57 -0
  36. pypaf-0.1.0/tests/test_rule_6.py +79 -0
  37. pypaf-0.1.0/tests/test_rule_7.py +57 -0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 John Bard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
pypaf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.2
2
+ Name: PyPaf
3
+ Version: 0.1.0
4
+ Summary: Formats the elements of a Royal Mail Postcode Address File entry
5
+ Author-email: John Bard <johnbard@globalnet.co.uk>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/drabjay/pypaf
8
+ Project-URL: Repository, https://github.com/drabjay/pypaf.git
9
+ Project-URL: Issues, https://github.com/drabjay/paf/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE.txt
15
+
16
+ # PyPaf
17
+
18
+ Formats the elements of a Royal Mail Postcode Address File entry according to the rules described in the [Royal Mail Programmer's Guide Edition 7, Version 5.0](http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf)
19
+
20
+ ## Installation
21
+
22
+ Install it from PyPI:
23
+
24
+ $ pip install pypaf
25
+
26
+ ## Usage
27
+
28
+ May be used to format the PAF elements as an array of strings:
29
+
30
+ ```python
31
+ from paf import Paf
32
+ paf = Paf({
33
+ 'building_name': "1-2",
34
+ 'thoroughfare_name': "NURSERY",
35
+ 'thoroughfare_descriptor': "LANE",
36
+ 'dependent_locality': "PENN",
37
+ 'post_town': "HIGH WYCOMBE",
38
+ 'postcode': "HP10 8LS"
39
+ })
40
+ paf.list()
41
+
42
+ ['1-2 NURSERY LANE', 'PENN', 'HIGH WYCOMBE', 'HP10 8LS']
43
+ ```
44
+
45
+ Or as a single string:
46
+
47
+ ```python
48
+ from paf import Paf
49
+ paf = Paf({
50
+ 'building_name': "1-2",
51
+ 'thoroughfare_name': "NURSERY",
52
+ 'thoroughfare_descriptor': "LANE",
53
+ 'dependent_locality': "PENN",
54
+ 'post_town': "HIGH WYCOMBE",
55
+ 'postcode': "HP10 8LS"
56
+ })
57
+ str(paf)
58
+
59
+ '1-2 NURSERY LANE, PENN, HIGH WYCOMBE. HP10 8LS'
60
+ ```
61
+
62
+ ## Contributing
63
+
64
+ Bug reports and pull requests are welcome on GitHub at https://github.com/drabjay/pypaf. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
65
+
66
+ ## License
67
+
68
+ The package is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
69
+
70
+ ## Code of Conduct
71
+
72
+ Everyone interacting in the PyPaf project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/drabjayc/pypaf/blob/master/CODE_OF_CONDUCT.md).
pypaf-0.1.0/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # PyPaf
2
+
3
+ Formats the elements of a Royal Mail Postcode Address File entry according to the rules described in the [Royal Mail Programmer's Guide Edition 7, Version 5.0](http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf)
4
+
5
+ ## Installation
6
+
7
+ Install it from PyPI:
8
+
9
+ $ pip install pypaf
10
+
11
+ ## Usage
12
+
13
+ May be used to format the PAF elements as an array of strings:
14
+
15
+ ```python
16
+ from paf import Paf
17
+ paf = Paf({
18
+ 'building_name': "1-2",
19
+ 'thoroughfare_name': "NURSERY",
20
+ 'thoroughfare_descriptor': "LANE",
21
+ 'dependent_locality': "PENN",
22
+ 'post_town': "HIGH WYCOMBE",
23
+ 'postcode': "HP10 8LS"
24
+ })
25
+ paf.list()
26
+
27
+ ['1-2 NURSERY LANE', 'PENN', 'HIGH WYCOMBE', 'HP10 8LS']
28
+ ```
29
+
30
+ Or as a single string:
31
+
32
+ ```python
33
+ from paf import Paf
34
+ paf = Paf({
35
+ 'building_name': "1-2",
36
+ 'thoroughfare_name': "NURSERY",
37
+ 'thoroughfare_descriptor': "LANE",
38
+ 'dependent_locality': "PENN",
39
+ 'post_town': "HIGH WYCOMBE",
40
+ 'postcode': "HP10 8LS"
41
+ })
42
+ str(paf)
43
+
44
+ '1-2 NURSERY LANE, PENN, HIGH WYCOMBE. HP10 8LS'
45
+ ```
46
+
47
+ ## Contributing
48
+
49
+ Bug reports and pull requests are welcome on GitHub at https://github.com/drabjay/pypaf. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
50
+
51
+ ## License
52
+
53
+ The package is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
54
+
55
+ ## Code of Conduct
56
+
57
+ Everyone interacting in the PyPaf project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/drabjayc/pypaf/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,29 @@
1
+ [project]
2
+ name = "PyPaf"
3
+ dynamic = ["version"]
4
+ authors = [
5
+ { name="John Bard", email="johnbard@globalnet.co.uk" },
6
+ ]
7
+ description = "Formats the elements of a Royal Mail Postcode Address File entry"
8
+ readme = "README.md"
9
+ requires-python = ">=3.8"
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3",
12
+ "Operating System :: OS Independent"
13
+ ]
14
+ license = { text = "MIT", files = ["LICEN[CS]E*"] }
15
+
16
+ [project.urls]
17
+ Homepage = "https://github.com/drabjay/pypaf"
18
+ Repository = "https://github.com/drabjay/pypaf.git"
19
+ Issues = "https://github.com/drabjay/paf/issues"
20
+
21
+ [build-system]
22
+ requires = ["setuptools >= 61.0"]
23
+ build-backend = "setuptools.build_meta"
24
+
25
+ [tool.setuptools.dynamic]
26
+ version = { attr = "paf.__version__" }
27
+
28
+ [tool.setuptools.packages.find]
29
+ where = ["src"]
pypaf-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.2
2
+ Name: PyPaf
3
+ Version: 0.1.0
4
+ Summary: Formats the elements of a Royal Mail Postcode Address File entry
5
+ Author-email: John Bard <johnbard@globalnet.co.uk>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/drabjay/pypaf
8
+ Project-URL: Repository, https://github.com/drabjay/pypaf.git
9
+ Project-URL: Issues, https://github.com/drabjay/paf/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE.txt
15
+
16
+ # PyPaf
17
+
18
+ Formats the elements of a Royal Mail Postcode Address File entry according to the rules described in the [Royal Mail Programmer's Guide Edition 7, Version 5.0](http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf)
19
+
20
+ ## Installation
21
+
22
+ Install it from PyPI:
23
+
24
+ $ pip install pypaf
25
+
26
+ ## Usage
27
+
28
+ May be used to format the PAF elements as an array of strings:
29
+
30
+ ```python
31
+ from paf import Paf
32
+ paf = Paf({
33
+ 'building_name': "1-2",
34
+ 'thoroughfare_name': "NURSERY",
35
+ 'thoroughfare_descriptor': "LANE",
36
+ 'dependent_locality': "PENN",
37
+ 'post_town': "HIGH WYCOMBE",
38
+ 'postcode': "HP10 8LS"
39
+ })
40
+ paf.list()
41
+
42
+ ['1-2 NURSERY LANE', 'PENN', 'HIGH WYCOMBE', 'HP10 8LS']
43
+ ```
44
+
45
+ Or as a single string:
46
+
47
+ ```python
48
+ from paf import Paf
49
+ paf = Paf({
50
+ 'building_name': "1-2",
51
+ 'thoroughfare_name': "NURSERY",
52
+ 'thoroughfare_descriptor': "LANE",
53
+ 'dependent_locality': "PENN",
54
+ 'post_town': "HIGH WYCOMBE",
55
+ 'postcode': "HP10 8LS"
56
+ })
57
+ str(paf)
58
+
59
+ '1-2 NURSERY LANE, PENN, HIGH WYCOMBE. HP10 8LS'
60
+ ```
61
+
62
+ ## Contributing
63
+
64
+ Bug reports and pull requests are welcome on GitHub at https://github.com/drabjay/pypaf. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
65
+
66
+ ## License
67
+
68
+ The package is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
69
+
70
+ ## Code of Conduct
71
+
72
+ Everyone interacting in the PyPaf project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/drabjayc/pypaf/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,35 @@
1
+ LICENSE.txt
2
+ README.md
3
+ pyproject.toml
4
+ src/PyPaf.egg-info/PKG-INFO
5
+ src/PyPaf.egg-info/SOURCES.txt
6
+ src/PyPaf.egg-info/dependency_links.txt
7
+ src/PyPaf.egg-info/top_level.txt
8
+ src/paf/__init__.py
9
+ src/paf/attribute.py
10
+ src/paf/lineable.py
11
+ src/paf/paf.py
12
+ src/paf/premises_extender.py
13
+ src/paf/thoroughfare_locality.py
14
+ src/paf/version.py
15
+ src/paf/premises/__init__.py
16
+ src/paf/premises/common.py
17
+ src/paf/premises/rule000.py
18
+ src/paf/premises/rule001.py
19
+ src/paf/premises/rule010.py
20
+ src/paf/premises/rule011.py
21
+ src/paf/premises/rule101.py
22
+ src/paf/premises/rule110.py
23
+ src/paf/premises/rule111.py
24
+ tests/test_exception_i.py
25
+ tests/test_exception_ii.py
26
+ tests/test_exception_iii.py
27
+ tests/test_mainfile.py
28
+ tests/test_po_box.py
29
+ tests/test_rule_1.py
30
+ tests/test_rule_2.py
31
+ tests/test_rule_3.py
32
+ tests/test_rule_4.py
33
+ tests/test_rule_5.py
34
+ tests/test_rule_6.py
35
+ tests/test_rule_7.py
@@ -0,0 +1 @@
1
+ paf
@@ -0,0 +1,6 @@
1
+ """__init__ file"""
2
+
3
+ from .paf import Paf
4
+ from .version import __version__
5
+
6
+ __all__ = ["Paf", "__version__"]
@@ -0,0 +1,66 @@
1
+ """Attribute Mixin"""
2
+
3
+ class AttributeMixin():
4
+ """Base Paf address elements and derived properties"""
5
+
6
+ @classmethod
7
+ @property
8
+ def organisation_attrs(cls):
9
+ """Returns Paf organisation elements"""
10
+ return ['organisation_name', 'department_name']
11
+
12
+ @classmethod
13
+ @property
14
+ def premises_attrs(cls):
15
+ """Returns Paf premises elements"""
16
+ return ['sub_building_name', 'building_name', 'building_number']
17
+
18
+ @classmethod
19
+ @property
20
+ def dependent_thoroughfare_attrs(cls):
21
+ """Returns Paf dependent thoroughfare elements"""
22
+ return ['dependent_thoroughfare_name', 'dependent_thoroughfare_descriptor']
23
+
24
+ @classmethod
25
+ @property
26
+ def thoroughfare_attrs(cls):
27
+ """Returns Paf thoroughfare elements"""
28
+ return ['thoroughfare_name', 'thoroughfare_descriptor']
29
+
30
+ @classmethod
31
+ @property
32
+ def locality_attrs(cls):
33
+ """Returns Paf localoty elements"""
34
+ return ['double_dependent_locality', 'dependent_locality']
35
+
36
+ @classmethod
37
+ @property
38
+ def post_attrs(cls):
39
+ """Returns Paf post elements"""
40
+ return ['post_town', 'postcode']
41
+
42
+ @classmethod
43
+ @property
44
+ def other_attrs(cls):
45
+ """Returns Paf other elements"""
46
+ return ['po_box_number', 'udprn', 'concatenation_indicator']
47
+
48
+ @classmethod
49
+ @property
50
+ def attrs(cls):
51
+ """Returns all Paf address elements"""
52
+ return(
53
+ cls.organisation_attrs +
54
+ cls.premises_attrs +
55
+ cls.dependent_thoroughfare_attrs +
56
+ cls.thoroughfare_attrs +
57
+ cls.locality_attrs +
58
+ cls.post_attrs +
59
+ cls.other_attrs
60
+ )
61
+
62
+ def is_empty(self, attr):
63
+ """Returns if attribute value is empty"""
64
+ if getattr(self, attr, '') == '':
65
+ return True
66
+ return False
@@ -0,0 +1,27 @@
1
+ """Lineable Mixin"""
2
+
3
+ from itertools import chain
4
+ from .thoroughfare_locality import ThoroughfareLocalityMixin
5
+
6
+ class LineableMixin(ThoroughfareLocalityMixin):
7
+ """Converts Paf address elements into list of address lines, excluding postcode"""
8
+
9
+ @classmethod
10
+ @property
11
+ def lines_attrs(cls):
12
+ """Returns Paf address line attributes"""
13
+ return(
14
+ cls.organisation_attrs +
15
+ ['po_box', 'premises', 'thoroughfares_and_localities', 'post_town']
16
+ )
17
+
18
+ @property
19
+ def lines(self):
20
+ """Returns Paf as list of address lines"""
21
+ lines = list(filter(None, [getattr(self, k, None) for k in self.__class__.lines_attrs]))
22
+ return list(chain(*[line if isinstance(line, list) else [line] for line in lines]))
23
+
24
+ @property
25
+ def po_box(self):
26
+ """Returns PO Box"""
27
+ return '' if self.is_empty('po_box_number') else f"PO BOX {getattr(self, 'po_box_number')}"
@@ -0,0 +1,33 @@
1
+ """Paf"""
2
+
3
+ from .lineable import LineableMixin
4
+
5
+ class Paf(LineableMixin):
6
+ """Main Paf class"""
7
+
8
+ def __init__(self, args):
9
+ """Initialise Paf address elements"""
10
+ for key in self.__class__.attrs:
11
+ setattr(self, key, '')
12
+ for key, val in args.items():
13
+ if hasattr(self, key):
14
+ setattr(self, key, val)
15
+ self.extend_premises()
16
+
17
+ def __repr__(self):
18
+ """Return full representation of Paf"""
19
+ args = {k: getattr(self, k) for k in self.__class__.attrs if getattr(self, k, None)}
20
+ return self.__class__.__name__ + '(' + str(args) + ')'
21
+
22
+ def __str__(self):
23
+ """Return Paf as string"""
24
+ line = ', '.join(self.lines)
25
+ if self.is_empty('postcode'):
26
+ return line
27
+ return '. '.join([line] + [getattr(self, 'postcode')])
28
+
29
+ def list(self):
30
+ """Return Paf as list of strings"""
31
+ if self.is_empty('postcode'):
32
+ return self.lines
33
+ return self.lines + [getattr(self, 'postcode')]
File without changes
@@ -0,0 +1,38 @@
1
+ """Common"""
2
+
3
+ import re
4
+
5
+ class Common:
6
+ """Common premises processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Abstract method to be implemented by the Rule"""
11
+
12
+ @property
13
+ def premises(self):
14
+ """Returns premises list"""
15
+ return [getattr(self, k) for k in self.premises_rule_attrs]
16
+
17
+ @property
18
+ def name_and_thoroughfare_or_locality(self):
19
+ """Returns building number and first thoroughfare or locality"""
20
+ return self._concatenate(['building_name', 'first_thoroughfare_or_locality'])
21
+
22
+ @property
23
+ def number_and_thoroughfare_or_locality(self):
24
+ """Returns building number and first thoroughfare or locality"""
25
+ return self._concatenate(['building_number', 'first_thoroughfare_or_locality'])
26
+
27
+ @property
28
+ def sub_name_and_name(self):
29
+ """Returns sub-building name and building name"""
30
+ return self._concatenate(['sub_building_name', 'building_name'])
31
+
32
+ def is_exception(self, attr):
33
+ """Returns if value is an exception"""
34
+ return re.match(r'^(.|[\d][a-zA-Z]|[\d].*?[\d][a-zA-Z]?)$', getattr(self, attr, None))
35
+
36
+ def _concatenate(self, keys, concatenator=' '):
37
+ """Returns specified attributes concatenated with a specified separator"""
38
+ return concatenator.join(filter(None, [getattr(self, k, None) for k in keys]))
@@ -0,0 +1,16 @@
1
+ """Rule 1"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule000(Common):
6
+ """Rule 1 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ return []
12
+
13
+ @property
14
+ def does_premises_include_first_thoroughfare_or_locality(self):
15
+ """Returns if premises includes first thoroughfare or locality"""
16
+ return False
@@ -0,0 +1,16 @@
1
+ """Rule 2"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule001(Common):
6
+ """Rule 2 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ return ['number_and_thoroughfare_or_locality']
12
+
13
+ @property
14
+ def does_premises_include_first_thoroughfare_or_locality(self):
15
+ """Returns if premises includes first thoroughfare or locality"""
16
+ return True
@@ -0,0 +1,46 @@
1
+ """Rule 3"""
2
+
3
+ import re
4
+ from .common import Common
5
+
6
+ class Rule010(Common):
7
+ """Rule 3 processing"""
8
+
9
+ @property
10
+ def premises_rule_attrs(self):
11
+ """Returns premises list"""
12
+ if self.is_exception('building_name'):
13
+ return ['name_and_thoroughfare_or_locality']
14
+ if self.is_building_name_split_exception:
15
+ return ['building_name_but_last_word', 'name_last_word_and_thoroughfare_or_locality']
16
+ return ['building_name']
17
+
18
+ @property
19
+ def does_premises_include_first_thoroughfare_or_locality(self):
20
+ """Returns if premises includes first thoroughfare or locality"""
21
+ return self.is_exception('building_name') or self.is_building_name_split_exception
22
+
23
+ @property
24
+ def is_building_name_split_exception(self):
25
+ """Returns if building name should be split"""
26
+ return(
27
+ self.is_exception('building_name_last_word') and
28
+ not re.match(r'^\d+$', self.building_name_last_word)
29
+ )
30
+
31
+ @property
32
+ def building_name_last_word(self):
33
+ """Returns last word of the building name"""
34
+ *_, last = getattr(self, 'building_name', '').split()
35
+ return last
36
+
37
+ @property
38
+ def building_name_but_last_word(self):
39
+ """Returns all but last word of the building name"""
40
+ *first, _ = getattr(self, 'building_name', '').split()
41
+ return ' '.join(first)
42
+
43
+ @property
44
+ def name_last_word_and_thoroughfare_or_locality(self):
45
+ """Returns last word of building name and first thoroughfare or locality"""
46
+ return self._concatenate(['building_name_last_word', 'first_thoroughfare_or_locality'])
@@ -0,0 +1,16 @@
1
+ """Rule 4"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule011(Common):
6
+ """Rule 4 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ return ['building_name', 'number_and_thoroughfare_or_locality']
12
+
13
+ @property
14
+ def does_premises_include_first_thoroughfare_or_locality(self):
15
+ """Returns if premises includes first thoroughfare or locality"""
16
+ return True
@@ -0,0 +1,30 @@
1
+ """Rule 5"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule101(Common):
6
+ """Rule 5 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ if getattr(self, 'concatenation_indicator', '') == 'Y':
12
+ return ['number_sub_name_and_thoroughfare_or_locality']
13
+ return ['sub_building_name', 'number_and_thoroughfare_or_locality']
14
+
15
+ @property
16
+ def does_premises_include_first_thoroughfare_or_locality(self):
17
+ """Returns if premises includes first thoroughfare or locality"""
18
+ return True
19
+
20
+ @property
21
+ def building_number_and_sub_building_name(self):
22
+ """Returns building number and sub-building name"""
23
+ return self._concatenate(['building_number', 'sub_building_name'], '')
24
+
25
+ @property
26
+ def number_sub_name_and_thoroughfare_or_locality(self):
27
+ """Returns building number, sub-building name and first thoroughfare or locality"""
28
+ return(self._concatenate([
29
+ 'building_number_and_sub_building_name', 'first_thoroughfare_or_locality'
30
+ ]))
@@ -0,0 +1,20 @@
1
+ """Rule 6"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule110(Common):
6
+ """Rule 6 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ if self.is_exception('sub_building_name'):
12
+ return['sub_name_and_name']
13
+ if self.is_exception('building_name'):
14
+ return['sub_building_name', 'name_and_thoroughfare_or_locality']
15
+ return ['sub_building_name', 'building_name']
16
+
17
+ @property
18
+ def does_premises_include_first_thoroughfare_or_locality(self):
19
+ """Returns if premises includes first thoroughfare or locality"""
20
+ return (not self.is_exception('sub_building_name')) and self.is_exception('building_name')
@@ -0,0 +1,18 @@
1
+ """Rule 7"""
2
+
3
+ from .common import Common
4
+
5
+ class Rule111(Common):
6
+ """Rule 7 processing"""
7
+
8
+ @property
9
+ def premises_rule_attrs(self):
10
+ """Returns premises list"""
11
+ if self.is_exception('sub_building_name'):
12
+ return['sub_name_and_name', 'number_and_thoroughfare_or_locality']
13
+ return ['sub_building_name', 'building_name', 'number_and_thoroughfare_or_locality']
14
+
15
+ @property
16
+ def does_premises_include_first_thoroughfare_or_locality(self):
17
+ """Returns if premises includes first thoroughfare or locality"""
18
+ return True