From 9aada80c055856919d3cda6effc9b4b2488f89b8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 29 Mar 2020 17:40:51 -0700 Subject: [PATCH] Use timezone dates Fixes #114 --- fedireads/connectors/abstract_connector.py | 10 +++++++ fedireads/connectors/fedireads_connector.py | 29 +++++++------------ fedireads/connectors/openlibrary.py | 21 ++------------ .../migrations/0025_auto_20200330_0037.py | 24 +++++++++++++++ fedireads/models/book.py | 4 +-- fedireads/models/status.py | 4 +-- fedireads/routine_book_tasks.py | 5 ++-- fedireads/views.py | 6 +++- requirements.txt | 1 + 9 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 fedireads/migrations/0025_auto_20200330_0037.py diff --git a/fedireads/connectors/abstract_connector.py b/fedireads/connectors/abstract_connector.py index daccb6098..e9153a246 100644 --- a/fedireads/connectors/abstract_connector.py +++ b/fedireads/connectors/abstract_connector.py @@ -1,5 +1,7 @@ ''' functionality outline for a book data connector ''' from abc import ABC, abstractmethod +from dateutil import parser +import pytz from fedireads import models @@ -80,6 +82,14 @@ def has_attr(obj, key): return False +def get_date(date_string): + ''' helper function to try to interpret dates ''' + try: + return pytz.utc.localize(parser.parse(date_string)) + except ValueError: + return None + + class SearchResult(object): ''' standardized search result object ''' def __init__(self, title, key, author, year, raw_data): diff --git a/fedireads/connectors/fedireads_connector.py b/fedireads/connectors/fedireads_connector.py index 8fc6e2708..ba482094e 100644 --- a/fedireads/connectors/fedireads_connector.py +++ b/fedireads/connectors/fedireads_connector.py @@ -1,11 +1,11 @@ ''' using another fedireads instance as a source of book data ''' -from datetime import datetime from django.core.exceptions import ObjectDoesNotExist from django.core.files.base import ContentFile import requests from fedireads import models -from .abstract_connector import AbstractConnector, update_from_mappings +from .abstract_connector import AbstractConnector +from .abstract_connector import update_from_mappings, get_date class Connector(AbstractConnector): @@ -81,7 +81,7 @@ class Connector(AbstractConnector): book.authors.add(self.get_or_create_author(author_id)) if book.sync_cover and data.get('covers') and len(data['covers']): - book.cover.save(*self.get_cover(data['covers'][0]), save=True) + book.cover.save(*get_cover(data['covers'][0]), save=True) return book @@ -111,19 +111,12 @@ class Connector(AbstractConnector): return author - def get_cover(self, cover_url): - ''' ask openlibrary for the cover ''' - image_name = cover_url.split('/')[-1] - response = requests.get(cover_url) - if not response.ok: - response.raise_for_status() - image_content = ContentFile(response.content) - return [image_name, image_content] +def get_cover(cover_url): + ''' ask openlibrary for the cover ''' + image_name = cover_url.split('/')[-1] + response = requests.get(cover_url) + if not response.ok: + response.raise_for_status() + image_content = ContentFile(response.content) + return [image_name, image_content] - -def get_date(date_string): - ''' helper function to try to interpret dates ''' - try: - datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S") - except ValueError: - return False diff --git a/fedireads/connectors/openlibrary.py b/fedireads/connectors/openlibrary.py index fb4f57612..979834be1 100644 --- a/fedireads/connectors/openlibrary.py +++ b/fedireads/connectors/openlibrary.py @@ -1,13 +1,12 @@ ''' openlibrary data connector ''' -from datetime import datetime from django.core.exceptions import ObjectDoesNotExist from django.core.files.base import ContentFile import re import requests from fedireads import models -from .abstract_connector import AbstractConnector, SearchResult, \ - update_from_mappings +from .abstract_connector import AbstractConnector, SearchResult +from .abstract_connector import update_from_mappings, get_date class Connector(AbstractConnector): @@ -58,7 +57,7 @@ class Connector(AbstractConnector): except ObjectDoesNotExist: # no book was found, so we start creating a new one book = model(openlibrary_key=olkey) - self.update_book(book) + return self.update_book(book) def update_book(self, book): @@ -156,20 +155,6 @@ class Connector(AbstractConnector): return [image_name, image_content] -def get_date(date_string): - ''' helper function to try to interpret dates ''' - formats = [ - '%B %Y', - '%Y', - ] - for date_format in formats: - try: - return datetime.strptime(date_string, date_format) - except ValueError: - pass - return None - - def get_description(description_blob): ''' descriptions can be a string or a dict ''' if isinstance(description_blob, dict): diff --git a/fedireads/migrations/0025_auto_20200330_0037.py b/fedireads/migrations/0025_auto_20200330_0037.py new file mode 100644 index 000000000..2238ef6c7 --- /dev/null +++ b/fedireads/migrations/0025_auto_20200330_0037.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.3 on 2020-03-30 00:37 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('fedireads', '0024_federatedserver_application_version'), + ] + + operations = [ + migrations.AlterField( + model_name='book', + name='last_sync_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name='status', + name='published_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + ] diff --git a/fedireads/models/book.py b/fedireads/models/book.py index f6f6ea046..57cc44c8d 100644 --- a/fedireads/models/book.py +++ b/fedireads/models/book.py @@ -1,5 +1,5 @@ ''' database schema for books and shelves ''' -from datetime import datetime +from django.utils import timezone from django.db import models from model_utils.managers import InheritanceManager from uuid import uuid4 @@ -57,7 +57,7 @@ class Book(FedireadsModel): source_url = models.CharField(max_length=255, unique=True, null=True) sync = models.BooleanField(default=True) sync_cover = models.BooleanField(default=True) - last_sync_date = models.DateTimeField(default=datetime.now) + last_sync_date = models.DateTimeField(default=timezone.now) connector = models.ForeignKey( 'Connector', on_delete=models.PROTECT, null=True) diff --git a/fedireads/models/status.py b/fedireads/models/status.py index cc2ae0f3b..0bdec6d7b 100644 --- a/fedireads/models/status.py +++ b/fedireads/models/status.py @@ -1,5 +1,5 @@ ''' models for storing different kinds of Activities ''' -from datetime import datetime +from django.utils import timezone from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from model_utils.managers import InheritanceManager @@ -21,7 +21,7 @@ class Status(FedireadsModel): privacy = models.CharField(max_length=255, default='public') sensitive = models.BooleanField(default=False) # the created date can't be this, because of receiving federated posts - published_date = models.DateTimeField(default=datetime.now) + published_date = models.DateTimeField(default=timezone.now) favorites = models.ManyToManyField( 'User', symmetrical=False, diff --git a/fedireads/routine_book_tasks.py b/fedireads/routine_book_tasks.py index ac710be76..b35ccf4d5 100644 --- a/fedireads/routine_book_tasks.py +++ b/fedireads/routine_book_tasks.py @@ -1,11 +1,12 @@ ''' Routine tasks for keeping your library tidy ''' -from datetime import datetime, timedelta +from datetime import timedelta +from django.utils import timezone from fedireads import books_manager from fedireads import models def sync_book_data(): ''' update books with any changes to their canonical source ''' - expiry = datetime.now() - timedelta(days=1) + expiry = timezone.now() - timedelta(days=1) books = models.Book.objects.filter( sync=True, last_sync_date__lte=expiry diff --git a/fedireads/views.py b/fedireads/views.py index 0d900afd2..ec71f8e05 100644 --- a/fedireads/views.py +++ b/fedireads/views.py @@ -352,7 +352,11 @@ def book_page(request, book_identifier, tab='friends'): ) try: - shelf = models.Shelf.objects.get(user=request.user, book=book) + # TODO: books can be on multiple shelves + shelf = models.Shelf.objects.filter( + user=request.user, + book=book + ).first() except models.Shelf.DoesNotExist: shelf = None diff --git a/requirements.txt b/requirements.txt index 0375a27de..b8836226b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ environs==7.2.0 Pillow==7.0.0 psycopg2==2.8.4 pycryptodome==3.9.4 +python-dateutil==2.8.1 requests==2.22.0