Skip to content

Commit aa93486

Browse files
authored
Merge pull request #18 from gdalmau/imp_support_v3
Add support for Postcode API v3
2 parents aa0fc31 + 4582f44 commit aa93486

2 files changed

Lines changed: 122 additions & 17 deletions

File tree

pyPostcode/__init__.py

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import json
1616
import logging
17+
from warnings import warn
1718

1819

1920
__version__ = '0.5'
@@ -28,14 +29,14 @@ def __init__(self, id, message):
2829

2930
class Api(object):
3031

31-
def __init__(self, api_key, api_version=(2, 0, 0)):
32+
def __init__(self, api_key, api_version=(3, 0, 0)):
3233
if api_key is None or api_key is '':
3334
raise pyPostcodeException(
3435
0, "Please request an api key on http://postcodeapi.nu")
3536

3637
self.api_key = api_key
3738
self.api_version = api_version
38-
if api_version >= (2, 0, 0):
39+
if (2, 0, 0) <= api_version < (3, 0, 0):
3940
self.url = 'https://postcode-api.apiwise.nl'
4041
else:
4142
self.url = 'http://api.postcodeapi.nu'
@@ -58,9 +59,7 @@ def request(self, path=None):
5859
headers = {
5960
"Accept": "application/json",
6061
"Accept-Language": "en",
61-
# this is the v1 api
62-
"Api-Key": self.api_key,
63-
# this is the v2 api
62+
# this is the v2 and v3 api key
6463
"X-Api-Key": self.api_key,
6564
}
6665

@@ -77,28 +76,30 @@ def request(self, path=None):
7776
resultdata = resultdata.decode("utf-8") # for Python 3
7877
jsondata = json.loads(resultdata)
7978

80-
if self.api_version >= (2, 0, 0):
79+
if (2, 0, 0) <= self.api_version < (3, 0, 0):
8180
data = jsondata.get('_embedded', {}).get('addresses', [])
8281
if data:
8382
data = data[0]
8483
else:
8584
data = None
8685
else:
87-
data = jsondata['resource']
86+
data = jsondata
8887

8988
return data
9089

9190
def getaddress(self, postcode, house_number=None):
92-
if house_number is None:
93-
house_number = ''
94-
95-
if self.api_version >= (2, 0, 0):
96-
path = '/v2/addresses/?postcode={0}&number={1}'
91+
if (2, 0, 0) <= self.api_version < (3, 0, 0):
92+
path = '/v2/addresses/?postcode={0}'
93+
if house_number is not None:
94+
path += '&number={1}'
95+
resource = ResourceV2
9796
else:
98-
path = '/{0}/{1}'
97+
if house_number is None:
98+
raise ValueError('"house_number" cannot be None')
99+
path = '/v3/lookup/{postcode}/{house_number}'
100+
resource = ResourceV3
99101
path = path.format(
100-
str(postcode),
101-
str(house_number))
102+
postcode=str(postcode), house_number=str(house_number))
102103

103104
try:
104105
data = self.request(path)
@@ -113,16 +114,34 @@ def getaddress(self, postcode, house_number=None):
113114
data = None
114115

115116
if data is not None:
116-
return Resource(data)
117+
return resource(data)
117118
else:
118119
return False
119120

120121

121-
class Resource(object):
122+
class Resource:
122123

123124
def __init__(self, data):
124125
self._data = data
125126

127+
def not_implemented(self):
128+
raise NotImplementedError
129+
130+
street = property(not_implemented)
131+
house_number = property(not_implemented)
132+
postcode = property(not_implemented)
133+
town = property(not_implemented)
134+
municipality = property(not_implemented)
135+
province = property(not_implemented)
136+
latitude = property(not_implemented)
137+
longitude = property(not_implemented)
138+
x = property(not_implemented)
139+
y = property(not_implemented)
140+
coordinates = property(not_implemented)
141+
142+
143+
class ResourceV2(Resource):
144+
126145
@property
127146
def street(self):
128147
return self._data['street']
@@ -184,3 +203,58 @@ def y(self):
184203
if self._data.get('y'):
185204
return self._data.get('y')
186205
return self._get_geo_coordinates('rd')[1]
206+
207+
208+
class ResourceV3(Resource):
209+
210+
@property
211+
def street(self):
212+
return self._data['street']
213+
214+
@property
215+
def house_number(self):
216+
return self._data.get('number')
217+
218+
@property
219+
def postcode(self):
220+
return self._data.get('postcode')
221+
222+
@property
223+
def city(self):
224+
return self._data.get('city')
225+
226+
@property
227+
def town(self):
228+
warn('Use the attribute "city" instead',
229+
DeprecationWarning, stacklevel=2)
230+
return self.city
231+
232+
@property
233+
def municipality(self):
234+
return self._data.get('municipality')
235+
236+
@property
237+
def province(self):
238+
return self._data.get('province')
239+
240+
@property
241+
def coordinates(self):
242+
return self._data.get('location', {}).get('coordinates')
243+
244+
@property
245+
def latitude(self):
246+
coordinates = self.coordinates
247+
return coordinates and coordinates[1] or None
248+
249+
@property
250+
def longitude(self):
251+
coordinates = self.coordinates
252+
return coordinates and coordinates[0] or None
253+
254+
@property
255+
def x(self):
256+
return self.longitude
257+
258+
@property
259+
def y(self):
260+
return self.latitude

tests/test_api.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import unittest
2+
import os
3+
4+
from pyPostcode import Api, pyPostcodeException
5+
6+
7+
class TestAPI(unittest.TestCase):
8+
def setUp(self) -> None:
9+
self.api = Api(os.environ.get('POSTCODE_API_KEY'))
10+
self.api.url = 'https://sandbox.postcodeapi.nu'
11+
12+
def test_api_key_is_required(self):
13+
with self.assertRaises(pyPostcodeException):
14+
Api('')
15+
16+
def test_api(self):
17+
results = self.api.getaddress('6545CA', 29)
18+
latitude = 51.841554
19+
longitude = 5.8696099
20+
21+
self.assertEqual(results.postcode, '6545CA')
22+
self.assertEqual(results.house_number, 29)
23+
self.assertEqual(results.street, 'Waldeck Pyrmontsingel')
24+
self.assertEqual(results.city, 'Nijmegen')
25+
self.assertEqual(results.municipality, 'Nijmegen')
26+
self.assertEqual(results.province, 'Gelderland')
27+
self.assertEqual(results.coordinates, [longitude, latitude])
28+
self.assertEqual(results.x, longitude)
29+
self.assertEqual(results.longitude, longitude)
30+
self.assertEqual(results.y, latitude)
31+
self.assertEqual(results.latitude, latitude)

0 commit comments

Comments
 (0)