Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Account for more corner cases w/ section search. #84

Merged
merged 3 commits into from
Aug 17, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ python:
- "3.4"
- "3.5"
- "3.6"
- "pypy"
install:
- pip install coveralls tox-travis
script:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This repository is part of a larger project. To read about it, please see
## Requirements

This library requires
* Python 2.7 (including PyPy), 3.4, 3.5, or 3.6
* Python 2.7, 3.4, 3.5, or 3.6
* Django 1.8, 1.9, 1.10, or 1.11

## API Docs
Expand Down
97 changes: 78 additions & 19 deletions regcore_pgsql/tests/views_tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from django.db.models import Q
from mock import call, Mock

pytest.importorskip('django', minversion='1.10') # noqa
Expand Down Expand Up @@ -32,22 +33,80 @@ def test_matching_sections(monkeypatch):
assert call(documentindex__doc_root='rrr') in filters


def test_transform_results():
"""Verify conversion to a dict."""
sect1, sect2 = Mock(title='Section 111'), Mock(title='Section 222')
query1, query2 = make_queryset_mock(), make_queryset_mock()
sect1.get_descendants.return_value = query1
sect2.get_descendants.return_value = query2
query1.first.return_value = doc_recipe.prepare(
text='sect1', label_string='root-111', version='vvv',
title='Section 111')
query2.first.return_value = doc_recipe.prepare(
text='subpar', label_string='root-222-a-3', version='vvv')

assert views.transform_results([sect1, sect2], 'my terms') == [
dict(text='sect1', label=['root', '111'], version='vvv',
regulation='root', label_string='root-111', title='Section 111'),
dict(text='subpar', label=['root', '222', 'a', '3'], version='vvv',
regulation='root', label_string='root-222-a-3',
title='Section 222'),
]
@pytest.mark.django_db
def test_transform_results(monkeypatch):
"""If there's a text match inside a section, we should convert it to a
dictionary."""
monkeypatch.setattr( # __search isn't supported by sqlite
views, 'Q', Mock(return_value=Q(text__contains='matching')))
sect = doc_recipe.make(label_string='root-11', title='Sect 111',
version='vvv')
par_a = doc_recipe.make(label_string='root-11-a', parent=sect)
doc_recipe.make(text='matching text', label_string='root-11-a-3',
parent=par_a, title="Match's title")

results = views.transform_results([sect], 'this is a query')
assert results == [{
'text': 'matching text',
'label': ['root', '11', 'a', '3'],
'version': 'vvv',
'regulation': 'root',
'label_string': 'root-11-a-3',
'match_title': "Match's title",
'paragraph_title': "Match's title",
'section_title': 'Sect 111',
'title': 'Sect 111',
}]


@pytest.mark.django_db
def test_transform_title_match(monkeypatch):
"""If there's a title match with no text, we should conver to the correct
dictionary."""
monkeypatch.setattr( # __search isn't supported by sqlite
views, 'Q', Mock(return_value=Q(title__contains='matching')))
sect = doc_recipe.make(label_string='root-11', title='Sect 111',
version='vvv')
par_a = doc_recipe.make(label_string='root-11-a', parent=sect, text='',
title='matching title')
doc_recipe.make(label_string='root-11-a-3', parent=par_a,
text='inner text', title='inner title')

results = views.transform_results([sect], 'this is a query')
assert results == [{
'text': 'inner text',
'label': ['root', '11', 'a'],
'version': 'vvv',
'regulation': 'root',
'label_string': 'root-11-a',
'match_title': 'matching title',
'paragraph_title': 'inner title',
'section_title': 'Sect 111',
'title': 'Sect 111',
}]


@pytest.mark.django_db
def test_transform_no_exact_match(monkeypatch):
"""If text is searched text is broken across multiple paragraphs, we
should just graph the first text node we can find."""
monkeypatch.setattr( # __search isn't supported by sqlite
views, 'Q', Mock(return_value=Q(text=None))) # will have no results
sect = doc_recipe.make(label_string='root-11', text='', title='Sect 111',
version='vvv')
par_a = doc_recipe.make(label_string='root-11-a', parent=sect,
text='has some text', title='nonmatching title')
doc_recipe.make(label_string='root-11-a-3', parent=par_a)

results = views.transform_results([sect], 'this is a query')
assert results == [{
'text': 'has some text',
'label': ['root', '11'],
'version': 'vvv',
'regulation': 'root',
'label_string': 'root-11',
'match_title': 'Sect 111',
'paragraph_title': 'nonmatching title',
'section_title': 'Sect 111',
'title': 'Sect 111',
}]
20 changes: 14 additions & 6 deletions regcore_pgsql/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,25 @@ def transform_results(sections, search_terms):
serialization."""
final_results = []
for section in sections:
first_match = section.get_descendants(include_self=True)\
# TODO: n+1 problem; hypothetically these could all be performed via
# subqueries and annotated on the sections queryset
match_node = section.get_descendants(include_self=True)\
.filter(Q(text__search=search_terms) |
Q(title__search=search_terms))\
.first() or section
text_node = match_node.get_descendants(include_self=True)\
.exclude(text='')\
.first()

final_results.append({
'text': first_match.text,
'label': first_match.label_string.split('-'),
'version': first_match.version,
'regulation': first_match.label_string.split('-')[0],
'label_string': first_match.label_string,
'text': text_node.text if text_node else '',
'label': match_node.label_string.split('-'),
'version': section.version,
'regulation': section.label_string.split('-')[0],
'label_string': match_node.label_string,
'match_title': match_node.title,
'paragraph_title': text_node.title if text_node else '',
'section_title': section.title,
'title': section.title,
})
return final_results
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = clean,py{27,34,35,36,py}-django{18,19,110,111}-{elastic,haystack},py{27,34,35,36}-django{110,111}-pgsql,lint,docs
envlist = clean,py{27,34,35,36}-django{18,19,110,111}-{elastic,haystack},py{27,34,35,36}-django{110,111}-pgsql,lint,docs

[testenv]
deps =
Expand Down