Example #1
0
def _update_query_with_dates(q: AdvancedQuery, date_data: MultiDict) \
        -> AdvancedQuery:
    filter_by = date_data['filter_by']
    if filter_by == 'all_dates':  # Nothing to do; all dates by default.
        return q
    elif filter_by == 'past_12':
        one_year_ago = date.today() - relativedelta(months=12)
        # Fix for these typing issues is coming soon!
        #  See: https://github.com/python/mypy/pull/4397
        q.date_range = DateRange(  # type: ignore
            start_date=datetime(year=one_year_ago.year,
                                month=one_year_ago.month,
                                day=1,
                                hour=0,
                                minute=0,
                                second=0,
                                tzinfo=EASTERN))
    elif filter_by == 'specific_year':
        q.date_range = DateRange(  # type: ignore
            start_date=datetime(year=date_data['year'].year,
                                month=1,
                                day=1,
                                hour=0,
                                minute=0,
                                second=0,
                                tzinfo=EASTERN),
            end_date=datetime(year=date_data['year'].year + 1,
                              month=1,
                              day=1,
                              hour=0,
                              minute=0,
                              second=0,
                              tzinfo=EASTERN),
        )
    elif filter_by == 'date_range':
        if date_data['from_date']:
            date_data['from_date'] = datetime.combine(  # type: ignore
                date_data['from_date'],
                datetime.min.time(),
                tzinfo=EASTERN)
        if date_data['to_date']:
            date_data['to_date'] = datetime.combine(  # type: ignore
                date_data['to_date'],
                datetime.min.time(),
                tzinfo=EASTERN)

        q.date_range = DateRange(  # type: ignore
            start_date=date_data['from_date'],
            end_date=date_data['to_date'],
        )

    if q.date_range:
        q.date_range.date_type = date_data['date_type']
    return q
Example #2
0
 def test_group_terms(self):
     """:meth:`._group_terms` groups terms using logical precedence."""
     query = AdvancedQuery(terms=FieldedSearchList([
         FieldedSearchTerm(operator=None, field='title', term='muon'),
         FieldedSearchTerm(operator='OR', field='title', term='gluon'),
         FieldedSearchTerm(operator='NOT', field='title', term='foo'),
         FieldedSearchTerm(operator='AND', field='title', term='boson'),
     ]))
     expected = (
         FieldedSearchTerm(operator=None, field='title', term='muon'),
         'OR',
         (
           (
             FieldedSearchTerm(operator='OR', field='title', term='gluon'),
             'NOT',
             FieldedSearchTerm(operator='NOT', field='title', term='foo')
           ),
           'AND',
           FieldedSearchTerm(operator='AND', field='title', term='boson')
         )
     )
     try:
         terms = advanced._group_terms(query)
     except AssertionError:
         self.fail('Should result in a single group')
     self.assertEqual(expected, terms)
Example #3
0
def _update_query_with_classification(q: AdvancedQuery, data: MultiDict) \
        -> AdvancedQuery:
    q.classification = ClassificationList()
    archives = [('computer_science', 'cs'), ('economics', 'econ'),
                ('eess', 'eess'), ('mathematics', 'math'),
                ('q_biology', 'q-bio'), ('q_finance', 'q-fin'),
                ('statistics', 'stat')]
    for field, archive in archives:
        if data.get(field):
            # Fix for these typing issues is coming soon!
            #  See: https://github.com/python/mypy/pull/4397
            q.classification.append(
                Classification(archive={'id': archive})  # type: ignore
            )
    if data.get('physics') and 'physics_archives' in data:
        if 'all' in data['physics_archives']:
            q.classification.append(
                Classification(group={'id': 'grp_physics'})  # type: ignore
            )
        else:
            q.classification.append(
                Classification(  # type: ignore
                    group={'id': 'grp_physics'},
                    archive={'id': data['physics_archives']}))
    return q
Example #4
0
def _update_query_with_terms(q: AdvancedQuery, terms_data: list) \
        -> AdvancedQuery:
    q.terms = FieldedSearchList([
        FieldedSearchTerm(**term)  # type: ignore
        for term in terms_data if term['term']
    ])
    return q
Example #5
0
def _update_query_with_classification(q: AdvancedQuery,
                                      data: MultiDict) -> AdvancedQuery:
    q.classification = ClassificationList()
    archives = [
        ("computer_science", "cs"),
        ("economics", "econ"),
        ("eess", "eess"),
        ("mathematics", "math"),
        ("q_biology", "q-bio"),
        ("q_finance", "q-fin"),
        ("statistics", "stat"),
    ]
    for field, archive in archives:
        if data.get(field):
            # Fix for these typing issues is coming soon!
            #  See: https://github.com/python/mypy/pull/4397
            q.classification.append(
                Classification(archive={"id": archive})  # type: ignore
            )
    if data.get("physics") and "physics_archives" in data:
        if "all" in data["physics_archives"]:
            q.classification.append(
                Classification(group={"id": "grp_physics"})  # type: ignore
            )
        else:
            q.classification.append(
                Classification(  # type: ignore
                    group={"id": "grp_physics"},
                    archive={"id": data["physics_archives"]},
                ))
    return q
Example #6
0
 def test_group_terms(self):
     """:meth:`._group_terms` groups terms using logical precedence."""
     query = AdvancedQuery(terms=FieldedSearchList([
         FieldedSearchTerm(operator=None, field="title", term="muon"),
         FieldedSearchTerm(operator="OR", field="title", term="gluon"),
         FieldedSearchTerm(operator="NOT", field="title", term="foo"),
         FieldedSearchTerm(operator="AND", field="title", term="boson"),
     ]))
     expected = (
         FieldedSearchTerm(operator=None, field="title", term="muon"),
         "OR",
         (
             (
                 FieldedSearchTerm(operator="OR",
                                   field="title",
                                   term="gluon"),
                 "NOT",
                 FieldedSearchTerm(operator="NOT",
                                   field="title",
                                   term="foo"),
             ),
             "AND",
             FieldedSearchTerm(operator="AND", field="title", term="boson"),
         ),
     )
     try:
         terms = advanced._group_terms(query)
     except AssertionError:
         self.fail("Should result in a single group")
     self.assertEqual(expected, terms)
Example #7
0
 def test_specific_year_is_selected(self):
     """Start and end dates are set, one year apart."""
     date_data = {
         'filter_by': 'specific_year',
         'year': date(year=1999, month=1, day=1)
     }
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertEqual(q.date_range.end_date.date(),
                      date(year=2000, month=1, day=1))
     self.assertEqual(q.date_range.start_date.date(),
                      date(year=1999, month=1, day=1))
Example #8
0
def _query_from_form(form: forms.AdvancedSearchForm) -> AdvancedQuery:
    """
    Generate a :class:`.AdvancedQuery` from valid :class:`.AdvancedSearchForm`.

    Parameters
    ----------
    form : :class:`.AdvancedSearchForm`
        Presumed to be filled and valid.

    Returns
    -------
    :class:`.AdvancedQuery`

    """
    q = AdvancedQuery()
    q = _update_query_with_dates(q, form.date.data)
    q = _update_query_with_terms(q, form.terms.data)
    q = _update_query_with_classification(q, form.classification.data)
    q.include_cross_list = form.classification.include_cross_list.data \
        == form.classification.INCLUDE_CROSS_LIST
    if form.include_older_versions.data:
        q.include_older_versions = True
    order = form.order.data
    if order and order != 'None':
        q.order = order
    q.hide_abstracts = form.abstracts.data == form.HIDE_ABSTRACTS
    return q
Example #9
0
 def test_specific_year_is_selected(self):
     """Start and end dates are set, one year apart."""
     date_data = {
         "filter_by": "specific_year",
         "year": date(year=1999, month=1, day=1),
         "date_type": "submitted_date",
     }
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertEqual(q.date_range.end_date.date(),
                      date(year=2000, month=1, day=1))
     self.assertEqual(q.date_range.start_date.date(),
                      date(year=1999, month=1, day=1))
Example #10
0
 def test_date_range_is_selected(self):
     """Start and end dates are set based on selection."""
     from_date = date(year=1999, month=7, day=3)
     to_date = date(year=1999, month=8, day=5)
     date_data = {
         'filter_by': 'date_range',
         'from_date': from_date,
         'to_date': to_date,
     }
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertEqual(q.date_range.end_date.date(), to_date)
     self.assertEqual(q.date_range.start_date.date(), from_date)
Example #11
0
 def test_date_range_is_selected(self):
     """Start and end dates are set based on selection."""
     from_date = date(year=1999, month=7, day=3)
     to_date = date(year=1999, month=8, day=5)
     date_data = {
         "filter_by": "date_range",
         "from_date": from_date,
         "to_date": to_date,
         "date_type": "submitted_date",
     }
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertEqual(q.date_range.end_date.date(), to_date)
     self.assertEqual(q.date_range.start_date.date(), from_date)
Example #12
0
    def test_advanced_query(self, mock_Elasticsearch, mock_Search):
        """:class:`.index.search` supports :class:`AdvancedQuery`."""
        mock_results = mock.MagicMock()
        mock_results.__getitem__.return_value = {'total': 53}
        rdata = dict(authors=[{'full_name': 'N. Ame'}],
                     owners=[{'full_name': 'N. Ame'}],
                     submitter={'full_name': 'N. Ame'},
                     paper_id='1234.56789')
        mock_result = mock.MagicMock(_d_=rdata, **rdata)
        mock_result.meta.score = 1
        mock_results.__iter__.return_value = [mock_result]
        mock_Search.execute.return_value = mock_results

        # Support the chaining API for py-ES.
        mock_Search.return_value = mock_Search
        mock_Search.filter.return_value = mock_Search
        mock_Search.highlight.return_value = mock_Search
        mock_Search.highlight_options.return_value = mock_Search
        mock_Search.query.return_value = mock_Search
        mock_Search.sort.return_value = mock_Search
        mock_Search.__getitem__.return_value = mock_Search

        query = AdvancedQuery(
            order='relevance',
            size=10,
            date_range=DateRange(
                start_date=datetime.now() - timedelta(days=5),
                end_date=datetime.now()
            ),
            classification=ClassificationList([
                Classification(
                    group={'id': 'physics'},
                    archive={'id': 'physics'},
                    category={'id': 'hep-th'}
                )
            ]),
            terms=FieldedSearchList([
                FieldedSearchTerm(operator='AND', field='title', term='foo'),
                FieldedSearchTerm(operator='AND', field='author', term='joe'),
                FieldedSearchTerm(operator='OR', field='abstract', term='hmm'),
                FieldedSearchTerm(operator='NOT', field='comments', term='eh'),
                FieldedSearchTerm(operator='AND', field='journal_ref',
                                  term='jref (1999) 1:2-3'),
                FieldedSearchTerm(operator='AND', field='acm_class',
                                  term='abc123'),
                FieldedSearchTerm(operator='AND', field='msc_class',
                                  term='abc123'),
                FieldedSearchTerm(operator='OR', field='report_num',
                                  term='abc123'),
                FieldedSearchTerm(operator='OR', field='doi',
                                  term='10.01234/56789'),
                FieldedSearchTerm(operator='OR', field='orcid',
                                  term='0000-0000-0000-0000'),
                FieldedSearchTerm(operator='OR', field='author_id',
                                  term='Bloggs_J'),
            ])
        )
        document_set = index.SearchSession.search(query)
        # self.assertIsInstance(document_set, DocumentSet)
        self.assertEqual(document_set['metadata']['start'], 0)
        self.assertEqual(document_set['metadata']['total'], 53)
        self.assertEqual(document_set['metadata']['current_page'], 1)
        self.assertEqual(document_set['metadata']['total_pages'], 6)
        self.assertEqual(document_set['metadata']['size'], 10)
        self.assertEqual(len(document_set['results']), 1)
Example #13
0
 def test_all_dates_is_selected(self):
     """Query does not select on date."""
     date_data = {"filter_by": "all_dates", "date_type": "submitted_date"}
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertIsNone(q.date_range)
Example #14
0
    def test_advanced_query(self, mock_Elasticsearch, mock_Search):
        """:class:`.index.search` supports :class:`AdvancedQuery`."""
        mock_results = mock.MagicMock()
        mock_results.__getitem__.return_value = {"total": 53}
        rdata = mock_rdata()
        mock_result = mock.MagicMock(_d_=rdata, **rdata)
        mock_result.meta.score = 1
        mock_results.__iter__.return_value = [mock_result]
        mock_Search.execute.return_value = mock_results

        # Support the chaining API for py-ES.
        mock_Search.return_value = mock_Search
        mock_Search.filter.return_value = mock_Search
        mock_Search.highlight.return_value = mock_Search
        mock_Search.highlight_options.return_value = mock_Search
        mock_Search.query.return_value = mock_Search
        mock_Search.sort.return_value = mock_Search
        mock_Search.__getitem__.return_value = mock_Search

        query = AdvancedQuery(
            order="relevance",
            size=10,
            date_range=DateRange(
                start_date=datetime.now() - timedelta(days=5),
                end_date=datetime.now(),
            ),
            classification=ClassificationList([
                Classification(
                    group={"id": "physics"},
                    archive={"id": "physics"},
                    category={"id": "hep-th"},
                )
            ]),
            terms=FieldedSearchList([
                FieldedSearchTerm(operator="AND", field="title", term="foo"),
                FieldedSearchTerm(operator="AND", field="author", term="joe"),
                FieldedSearchTerm(operator="OR", field="abstract", term="hmm"),
                FieldedSearchTerm(operator="NOT", field="comments", term="eh"),
                FieldedSearchTerm(
                    operator="AND",
                    field="journal_ref",
                    term="jref (1999) 1:2-3",
                ),
                FieldedSearchTerm(operator="AND",
                                  field="acm_class",
                                  term="abc123"),
                FieldedSearchTerm(operator="AND",
                                  field="msc_class",
                                  term="abc123"),
                FieldedSearchTerm(operator="OR",
                                  field="report_num",
                                  term="abc123"),
                FieldedSearchTerm(operator="OR",
                                  field="doi",
                                  term="10.01234/56789"),
                FieldedSearchTerm(
                    operator="OR",
                    field="orcid",
                    term="0000-0000-0000-0000",
                ),
                FieldedSearchTerm(operator="OR",
                                  field="author_id",
                                  term="Bloggs_J"),
            ]),
        )
        document_set = index.SearchSession.search(query)
        # self.assertIsInstance(document_set, DocumentSet)
        self.assertEqual(document_set["metadata"]["start"], 0)
        self.assertEqual(document_set["metadata"]["total_results"], 53)
        self.assertEqual(document_set["metadata"]["current_page"], 1)
        self.assertEqual(document_set["metadata"]["total_pages"], 6)
        self.assertEqual(document_set["metadata"]["size"], 10)
        self.assertEqual(len(document_set["results"]), 1)
Example #15
0
def _update_query_with_dates(q: AdvancedQuery,
                             date_data: MultiDict) -> AdvancedQuery:
    filter_by = date_data["filter_by"]
    if filter_by == "all_dates":  # Nothing to do; all dates by default.
        return q
    elif filter_by == "past_12":
        one_year_ago = date.today() - relativedelta(months=12)
        # Fix for these typing issues is coming soon!
        #  See: https://github.com/python/mypy/pull/4397
        q.date_range = DateRange(  # type: ignore
            start_date=datetime(
                year=one_year_ago.year,
                month=one_year_ago.month,
                day=1,
                hour=0,
                minute=0,
                second=0,
                tzinfo=consts.EASTERN,
            ))
    elif filter_by == "specific_year":
        q.date_range = DateRange(  # type: ignore
            start_date=datetime(
                year=date_data["year"].year,
                month=1,
                day=1,
                hour=0,
                minute=0,
                second=0,
                tzinfo=consts.EASTERN,
            ),
            end_date=datetime(
                year=date_data["year"].year + 1,
                month=1,
                day=1,
                hour=0,
                minute=0,
                second=0,
                tzinfo=consts.EASTERN,
            ),
        )
    elif filter_by == "date_range":
        if date_data["from_date"]:
            date_data["from_date"] = datetime.combine(  # type: ignore
                date_data["from_date"],
                datetime.min.time(),
                tzinfo=consts.EASTERN,
            )
        if date_data["to_date"]:
            date_data["to_date"] = datetime.combine(  # type: ignore
                date_data["to_date"],
                datetime.min.time(),
                tzinfo=consts.EASTERN,
            )

        q.date_range = DateRange(  # type: ignore
            start_date=date_data["from_date"],
            end_date=date_data["to_date"])

    if q.date_range:
        q.date_range.date_type = date_data["date_type"]
    return q
Example #16
0
 def test_all_dates_is_selected(self):
     """Query does not select on date."""
     date_data = {'filter_by': 'all_dates'}
     q = advanced._update_query_with_dates(AdvancedQuery(), date_data)
     self.assertIsInstance(q, AdvancedQuery)
     self.assertIsNone(q.date_range)