Projet

Général

Profil

0001-opendatasoft-remove-operators-form-query-parameter-4.patch

Nicolas Roche, 27 mai 2022 12:17

Télécharger (5,36 ko)

Voir les différences:

Subject: [PATCH] opendatasoft: remove operators form query parameter (#43235)

 passerelle/apps/opendatasoft/models.py |  6 +++++-
 tests/test_opendatasoft.py             | 16 ++++++++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)
passerelle/apps/opendatasoft/models.py
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU Affero General Public License for more details.
13 13
#
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import re
17 18
from urllib import parse as urlparse
18 19

  
19 20
from django.db import models
20 21
from django.shortcuts import get_object_or_404
21 22
from django.urls import reverse
22 23
from django.utils.translation import ugettext_lazy as _
23 24
from requests import RequestException
24 25

  
......
72 73
        scheme, netloc, path, params, query, fragment = urlparse.urlparse(self.service_url)
73 74
        path = urlparse.urljoin(path, 'api/records/1.0/search/')
74 75
        url = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
75 76

  
76 77
        params = {'dataset': dataset}
77 78
        if id is not None:
78 79
            params['q'] = 'recordid:%s' % id
79 80
        elif q is not None:
80
            params['q'] = q
81
            # remove query language operators
82
            terms = re.split('[^\w]', q)
83
            terms = [term for term in terms if len(term) > 1 and term.lower() not in ['and', 'or', 'not']]
84
            params['q'] = ' '.join(terms)
81 85
        elif sort:
82 86
            params['sort'] = sort
83 87
        if self.api_key:
84 88
            params['apikey'] = self.api_key
85 89
        if limit:
86 90
            params['rows'] = limit
87 91
        params.update(urlparse.parse_qs(filter_expression))
88 92

  
tests/test_opendatasoft.py
239 239
        'q': "rue de l'aubepine",
240 240
    }
241 241
    mocked_get.return_value = tests.utils.FakedResponse(content=FAKED_CONTENT_Q_SEARCH, status_code=200)
242 242
    resp = app.get(endpoint, params=params, status=200)
243 243
    assert mocked_get.call_args[1]['params'] == {
244 244
        'apikey': 'my_secret',
245 245
        'dataset': 'referentiel-adresse-test',
246 246
        'rows': '3',
247
        'q': "rue de l'aubepine",
247
        'q': "rue de aubepine",
248 248
    }
249 249
    assert not resp.json['err']
250 250
    assert len(resp.json['data']) == 3
251 251
    # check order is kept
252 252
    assert [x['id'] for x in resp.json['data']] == [
253 253
        'e00cf6161e52a4c8fe510b2b74d4952036cb3473',
254 254
        '7cafcd5c692773e8b863587b2d38d6be82e023d8',
255 255
        '0984a5e1745701f71c91af73ce764e1f7132e0ff',
......
258 258
    assert [x['text'] for x in resp.json['data']] == [
259 259
        "33 RUE DE L'AUBEPINE Strasbourg",
260 260
        "19 RUE DE L'AUBEPINE Lipsheim",
261 261
        "29 RUE DE L'AUBEPINE Strasbourg",
262 262
    ]
263 263
    # check additional attributes
264 264
    assert [x['numero'] for x in resp.json['data']] == ['33', '19', '29']
265 265

  
266
    # check operators are removed
267
    params['q'] = 'please, do NOT send boolean operators like And, OR and nOt'
268
    resp = app.get(endpoint, params=params, status=200)
269
    assert mocked_get.call_args[1]['params']['q'] == 'please do send boolean operators like'
270

  
271
    params['q'] = 'field operators are almost ignored too:, -, ==, >, <, >=, <=, [start_date TO end_date]'
272
    resp = app.get(endpoint, params=params, status=200)
273
    assert (
274
        mocked_get.call_args[1]['params']['q']
275
        == 'field operators are almost ignored too start_date TO end_date'
276
    )
277

  
266 278

  
267 279
@mock.patch('passerelle.utils.Request.get')
268 280
def test_search_using_id(mocked_get, app, connector):
269 281
    endpoint = tests.utils.generic_endpoint_url('opendatasoft', 'search', slug=connector.slug)
270 282
    assert endpoint == '/opendatasoft/my_connector/search'
271 283
    params = {
272 284
        'dataset': 'referentiel-adresse-test',
273 285
        'text_template': '{{numero}} {{nom_rue}} {{nom_commun}}',
......
327 339
    mocked_get.return_value = tests.utils.FakedResponse(content=FAKED_CONTENT_Q_SEARCH, status_code=200)
328 340
    resp = app.get(endpoint, params=params, status=200)
329 341
    assert mocked_get.call_args[1]['params'] == {
330 342
        'apikey': 'my_secret',
331 343
        'dataset': 'referentiel-adresse-test',
332 344
        'refine.source': ['Ville et Eurométropole de Strasbourg'],
333 345
        'exclude.numero': ['42', '43'],
334 346
        'rows': 3,
335
        'q': "rue de l'aubepine",
347
        'q': "rue de aubepine",
336 348
    }
337 349
    assert not resp.json['err']
338 350
    assert len(resp.json['data']) == 3
339 351
    # check order is kept
340 352
    assert [x['id'] for x in resp.json['data']] == [
341 353
        'e00cf6161e52a4c8fe510b2b74d4952036cb3473',
342 354
        '7cafcd5c692773e8b863587b2d38d6be82e023d8',
343 355
        '0984a5e1745701f71c91af73ce764e1f7132e0ff',
344
-