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 all 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 setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="regcore",
version="4.0.0",
version="4.1.0",
license="public domain",
packages=find_packages(),
include_package_data=True,
Expand Down
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