Projet

Général

Profil

0003-opengis-PEP8ness-code-style-30458.patch

Benjamin Dauvergne, 08 février 2019 08:43

Télécharger (18,5 ko)

Voir les différences:

Subject: [PATCH 03/13] opengis: PEP8ness, code style (#30458)

 passerelle/apps/opengis/models.py | 79 ++++++++++++++++++--------
 tests/test_opengis.py             | 92 +++++++++++++++++++++++++------
 2 files changed, 131 insertions(+), 40 deletions(-)
passerelle/apps/opengis/models.py
18 18
import xml.etree.ElementTree as ET
19 19
from HTMLParser import HTMLParser
20 20

  
21
import six
22

  
21 23
import pyproj
22 24

  
23 25
from django.core.cache import cache
......
59 61
    projection = models.CharField(_('GIS projection'), choices=PROJECTIONS,
60 62
                                  default='EPSG:3857', max_length=16)
61 63
    search_radius = models.IntegerField(_('Radius for point search'), default=5)
62
    attributes_mapping = (('road', ('road', 'road_name', 'street', 'street_name', 'voie', 'nom_voie', 'rue')),
63
                          ('city', ('city', 'city_name', 'town', 'town_name', 'commune', 'nom_commune', 'ville', 'nom_ville')),
64
                          ('house_number', ('house_number', 'number', 'numero', 'numero_voie', 'numero_rue')),
65
                          ('postcode', ('postcode', 'postalCode', 'zipcode', 'codepostal', 'cp', 'code_postal', 'code_post')),
66
                          ('country', ('country', 'country_name', 'pays', 'nom_pays'))
67
                          )
64
    attributes_mapping = (
65
        ('road', ('road', 'road_name', 'street', 'street_name', 'voie', 'nom_voie', 'rue')),
66
        ('city', ('city', 'city_name', 'town', 'town_name', 'commune', 'nom_commune', 'ville', 'nom_ville')),
67
        ('house_number', ('house_number', 'number', 'numero', 'numero_voie', 'numero_rue')),
68
        ('postcode', ('postcode', 'postalCode', 'zipcode', 'codepostal', 'cp', 'code_postal', 'code_post')),
69
        ('country', ('country', 'country_name', 'pays', 'nom_pays'))
70
    )
68 71

  
69 72
    class Meta:
70 73
        verbose_name = _('OpenGIS')
......
92 95

  
93 96
    def check_status(self):
94 97
        if self.wms_service_url:
95
            response = self.requests.get(self.wms_service_url,
96
                    params={'service': 'WMS', 'request': 'GetCapabilities'})
98
            response = self.requests.get(
99
                self.wms_service_url,
100
                params={
101
                    'service': 'WMS',
102
                    'request': 'GetCapabilities'
103
                })
97 104
            response.raise_for_status()
98 105
        if self.wfs_service_url:
99
            response = self.requests.get(self.wfs_service_url,
100
                    params={'service': 'WFS', 'request': 'GetCapabilities'})
106
            response = self.requests.get(
107
                self.wfs_service_url,
108
                params={
109
                    'service': 'WFS',
110
                    'request': 'GetCapabilities'
111
                })
101 112
            response.raise_for_status()
102 113

  
103 114
    @endpoint(perm='can_access', description='Get features',
104
              parameters={'type_names': {'description': _('Type of feature to query'), 'example_value':'feature'},
105
                         'property_name': {'description': _('Property to list'), 'example_value':'nom_commune'},
106
                         'cql_filter': {'description': _('CQL filter applied to the query'), 'example_value':'commune=\'Paris\''},
107
                         'filter_property_name': {'description': _('Property by which to filter'), 'example_value':'voie'},
108
                         'q': {'description': _('Filter value'), 'example_value':'rue du chateau'},
109
                         'case-insensitive': {'description': _('Enables case-insensitive search'), 'example_value':'true'}
110
             })
111
    def features(self, request, type_names, property_name, cql_filter=None, filter_property_name=None, q=None, **kwargs):
115
              parameters={
116
                  'type_names': {
117
                      'description': _('Type of feature to query'),
118
                      'example_value': 'feature'
119
                  },
120
                  'property_name': {
121
                      'description': _('Property to list'),
122
                      'example_value': 'nom_commune'
123
                  },
124
                  'cql_filter': {
125
                      'description': _('CQL filter applied to the query'),
126
                      'example_value': 'commune=\'Paris\''
127
                  },
128
                  'filter_property_name': {
129
                      'description': _('Property by which to filter'),
130
                      'example_value': 'voie'
131
                  },
132
                  'q': {
133
                      'description': _('Filter value'),
134
                      'example_value': 'rue du chateau'
135
                  },
136
                  'case-insensitive': {
137
                      'description': _('Enables case-insensitive search'),
138
                      'example_value': 'true'
139
                  }
140
              })
141
    def features(self, request, type_names, property_name, cql_filter=None,
142
                 filter_property_name=None, q=None, **kwargs):
112 143
        params = {
113 144
            'VERSION': self.get_wfs_service_version(),
114 145
            'SERVICE': 'WFS',
......
128 159
        response = self.requests.get(self.wfs_service_url, params=params)
129 160
        data = []
130 161
        try:
131
            json_result = response.json()
162
            response.json()
132 163
        except ValueError:
133 164
            self.handle_opengis_error(response)
134 165
            # if handle_opengis_error did not raise an error, we raise a generic one
......
252 283
            'SRS': self.projection,
253 284
            'BBOX': bbox,
254 285
        }
255
        return HttpResponse(
256
                self.requests.get(self.wms_service_url, params=params, cache_duration=300).content,
257
                content_type='image/png')
286
        response = self.requests.get(
287
            self.wms_service_url,
288
            params=params,
289
            cache_duration=300)
290
        return HttpResponse(response.content, content_type='image/png')
258 291

  
259 292
    @endpoint(perm='can_access', description=_('Get feature info'))
260 293
    def reverse(self, request, lat, lon, **kwargs):
......
299 332
            for attribute, properties in self.attributes_mapping:
300 333
                for field in properties:
301 334
                    if closest_feature['properties'].get(field):
302
                        result['address'][attribute] = unicode(closest_feature['properties'][field])
335
                        result['address'][attribute] = six.text_type(closest_feature['properties'][field])
303 336
                        break
304 337
            return result
305 338
        raise APIError('Unable to geocode')
tests/test_opengis.py
6 6
import utils
7 7

  
8 8
FAKE_FEATURE_INFO = '''<?xml version="1.0" encoding="UTF-8"?>
9
<msGMLOutput xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
9
<msGMLOutput
10
      xmlns:gml="http://www.opengis.net/gml"
11
      xmlns:xlink="http://www.w3.org/1999/xlink"
12
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
10 13
  <cad_cadastre.cadparcelle_layer>
11 14
    <gml:name>Parcelle cadastrale (Plan cadastral informatise du Grand Lyon)</gml:name>
12 15
    <cad_cadastre.cadparcelle_feature>
......
28 31
</msGMLOutput>'''
29 32

  
30 33
FAKE_SERVICE_CAPABILITIES = '''<?xml version="1.0" encoding="UTF-8"?>
31
<wfs:WFS_Capabilities version="2.0.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1">
34
<wfs:WFS_Capabilities version="2.0.0"
35
       xmlns:wfs="http://www.opengis.net/wfs/2.0"
36
       xmlns:ows="http://www.opengis.net/ows/1.1">
32 37
    <ows:ServiceIdentification>
33 38
        <ows:Title/><ows:Abstract/>
34 39
        <ows:ServiceType>WFS</ows:ServiceType><ows:ServiceTypeVersion>2.0.0</ows:ServiceTypeVersion><ows:Fees/>
......
99 104
    "type": "FeatureCollection"
100 105
}'''
101 106

  
102
FAKE_ERROR = u'<ows:ExceptionReport xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.0" xsi:schemaLocation="http://www.opengis.net/ows/1.1 https://sigmetropole.lametro.fr/geoserver/schemas/ows/1.1.0/owsAll.xsd">\n  <ows:Exception exceptionCode="NoApplicableCode">\n    <ows:ExceptionText>Could not parse CQL filter list.\nEncountered &amp;quot;BIS&amp;quot; at line 1, column 129.\nWas expecting one of:\n    &amp;lt;EOF&amp;gt; \n    &amp;quot;and&amp;quot; ...\n    &amp;quot;or&amp;quot; ...\n    &amp;quot;;&amp;quot; ...\n    &amp;quot;/&amp;quot; ...\n    &amp;quot;*&amp;quot; ...\n    &amp;quot;+&amp;quot; ...\n    &amp;quot;-&amp;quot; ...\n     Parsing : strEqualsIgnoreCase(nom_commune, &amp;apos;Grenoble&amp;apos;) = true AND strEqualsIgnoreCase(nom_voie, &amp;apos;rue albert recoura&amp;apos;) = true AND numero=8 BIS.</ows:ExceptionText>\n  </ows:Exception>\n</ows:ExceptionReport>\n'
107
FAKE_ERROR = u'''<ows:ExceptionReport
108
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
109
     xmlns:ows="http://www.opengis.net/ows/1.1"
110
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
111
     version="2.0.0"
112
     xsi:schemaLocation="http://www.opengis.net/ows/1.1 https://sigmetropole.lametro.fr/geoserver/schemas/ows/1.1.0/owsAll.xsd">
113
  <ows:Exception exceptionCode="NoApplicableCode">
114
    <ows:ExceptionText>Could not parse CQL filter list.
115
Encountered &amp;quot;BIS&amp;quot; at line 1, column 129.
116
Was expecting one of:
117
    &amp;lt;EOF&amp;gt;
118
    &amp;quot;and&amp;quot; ...
119
    &amp;quot;or&amp;quot; ...
120
    &amp;quot;;&amp;quot; ...
121
    &amp;quot;/&amp;quot; ...
122
    &amp;quot;*&amp;quot; ...
123
    &amp;quot;+&amp;quot; ...
124
    &amp;quot;-&amp;quot; ...
125
     Parsing : strEqualsIgnoreCase(nom_commune, &amp;apos;Grenoble&amp;apos;) = true AND strEqualsIgnoreCase(nom_voie, &amp;apos;rue albert recoura&amp;apos;) = true AND numero=8 BIS.</ows:ExceptionText>
126
  </ows:Exception>
127
</ows:ExceptionReport>
128
'''
103 129

  
104 130
FAKE_GEOLOCATED_FEATURE = '''{
105 131
    "crs": {
......
195 221
        wms_service_url='http://example.net/wms',
196 222
        wfs_service_url='http://example.net/wfs'))
197 223

  
224

  
198 225
def geoserver_responses(url, **kwargs):
199 226
    if kwargs['params'].get('request') == 'GetCapabilities':
200 227
        return utils.FakedResponse(status_code=200, content=FAKE_SERVICE_CAPABILITIES)
201 228
    return utils.FakedResponse(status_code=200, content=FAKE_FEATURES_JSON)
202 229

  
230

  
203 231
def geoserver_responses_errors(url, **kwargs):
204 232
    if kwargs['params'].get('request') == 'GetCapabilities':
205 233
        return utils.FakedResponse(status_code=200, content=FAKE_SERVICE_CAPABILITIES)
206 234
    return utils.FakedResponse(status_code=200, content=FAKE_ERROR)
207 235

  
236

  
208 237
def geoserver_responses_errors_unparsable(url, **kwargs):
209 238
    if kwargs['params'].get('request') == 'GetCapabilities':
210 239
        return utils.FakedResponse(status_code=200, content=FAKE_SERVICE_CAPABILITIES)
211 240
    return utils.FakedResponse(status_code=200, content=FAKE_ERROR[:10])
212 241

  
242

  
213 243
@mock.patch('passerelle.utils.Request.get')
214 244
def test_feature_info(mocked_get, app, connector):
215 245
    endpoint = utils.generic_endpoint_url('opengis', 'feature_info', slug=connector.slug)
......
218 248
    resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'})
219 249
    assert mocked_get.call_args[1]['params']['BBOX'] == '5747860.22776,532568.028684,5748179.56467,532790.667665'
220 250
    assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:3857'
221
    assert resp.json['data']['cad_cadastrecadparcelle_layer']['cad_cadastrecadparcelle_feature']['natureproprietaire'] == 'Particulier'
251
    assert (resp.json['data']
252
                     ['cad_cadastrecadparcelle_layer']
253
                     ['cad_cadastrecadparcelle_feature']
254
                     ['natureproprietaire']
255
            == 'Particulier')
222 256
    connector.projection = 'EPSG:4326'
223 257
    connector.save()
224 258
    resp = app.get(endpoint, params={'lat': '45.796890', 'lon': '4.784140'})
225 259
    assert mocked_get.call_args[1]['params']['BBOX'] == '45.796890,4.784140,45.79889,4.78614'
226 260
    assert mocked_get.call_args[1]['params']['CRS'] == 'EPSG:4326'
227 261

  
262

  
228 263
@mock.patch('passerelle.utils.Request.get')
229 264
def test_tile(mocked_get, app, connector):
230 265
    endpoint = utils.generic_endpoint_url('opengis', 'tile', slug=connector.slug)
......
249 284
    assert endpoint == '/opengis/test/features'
250 285
    mocked_get.side_effect = geoserver_responses
251 286
    resp = app.get(endpoint, params={'type_names': 'ref_metro_limites_communales', 'property_name': 'nom'})
252
    print resp.content
253
    assert resp.json['data'] == None
287
    assert resp.json['data'] is None
254 288
    assert resp.json['err'] == 1
255 289
    assert resp.json['err_desc'] == 'no wfs URL declared'
256 290

  
291

  
257 292
@mock.patch('passerelle.utils.Request.get')
258 293
def test_get_feature(mocked_get, app, connector):
259 294
    endpoint = utils.generic_endpoint_url('opengis', 'features', slug=connector.slug)
......
270 305
    for item in resp.json['data']:
271 306
        assert 'text' in item
272 307

  
308

  
273 309
@mock.patch('passerelle.utils.Request.get')
274 310
def test_get_filtered_feature(mocked_get, app, connector):
275 311
    endpoint = utils.generic_endpoint_url('opengis', 'features', slug=connector.slug)
276 312
    mocked_get.side_effect = geoserver_responses
277
    resp = app.get(endpoint, params={'type_names': 'ref_metro_limites_communales',
278
                                     'property_name': 'nom', 'cql_filter': 'nom=\'Fontaine\''})
313
    app.get(endpoint,
314
            params={
315
                'type_names': 'ref_metro_limites_communales',
316
                'property_name': 'nom',
317
                'cql_filter': 'nom=\'Fontaine\''
318
            })
279 319
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'nom=\'Fontaine\''
280 320

  
321

  
281 322
@mock.patch('passerelle.utils.Request.get')
282 323
def test_get_filtered_by_property_feature(mocked_get, app, connector):
283 324
    endpoint = utils.generic_endpoint_url('opengis', 'features', slug=connector.slug)
......
285 326
    params = {'type_names': 'ref_metro_limites_communales',
286 327
              'property_name': 'nom', 'cql_filter': 'nom=\'Fontaine\'',
287 328
              'filter_property_name': 'nom'}
288
    resp = app.get(endpoint, params=params)
329
    app.get(endpoint, params=params)
289 330
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'nom=\'Fontaine\''
290 331
    params['q'] = 'bens'
291
    resp = app.get(endpoint, params=params)
332
    app.get(endpoint, params=params)
292 333
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'nom=\'Fontaine\' AND nom LIKE \'%bens%\''
293 334
    params['case-insensitive'] = True
294
    resp = app.get(endpoint, params=params)
335
    app.get(endpoint, params=params)
295 336
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'nom=\'Fontaine\' AND nom ILIKE \'%bens%\''
296 337
    params.pop('cql_filter')
297
    resp = app.get(endpoint, params=params)
338
    app.get(endpoint, params=params)
298 339
    assert 'CQL_FILTER' not in mocked_get.call_args[1]['params']
299 340

  
341

  
300 342
@mock.patch('passerelle.utils.Request.get')
301 343
def test_get_feature_error(mocked_get, app, connector):
302 344
    endpoint = utils.generic_endpoint_url('opengis', 'features', slug=connector.slug)
......
317 359
    assert result['err_desc'] == 'OpenGIS Error: NoApplicableCode'
318 360
    assert 'Could not parse' in result['data']['text']
319 361

  
362

  
320 363
@mock.patch('passerelle.utils.Request.get')
321
def test_get_feature_error(mocked_get, app, connector):
364
def test_get_feature_error2(mocked_get, app, connector):
322 365
    endpoint = utils.generic_endpoint_url('opengis', 'features', slug=connector.slug)
323 366
    assert endpoint == '/opengis/test/features'
324 367
    mocked_get.side_effect = geoserver_responses_errors_unparsable
......
337 380
    assert result['err_desc'] == 'OpenGIS Error: unparsable error'
338 381
    assert '<ows:' in result['data']['content']
339 382

  
383

  
340 384
@mock.patch('passerelle.utils.Request.get')
341 385
def test_reverse_geocoding(mocked_get, app, connector):
342 386
    connector.search_radius = 45
......
345 389
    endpoint = utils.generic_endpoint_url('opengis', 'reverse', slug=connector.slug)
346 390
    assert endpoint == '/opengis/test/reverse'
347 391
    mocked_get.return_value = utils.FakedResponse(content=FAKE_GEOLOCATED_FEATURE, status_code=200)
348
    resp = app.get(endpoint, params={'lat':'45.1893469606986', 'lon': '5.72462060798'})
349
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'DWITHIN(the_geom,Point(1914061.48604 4224640.45779),45,meters)'
392
    resp = app.get(endpoint,
393
                   params={
394
                       'lat': '45.1893469606986',
395
                       'lon': '5.72462060798'
396
                   })
397
    assert (mocked_get.call_args[1]['params']['CQL_FILTER']
398
            == 'DWITHIN(the_geom,Point(1914061.48604 4224640.45779),45,meters)')
350 399
    assert resp.json['lon'] == '5.72407744145'
351 400
    assert resp.json['lat'] == '45.1893972656'
352 401
    assert resp.json['address']['house_number'] == '4'
......
358 407
    connector.search_radius = 10
359 408
    connector.save()
360 409
    mocked_get.return_value = utils.FakedResponse(content='{"features": []}', status_code=200)
361
    resp = app.get(endpoint, params={'lat':'45.183784', 'lon': '5.714885'})
410
    resp = app.get(
411
        endpoint,
412
        params={
413
            'lat': '45.183784',
414
            'lon': '5.714885'
415
        })
362 416
    assert mocked_get.call_args[1]['params']['CQL_FILTER'] == 'DWITHIN(the_geom,Point(5.714885 45.183784),10,meters)'
363 417
    assert resp.json['err'] == 1
364 418
    assert resp.json['err_desc'] == 'Unable to geocode'
365 419

  
366 420
    mocked_get.return_value = utils.FakedResponse(status_code=404, content='{}', ok=False)
367
    resp = app.get(endpoint, params={'lat':'45.183784', 'lon': '5.714885'})
421
    resp = app.get(endpoint,
422
                   params={
423
                       'lat': '45.183784',
424
                       'lon': '5.714885'
425
                   })
368 426
    assert resp.json['err'] == 1
369 427
    assert resp.json['err_desc'] == 'Webservice returned status code 404'
370
-