Skip to content

Commit

Permalink
Add classifiers to search
Browse files Browse the repository at this point in the history
  • Loading branch information
di committed Apr 5, 2016
1 parent c38ebb7 commit faa229f
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 64 deletions.
28 changes: 28 additions & 0 deletions tests/common/db/classifiers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import factory
import factory.fuzzy

from warehouse.classifiers.models import Classifier

from .base import WarehouseFactory


class ClassifierFactory(WarehouseFactory):
class Meta:
model = Classifier

l2 = factory.fuzzy.FuzzyInteger(0)
l3 = factory.fuzzy.FuzzyInteger(0)
l4 = factory.fuzzy.FuzzyInteger(0)
l5 = factory.fuzzy.FuzzyInteger(0)
5 changes: 5 additions & 0 deletions tests/unit/packaging/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def test_build_search():
keywords="the, keywords, lol",
platform="any platform",
created=datetime.datetime(1956, 1, 31),
_classifiers=[
pretend.stub(classifier='Alpha'),
pretend.stub(classifier='Beta'),
],
uploader=pretend.stub(
username="some-username",
name="the-users-name",
Expand All @@ -60,5 +64,6 @@ def test_build_search():
assert obj["keywords"] == "the, keywords, lol"
assert obj["platform"] == "any platform"
assert obj["created"] == datetime.datetime(1956, 1, 31)
assert obj["classifiers"] == ['Alpha', 'Beta']
assert obj["uploader_name"] == "the-users-name"
assert obj["uploader_username"] == "some-username"
162 changes: 121 additions & 41 deletions tests/unit/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@

import pretend
import pytest
from webob.multidict import MultiDict

from warehouse import views
from warehouse.views import (
forbidden, index, httpexception_view, robotstxt, current_user_indicator,
search,
)

from ..common.db.accounts import UserFactory
from ..common.db.classifiers import ClassifierFactory
from ..common.db.packaging import (
ProjectFactory, ReleaseFactory, FileFactory,
)
from ..common.db.accounts import UserFactory


def test_httpexception_view():
Expand Down Expand Up @@ -96,19 +98,21 @@ def test_esi_current_user_indicator():
class TestSearch:

@pytest.mark.parametrize("page", [None, 1, 5])
def test_with_a_query(self, monkeypatch, page):
params = {"q": "foo bar"}
def test_with_a_query(self, monkeypatch, db_request, page):
params = MultiDict({"q": "foo bar"})
if page is not None:
params["page"] = page
suggest = pretend.stub()
query = pretend.stub(
db_request.params = params

sort = pretend.stub()
suggest = pretend.stub(
sort=pretend.call_recorder(lambda *a, **kw: sort),
)
es_query = pretend.stub(
suggest=pretend.call_recorder(lambda *a, **kw: suggest),
)
request = pretend.stub(
es=pretend.stub(
query=pretend.call_recorder(lambda *a, **kw: query),
),
params=params,
db_request.es = pretend.stub(
query=pretend.call_recorder(lambda *a, **kw: es_query)
)

page_obj = pretend.stub()
Expand All @@ -119,16 +123,18 @@ def test_with_a_query(self, monkeypatch, page):
url_maker_factory = pretend.call_recorder(lambda request: url_maker)
monkeypatch.setattr(views, "paginate_url_factory", url_maker_factory)

assert search(request) == {
assert search(db_request) == {
"page": page_obj,
"term": params.get("q"),
"order": params.get("o"),
"term": params.get("q", ''),
"order": params.get("o", ''),
"applied_filters": [],
"available_filters": [],
}
assert page_cls.calls == [
pretend.call(suggest, url_maker=url_maker, page=page or 1),
]
assert url_maker_factory.calls == [pretend.call(request)]
assert request.es.query.calls == [
assert url_maker_factory.calls == [pretend.call(db_request)]
assert db_request.es.query.calls == [
pretend.call(
"multi_match",
query="foo bar",
Expand All @@ -140,7 +146,7 @@ def test_with_a_query(self, monkeypatch, page):
],
),
]
assert query.suggest.calls == [
assert es_query.suggest.calls == [
pretend.call(
name="name_suggestion",
term={"field": "name"},
Expand All @@ -149,22 +155,21 @@ def test_with_a_query(self, monkeypatch, page):
]

@pytest.mark.parametrize("page", [None, 1, 5])
def test_with_an_ordering(self, monkeypatch, page):
params = {"q": "foo bar", "o": "-created"}
def test_with_an_ordering(self, monkeypatch, db_request, page):
params = MultiDict({"q": "foo bar", "o": "-created"})
if page is not None:
params["page"] = page
db_request.params = params

sort = pretend.stub()
suggest = pretend.stub(
sort=pretend.call_recorder(lambda *a, **kw: sort),
)
query = pretend.stub(
es_query = pretend.stub(
suggest=pretend.call_recorder(lambda *a, **kw: suggest),
)
request = pretend.stub(
es=pretend.stub(
query=pretend.call_recorder(lambda *a, **kw: query),
),
params=params,
db_request.es = pretend.stub(
query=pretend.call_recorder(lambda *a, **kw: es_query)
)

page_obj = pretend.stub()
Expand All @@ -175,16 +180,18 @@ def test_with_an_ordering(self, monkeypatch, page):
url_maker_factory = pretend.call_recorder(lambda request: url_maker)
monkeypatch.setattr(views, "paginate_url_factory", url_maker_factory)

assert search(request) == {
assert search(db_request) == {
"page": page_obj,
"term": params.get("q"),
"order": params.get("o"),
"term": params.get("q", ''),
"order": params.get("o", ''),
"applied_filters": [],
"available_filters": [],
}
assert page_cls.calls == [
pretend.call(sort, url_maker=url_maker, page=page or 1),
]
assert url_maker_factory.calls == [pretend.call(request)]
assert request.es.query.calls == [
assert url_maker_factory.calls == [pretend.call(db_request)]
assert db_request.es.query.calls == [
pretend.call(
"multi_match",
query="foo bar",
Expand All @@ -196,7 +203,7 @@ def test_with_an_ordering(self, monkeypatch, page):
],
),
]
assert query.suggest.calls == [
assert es_query.suggest.calls == [
pretend.call(
name="name_suggestion",
term={"field": "name"},
Expand All @@ -208,16 +215,87 @@ def test_with_an_ordering(self, monkeypatch, page):
]

@pytest.mark.parametrize("page", [None, 1, 5])
def test_without_a_query(self, monkeypatch, page):
params = {}
def test_with_classifiers(self, monkeypatch, db_request, page):
params = MultiDict([
("q", "foo bar"),
("c", "foo :: bar"),
("c", "fiz :: buz"),
])
if page is not None:
params["page"] = page
query = pretend.stub()
request = pretend.stub(
es=pretend.stub(query=lambda: query),
params=params,
db_request.params = params

es_query = pretend.stub(
suggest=pretend.call_recorder(lambda *a, **kw: es_query),
filter=pretend.call_recorder(lambda *a, **kw: es_query),
sort=pretend.call_recorder(lambda *a, **kw: es_query),
)
db_request.es = pretend.stub(
query=pretend.call_recorder(lambda *a, **kw: es_query)
)

classifier1 = ClassifierFactory.create(classifier="foo :: bar")
classifier2 = ClassifierFactory.create(classifier="foo :: baz")
classifier3 = ClassifierFactory.create(classifier="fiz :: buz")

page_obj = pretend.stub()
page_cls = pretend.call_recorder(lambda *a, **kw: page_obj)
monkeypatch.setattr(views, "ElasticsearchPage", page_cls)

url_maker = pretend.stub()
url_maker_factory = pretend.call_recorder(lambda request: url_maker)
monkeypatch.setattr(views, "paginate_url_factory", url_maker_factory)

assert search(db_request) == {
"page": page_obj,
"term": params.get("q", ''),
"order": params.get("o", ''),
"applied_filters": params.getall("c"),
"available_filters": [
('fiz', [classifier3.classifier]),
('foo', [
classifier1.classifier,
classifier2.classifier,
])
],
}
assert page_cls.calls == [
pretend.call(es_query, url_maker=url_maker, page=page or 1),
]
assert url_maker_factory.calls == [pretend.call(db_request)]
assert db_request.es.query.calls == [
pretend.call(
"multi_match",
query="foo bar",
fields=[
"name^2", "version", "author", "author_email",
"maintainer", "maintainer_email", "home_page", "license",
"summary", "description", "keywords", "platform",
"download_url",
],
),
]
assert es_query.suggest.calls == [
pretend.call(
name="name_suggestion",
term={"field": "name"},
text="foo bar",
),
]
assert es_query.filter.calls == [
pretend.call('terms', classifiers=['foo :: bar', 'fiz :: buz'])
]

@pytest.mark.parametrize("page", [None, 1, 5])
def test_without_a_query(self, monkeypatch, db_request, page):
params = MultiDict()
if page is not None:
params["page"] = page
db_request.params = params

es_query = pretend.stub()
db_request.es = pretend.stub(query=lambda *a, **kw: es_query)

page_obj = pretend.stub()
page_cls = pretend.call_recorder(lambda *a, **kw: page_obj)
monkeypatch.setattr(views, "ElasticsearchPage", page_cls)
Expand All @@ -226,12 +304,14 @@ def test_without_a_query(self, monkeypatch, page):
url_maker_factory = pretend.call_recorder(lambda request: url_maker)
monkeypatch.setattr(views, "paginate_url_factory", url_maker_factory)

assert search(request) == {
assert search(db_request) == {
"page": page_obj,
"term": params.get("q"),
"order": params.get("o"),
"term": params.get("q", ''),
"order": params.get("o", ''),
"applied_filters": [],
"available_filters": [],
}
assert page_cls.calls == [
pretend.call(query, url_maker=url_maker, page=page or 1),
pretend.call(es_query, url_maker=url_maker, page=page or 1),
]
assert url_maker_factory.calls == [pretend.call(request)]
assert url_maker_factory.calls == [pretend.call(db_request)]
2 changes: 2 additions & 0 deletions warehouse/packaging/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Project(DocType):
keywords = String(analyzer="snowball")
platform = String(index="not_analyzed")
created = Date()
classifiers = String(index="not_analyzed", multi=True)

uploader_name = String()
uploader_username = String()
Expand All @@ -65,6 +66,7 @@ def from_db(cls, release):
obj["keywords"] = release.keywords
obj["platform"] = release.platform
obj["created"] = release.created
obj["classifiers"] = [c.classifier for c in release._classifiers]

obj["uploader_name"] = release.uploader.name
obj["uploader_username"] = release.uploader.username
Expand Down
5 changes: 5 additions & 0 deletions warehouse/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ $(document).ready(function() {
this.form.submit();
});

// Trove classifiers
$('#classifiers :checkbox').change(function () {
this.form.submit();
});

$.timeago.settings.cutoff = 7 * 24 * 60 * 60 * 1000; // One week

// document.l10n.ready.then(function() {
Expand Down

0 comments on commit faa229f

Please sign in to comment.