forked from mirrors/bookwyrm
Merge pull request #425 from mouse-reeve/import-error
Fixes goodreads import failing on every book
This commit is contained in:
commit
26c0880fe4
6 changed files with 78 additions and 21 deletions
|
@ -168,7 +168,7 @@ class AbstractConnector(AbstractMinimalConnector):
|
||||||
''' every work needs at least one edition '''
|
''' every work needs at least one edition '''
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_work_from_edition_date(self, data):
|
def get_work_from_edition_data(self, data):
|
||||||
''' every edition needs a work '''
|
''' every edition needs a work '''
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -228,6 +228,7 @@ class SearchResult:
|
||||||
key: str
|
key: str
|
||||||
author: str
|
author: str
|
||||||
year: str
|
year: str
|
||||||
|
connector: object
|
||||||
confidence: int = 1
|
confidence: int = 1
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -13,4 +13,5 @@ class Connector(AbstractMinimalConnector):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def format_search_result(self, search_result):
|
def format_search_result(self, search_result):
|
||||||
|
search_result['connector'] = self
|
||||||
return SearchResult(**search_result)
|
return SearchResult(**search_result)
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Connector(AbstractConnector):
|
||||||
return pick_default_edition(data['entries'])
|
return pick_default_edition(data['entries'])
|
||||||
|
|
||||||
|
|
||||||
def get_work_from_edition_date(self, data):
|
def get_work_from_edition_data(self, data):
|
||||||
try:
|
try:
|
||||||
key = data['works'][0]['key']
|
key = data['works'][0]['key']
|
||||||
except (IndexError, KeyError):
|
except (IndexError, KeyError):
|
||||||
|
@ -123,6 +123,7 @@ class Connector(AbstractConnector):
|
||||||
title=search_result.get('title'),
|
title=search_result.get('title'),
|
||||||
key=key,
|
key=key,
|
||||||
author=', '.join(author),
|
author=', '.join(author),
|
||||||
|
connector=self,
|
||||||
year=search_result.get('first_publish_year'),
|
year=search_result.get('first_publish_year'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -51,28 +51,23 @@ class Connector(AbstractConnector):
|
||||||
author=search_result.author_text,
|
author=search_result.author_text,
|
||||||
year=search_result.published_date.year if \
|
year=search_result.published_date.year if \
|
||||||
search_result.published_date else None,
|
search_result.published_date else None,
|
||||||
|
connector=self,
|
||||||
confidence=search_result.rank,
|
confidence=search_result.rank,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_remote_id_from_data(self, data):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def is_work_data(self, data):
|
def is_work_data(self, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_edition_from_work_data(self, data):
|
def get_edition_from_work_data(self, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_work_from_edition_date(self, data):
|
def get_work_from_edition_data(self, data):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_authors_from_data(self, data):
|
def get_authors_from_data(self, data):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_cover_from_data(self, data):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def parse_search_data(self, data):
|
def parse_search_data(self, data):
|
||||||
''' it's already in the right format, don't even worry about it '''
|
''' it's already in the right format, don't even worry about it '''
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -76,7 +76,7 @@ class ImportItem(models.Model):
|
||||||
)
|
)
|
||||||
if search_result:
|
if search_result:
|
||||||
# raises ConnectorException
|
# raises ConnectorException
|
||||||
return books_manager.get_or_create_book(search_result.key)
|
return search_result.connector.get_or_create_book(search_result.key)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ class ImportItem(models.Model):
|
||||||
)
|
)
|
||||||
if search_result:
|
if search_result:
|
||||||
# raises ConnectorException
|
# raises ConnectorException
|
||||||
return books_manager.get_or_create_book(search_result.key)
|
return search_result.connector.get_or_create_book(search_result.key)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
''' testing models '''
|
''' testing models '''
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
import responses
|
||||||
|
|
||||||
from bookwyrm import models
|
from bookwyrm import books_manager, models
|
||||||
|
from bookwyrm.connectors.abstract_connector import SearchResult
|
||||||
|
|
||||||
|
|
||||||
class ImportJob(TestCase):
|
class ImportJob(TestCase):
|
||||||
|
@ -54,11 +60,11 @@ class ImportJob(TestCase):
|
||||||
user = models.User.objects.create_user(
|
user = models.User.objects.create_user(
|
||||||
'mouse', 'mouse@mouse.mouse', 'mouseword', local=True)
|
'mouse', 'mouse@mouse.mouse', 'mouseword', local=True)
|
||||||
job = models.ImportJob.objects.create(user=user)
|
job = models.ImportJob.objects.create(user=user)
|
||||||
models.ImportItem.objects.create(
|
self.item_1 = models.ImportItem.objects.create(
|
||||||
job=job, index=1, data=currently_reading_data)
|
job=job, index=1, data=currently_reading_data)
|
||||||
models.ImportItem.objects.create(
|
self.item_2 = models.ImportItem.objects.create(
|
||||||
job=job, index=2, data=read_data)
|
job=job, index=2, data=read_data)
|
||||||
models.ImportItem.objects.create(
|
self.item_3 = models.ImportItem.objects.create(
|
||||||
job=job, index=3, data=unknown_read_data)
|
job=job, index=3, data=unknown_read_data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,8 +78,7 @@ class ImportJob(TestCase):
|
||||||
def test_shelf(self):
|
def test_shelf(self):
|
||||||
''' converts to the local shelf typology '''
|
''' converts to the local shelf typology '''
|
||||||
expected = 'reading'
|
expected = 'reading'
|
||||||
item = models.ImportItem.objects.get(index=1)
|
self.assertEqual(self.item_1.shelf, expected)
|
||||||
self.assertEqual(item.shelf, expected)
|
|
||||||
|
|
||||||
|
|
||||||
def test_date_added(self):
|
def test_date_added(self):
|
||||||
|
@ -91,21 +96,75 @@ class ImportJob(TestCase):
|
||||||
|
|
||||||
|
|
||||||
def test_currently_reading_reads(self):
|
def test_currently_reading_reads(self):
|
||||||
|
''' infer currently reading dates where available '''
|
||||||
expected = [models.ReadThrough(
|
expected = [models.ReadThrough(
|
||||||
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))]
|
start_date=datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc)
|
||||||
|
)]
|
||||||
actual = models.ImportItem.objects.get(index=1)
|
actual = models.ImportItem.objects.get(index=1)
|
||||||
self.assertEqual(actual.reads[0].start_date, expected[0].start_date)
|
self.assertEqual(actual.reads[0].start_date, expected[0].start_date)
|
||||||
self.assertEqual(actual.reads[0].finish_date, expected[0].finish_date)
|
self.assertEqual(actual.reads[0].finish_date, expected[0].finish_date)
|
||||||
|
|
||||||
def test_read_reads(self):
|
def test_read_reads(self):
|
||||||
actual = models.ImportItem.objects.get(index=2)
|
''' infer read dates where available '''
|
||||||
self.assertEqual(actual.reads[0].start_date, datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))
|
actual = self.item_2
|
||||||
self.assertEqual(actual.reads[0].finish_date, datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc))
|
self.assertEqual(
|
||||||
|
actual.reads[0].start_date,
|
||||||
|
datetime.datetime(2019, 4, 9, 0, 0, tzinfo=timezone.utc))
|
||||||
|
self.assertEqual(
|
||||||
|
actual.reads[0].finish_date,
|
||||||
|
datetime.datetime(2019, 4, 12, 0, 0, tzinfo=timezone.utc))
|
||||||
|
|
||||||
def test_unread_reads(self):
|
def test_unread_reads(self):
|
||||||
|
''' handle books with no read dates '''
|
||||||
expected = []
|
expected = []
|
||||||
actual = models.ImportItem.objects.get(index=3)
|
actual = models.ImportItem.objects.get(index=3)
|
||||||
self.assertEqual(actual.reads, expected)
|
self.assertEqual(actual.reads, expected)
|
||||||
|
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_book_from_isbn(self):
|
||||||
|
''' search and load books by isbn (9780356506999) '''
|
||||||
|
connector_info = models.Connector.objects.create(
|
||||||
|
identifier='openlibrary.org',
|
||||||
|
name='OpenLibrary',
|
||||||
|
connector_file='openlibrary',
|
||||||
|
base_url='https://openlibrary.org',
|
||||||
|
books_url='https://openlibrary.org',
|
||||||
|
covers_url='https://covers.openlibrary.org',
|
||||||
|
search_url='https://openlibrary.org/search?q=',
|
||||||
|
priority=3,
|
||||||
|
)
|
||||||
|
connector = books_manager.load_connector(connector_info)
|
||||||
|
result = SearchResult(
|
||||||
|
title='Test Result',
|
||||||
|
key='https://openlibrary.org/works/OL1234W',
|
||||||
|
author='An Author',
|
||||||
|
year='1980',
|
||||||
|
connector=connector,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
datafile = pathlib.Path(__file__).parent.joinpath(
|
||||||
|
'../data/ol_edition.json')
|
||||||
|
bookdata = json.loads(datafile.read_bytes())
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
'https://openlibrary.org/works/OL1234W',
|
||||||
|
json=bookdata,
|
||||||
|
status=200)
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
'https://openlibrary.org//works/OL15832982W',
|
||||||
|
json=bookdata,
|
||||||
|
status=200)
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
'https://openlibrary.org//authors/OL382982A.json',
|
||||||
|
json={'name': 'test author'},
|
||||||
|
status=200)
|
||||||
|
|
||||||
|
with patch('bookwyrm.books_manager.first_search_result') as search:
|
||||||
|
search.return_value = result
|
||||||
|
book = self.item_1.get_book_from_isbn()
|
||||||
|
|
||||||
|
self.assertEqual(book.title, 'Sabriel')
|
||||||
|
|
Loading…
Reference in a new issue