From 1f06d1a1d8386fcf6aa09441d09b6f2d0dd4941b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 14 Sep 2021 15:26:18 -0700 Subject: [PATCH] Removes local connector --- bookwyrm/connectors/__init__.py | 2 +- bookwyrm/connectors/abstract_connector.py | 1 - bookwyrm/connectors/connector_manager.py | 16 +- bookwyrm/connectors/self_connector.py | 164 ------------------ bookwyrm/management/commands/initdb.py | 13 -- .../migrations/0097_remove_connector_local.py | 17 ++ bookwyrm/models/connector.py | 1 - bookwyrm/templates/search/book.html | 19 +- .../snippets/search_result_text.html | 22 +-- bookwyrm/views/search.py | 19 +- 10 files changed, 55 insertions(+), 219 deletions(-) delete mode 100644 bookwyrm/connectors/self_connector.py create mode 100644 bookwyrm/migrations/0097_remove_connector_local.py diff --git a/bookwyrm/connectors/__init__.py b/bookwyrm/connectors/__init__.py index 689f2701..efbdb166 100644 --- a/bookwyrm/connectors/__init__.py +++ b/bookwyrm/connectors/__init__.py @@ -3,4 +3,4 @@ from .settings import CONNECTORS from .abstract_connector import ConnectorException from .abstract_connector import get_data, get_image -from .connector_manager import search, local_search, first_search_result +from .connector_manager import search, first_search_result diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index ffacffdf..9f20a6c3 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -31,7 +31,6 @@ class AbstractMinimalConnector(ABC): "isbn_search_url", "name", "identifier", - "local", ] for field in self_fields: setattr(self, field, getattr(info, field)) diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py index 1d9588d6..6f62b59a 100644 --- a/bookwyrm/connectors/connector_manager.py +++ b/bookwyrm/connectors/connector_manager.py @@ -55,7 +55,7 @@ def search(query, min_confidence=0.1, return_first=False): # if we found anything, return it return result_set[0] - if result_set or connector.local: + if result_set: results.append( { "connector": connector, @@ -71,20 +71,6 @@ def search(query, min_confidence=0.1, return_first=False): return results -def local_search(query, min_confidence=0.1, raw=False, filters=None): - """only look at local search results""" - connector = load_connector(models.Connector.objects.get(local=True)) - return connector.search( - query, min_confidence=min_confidence, raw=raw, filters=filters - ) - - -def isbn_local_search(query, raw=False): - """only look at local search results""" - connector = load_connector(models.Connector.objects.get(local=True)) - return connector.isbn_search(query, raw=raw) - - def first_search_result(query, min_confidence=0.1): """search until you find a result that fits""" return search(query, min_confidence=min_confidence, return_first=True) or None diff --git a/bookwyrm/connectors/self_connector.py b/bookwyrm/connectors/self_connector.py deleted file mode 100644 index 8d5a7614..00000000 --- a/bookwyrm/connectors/self_connector.py +++ /dev/null @@ -1,164 +0,0 @@ -""" using a bookwyrm instance as a source of book data """ -from functools import reduce -import operator - -from django.contrib.postgres.search import SearchRank, SearchQuery -from django.db.models import OuterRef, Subquery, F, Q - -from bookwyrm import models -from .abstract_connector import AbstractConnector, SearchResult - - -class Connector(AbstractConnector): - """instantiate a connector""" - - # pylint: disable=arguments-differ - def search(self, query, min_confidence=0, raw=False, filters=None): - """search your local database""" - filters = filters or [] - if not query: - return [] - # first, try searching unqiue identifiers - results = search_identifiers(query, *filters) - if not results: - # then try searching title/author - results = search_title_author(query, min_confidence, *filters) - search_results = [] - for result in results: - if raw: - search_results.append(result) - else: - search_results.append(self.format_search_result(result)) - if len(search_results) >= 10: - break - if not raw: - search_results.sort(key=lambda r: r.confidence, reverse=True) - return search_results - - def isbn_search(self, query, raw=False): - """search your local database""" - if not query: - return [] - - filters = [{f: query} for f in ["isbn_10", "isbn_13"]] - results = models.Edition.objects.filter( - reduce(operator.or_, (Q(**f) for f in filters)) - ).distinct() - - # when there are multiple editions of the same work, pick the default. - # it would be odd for this to happen. - - default_editions = models.Edition.objects.filter( - parent_work=OuterRef("parent_work") - ).order_by("-edition_rank") - results = ( - results.annotate( - default_id=Subquery(default_editions.values("id")[:1]) - ).filter(default_id=F("id")) - or results - ) - - search_results = [] - for result in results: - if raw: - search_results.append(result) - else: - search_results.append(self.format_search_result(result)) - if len(search_results) >= 10: - break - return search_results - - def format_search_result(self, search_result): - cover = None - if search_result.cover: - cover = "%s%s" % (self.covers_url, search_result.cover) - - return SearchResult( - title=search_result.title, - key=search_result.remote_id, - author=search_result.author_text, - year=search_result.published_date.year - if search_result.published_date - else None, - connector=self, - cover=cover, - confidence=search_result.rank if hasattr(search_result, "rank") else 1, - ) - - def format_isbn_search_result(self, search_result): - return self.format_search_result(search_result) - - def is_work_data(self, data): - pass - - def get_edition_from_work_data(self, data): - pass - - def get_work_from_edition_data(self, data): - pass - - def get_authors_from_data(self, data): - return None - - def parse_isbn_search_data(self, data): - """it's already in the right format, don't even worry about it""" - return data - - def parse_search_data(self, data): - """it's already in the right format, don't even worry about it""" - return data - - def expand_book_data(self, book): - pass - - -def search_identifiers(query, *filters): - """tries remote_id, isbn; defined as dedupe fields on the model""" - # pylint: disable=W0212 - or_filters = [ - {f.name: query} - for f in models.Edition._meta.get_fields() - if hasattr(f, "deduplication_field") and f.deduplication_field - ] - results = models.Edition.objects.filter( - *filters, reduce(operator.or_, (Q(**f) for f in or_filters)) - ).distinct() - if results.count() <= 1: - return results - - # when there are multiple editions of the same work, pick the default. - # it would be odd for this to happen. - default_editions = models.Edition.objects.filter( - parent_work=OuterRef("parent_work") - ).order_by("-edition_rank") - return ( - results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter( - default_id=F("id") - ) - or results - ) - - -def search_title_author(query, min_confidence, *filters): - """searches for title and author""" - query = SearchQuery(query, config="simple") | SearchQuery(query, config="english") - results = ( - models.Edition.objects.filter(*filters, search_vector=query) - .annotate(rank=SearchRank(F("search_vector"), query)) - .filter(rank__gt=min_confidence) - .order_by("-rank") - ) - - # when there are multiple editions of the same work, pick the closest - editions_of_work = results.values("parent_work__id").values_list("parent_work__id") - - # filter out multiple editions of the same work - for work_id in set(editions_of_work): - editions = results.filter(parent_work=work_id) - default = editions.order_by("-edition_rank").first() - default_rank = default.rank if default else 0 - # if mutliple books have the top rank, pick the default edition - if default_rank == editions.first().rank: - yield default - else: - yield editions.first() diff --git a/bookwyrm/management/commands/initdb.py b/bookwyrm/management/commands/initdb.py index 71ac511a..9f2f29cd 100644 --- a/bookwyrm/management/commands/initdb.py +++ b/bookwyrm/management/commands/initdb.py @@ -73,19 +73,6 @@ def init_permissions(): def init_connectors(): """access book data sources""" - Connector.objects.create( - identifier=DOMAIN, - name="Local", - local=True, - connector_file="self_connector", - base_url="https://%s" % DOMAIN, - books_url="https://%s/book" % DOMAIN, - covers_url="https://%s/images/" % DOMAIN, - search_url="https://%s/search?q=" % DOMAIN, - isbn_search_url="https://%s/isbn/" % DOMAIN, - priority=1, - ) - Connector.objects.create( identifier="bookwyrm.social", name="BookWyrm dot Social", diff --git a/bookwyrm/migrations/0097_remove_connector_local.py b/bookwyrm/migrations/0097_remove_connector_local.py new file mode 100644 index 00000000..fc04bcce --- /dev/null +++ b/bookwyrm/migrations/0097_remove_connector_local.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.4 on 2021-09-14 22:10 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0096_merge_20210912_0044"), + ] + + operations = [ + migrations.RemoveField( + model_name="connector", + name="local", + ), + ] diff --git a/bookwyrm/models/connector.py b/bookwyrm/models/connector.py index 17ba3148..b982c0ff 100644 --- a/bookwyrm/models/connector.py +++ b/bookwyrm/models/connector.py @@ -14,7 +14,6 @@ class Connector(BookWyrmModel): identifier = models.CharField(max_length=255, unique=True) priority = models.IntegerField(default=2) name = models.CharField(max_length=255, null=True, blank=True) - local = models.BooleanField(default=False) connector_file = models.CharField(max_length=255, choices=ConnectorFiles.choices) api_key = models.CharField(max_length=255, null=True, blank=True) active = models.BooleanField(default=True) diff --git a/bookwyrm/templates/search/book.html b/bookwyrm/templates/search/book.html index 39f83732..12164bb3 100644 --- a/bookwyrm/templates/search/book.html +++ b/bookwyrm/templates/search/book.html @@ -8,7 +8,24 @@ diff --git a/bookwyrm/templates/snippets/search_result_text.html b/bookwyrm/templates/snippets/search_result_text.html index 40fa5a3d..973f1f5b 100644 --- a/bookwyrm/templates/snippets/search_result_text.html +++ b/bookwyrm/templates/snippets/search_result_text.html @@ -9,10 +9,8 @@ {{ result.title }}

@@ -26,16 +24,14 @@ {% endif %}

- {% if remote_result %} -
- {% csrf_token %} + + {% csrf_token %} - + - -
- {% endif %} + + diff --git a/bookwyrm/views/search.py b/bookwyrm/views/search.py index cdea8663..6c9593a1 100644 --- a/bookwyrm/views/search.py +++ b/bookwyrm/views/search.py @@ -10,6 +10,7 @@ from django.views import View from bookwyrm import models from bookwyrm.connectors import connector_manager +from bookwyrm.book_search import search from bookwyrm.settings import PAGE_LENGTH from bookwyrm.utils import regex from .helpers import is_api_request, privacy_filter @@ -31,9 +32,7 @@ class Search(View): if is_api_request(request): # only return local book results via json so we don't cascade - book_results = connector_manager.local_search( - query, min_confidence=min_confidence - ) + book_results = search(query, min_confidence=min_confidence) return JsonResponse([r.json() for r in book_results], safe=False) if query and not search_type: @@ -69,13 +68,13 @@ class Search(View): def book_search(query, _, min_confidence, search_remote=False): """the real business is elsewhere""" # try a local-only search - if not search_remote: - results = connector_manager.local_search(query, min_confidence=min_confidence) - if results: - # gret, we found something - return [{"results": results}], False - # if there weere no local results, or the request was for remote, search all sources - return connector_manager.search(query, min_confidence=min_confidence), True + results = [{"results": search(query, min_confidence=min_confidence)}] + if results and not search_remote: + return results, False + + # if there were no local results, or the request was for remote, search all sources + results += connector_manager.search(query, min_confidence=min_confidence) + return results, True def user_search(query, viewer, *_):