Fixed multiple problems related to migration to django-preferences.

This commit is contained in:
Tiberiu Chibici 2018-12-29 23:16:04 +02:00
parent 10fced57e1
commit 2c93e50406
12 changed files with 77 additions and 40 deletions

View File

@ -153,17 +153,23 @@ _DEFAULT_DATABASE = {
CONFIG_ERRORS = [] CONFIG_ERRORS = []
CONFIG_WARNINGS = [] CONFIG_WARNINGS = []
# These are just to make inspector happy, they will be set in the load_config_ini() method
DEBUG = None
SECRET_KEY = None
DATABASES = None
LOG_LEVEL = None
# #
# Config parser options # Config parser options
# #
CFG_PARSER_OPTS = { CFG_PARSER_OPTS = {
'PROJECT_ROOT' : PROJECT_ROOT, 'PROJECT_ROOT': PROJECT_ROOT,
'BASE_DIR' : BASE_DIR, 'BASE_DIR': BASE_DIR,
'CONFIG_DIR' : CONFIG_DIR, 'CONFIG_DIR': CONFIG_DIR,
'DATA_DIR' : DATA_DIR, 'DATA_DIR': DATA_DIR,
} }
# #
# Load globals from config.ini # Load globals from config.ini
# #
@ -225,7 +231,7 @@ def load_config_ini():
logging.info(f"Using data directory {DATA_DIR}") logging.info(f"Using data directory {DATA_DIR}")
except OSError as e: except OSError as e:
print(f'CRITICAL ERROR! Cannot create data directory {DATA_DIR}! {e}', file=sys.stderr) print(f'CRITICAL ERROR! Cannot create data directory {DATA_DIR}! {e}', file=sys.stderr)
return; return
cfg = ConfigParser(allow_no_value=True, interpolation=ExtendedInterpolatorWithEnv()) cfg = ConfigParser(allow_no_value=True, interpolation=ExtendedInterpolatorWithEnv())
@ -252,7 +258,8 @@ def load_config_ini():
} }
if cfg.has_option('global', 'DatabaseURL'): if cfg.has_option('global', 'DatabaseURL'):
DATABASES['default'] = dj_database_url.parse(cfg.get('global', 'DatabaseURL', vars=CFG_PARSER_OPTS), conn_max_age=600) DATABASES['default'] = dj_database_url.parse(cfg.get('global', 'DatabaseURL', vars=CFG_PARSER_OPTS),
conn_max_age=600)
else: else:
DATABASES['default'] = { DATABASES['default'] = {

View File

@ -29,6 +29,13 @@ class AppConfig(object):
else: else:
super().__setattr__(key, value) super().__setattr__(key, value)
def for_sub(self, subscription, pref: str):
value = getattr(subscription, pref)
if value is None:
value = subscription.user.preferences[pref]
return value
global_prefs = global_preferences_registry.manager() global_prefs = global_preferences_registry.manager()
appconfig = AppConfig(global_prefs) appconfig = AppConfig(global_prefs)

View File

@ -0,0 +1,25 @@
# Generated by Django 2.1.2 on 2018-12-29 20:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('YtManagerApp', '0007_auto_20181029_1638'),
]
operations = [
migrations.RemoveField(
model_name='usersettings',
name='user',
),
migrations.RenameField(
model_name='subscription',
old_name='delete_after_watched',
new_name='automatically_delete_watched',
),
migrations.DeleteModel(
name='UserSettings',
),
]

View File

@ -116,7 +116,7 @@ class Subscription(models.Model):
null=True, blank=True, null=True, blank=True,
max_length=128, max_length=128,
choices=VIDEO_ORDER_CHOICES) choices=VIDEO_ORDER_CHOICES)
delete_after_watched = models.BooleanField(null=True, blank=True) automatically_delete_watched = models.BooleanField(null=True, blank=True)
def __str__(self): def __str__(self):
return self.name return self.name
@ -161,18 +161,6 @@ class Subscription(models.Model):
def delete_subscription(self, keep_downloaded_videos: bool): def delete_subscription(self, keep_downloaded_videos: bool):
self.delete() self.delete()
def get_overloads_dict(self) -> dict:
d = {}
if self.auto_download is not None:
d['AutoDownload'] = self.auto_download
if self.download_limit is not None:
d['DownloadSubscriptionLimit'] = self.download_limit
if self.download_order is not None:
d['DownloadOrder'] = self.download_order
if self.delete_after_watched is not None:
d['DeleteWatched'] = self.delete_after_watched
return d
class Video(models.Model): class Video(models.Model):
video_id = models.TextField(null=False) video_id = models.TextField(null=False)
@ -209,11 +197,11 @@ class Video(models.Model):
self.watched = True self.watched = True
self.save() self.save()
if self.downloaded_path is not None: if self.downloaded_path is not None:
from YtManagerApp.appconfig import settings from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.management.jobs.delete_video import schedule_delete_video from YtManagerApp.management.jobs.delete_video import schedule_delete_video
from YtManagerApp.management.jobs.synchronize import schedule_synchronize_now_subscription from YtManagerApp.management.jobs.synchronize import schedule_synchronize_now_subscription
if settings.getboolean_sub(self.subscription, 'user', 'DeleteWatched'): if appconfig.for_sub(self.subscription, 'automatically_delete_watched'):
schedule_delete_video(self) schedule_delete_video(self)
schedule_synchronize_now_subscription(self.subscription) schedule_synchronize_now_subscription(self.subscription)
@ -233,13 +221,13 @@ class Video(models.Model):
def delete_files(self): def delete_files(self):
if self.downloaded_path is not None: if self.downloaded_path is not None:
from YtManagerApp.management.jobs.delete_video import schedule_delete_video from YtManagerApp.management.jobs.delete_video import schedule_delete_video
from YtManagerApp.appconfig import settings from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.management.jobs.synchronize import schedule_synchronize_now_subscription from YtManagerApp.management.jobs.synchronize import schedule_synchronize_now_subscription
schedule_delete_video(self) schedule_delete_video(self)
# Mark watched? # Mark watched?
if settings.getboolean_sub(self, 'user', 'MarkDeletedAsWatched'): if appconfig.mark_deleted_as_watched:
self.watched = True self.watched = True
schedule_synchronize_now_subscription(self.subscription) schedule_synchronize_now_subscription(self.subscription)

View File

@ -3,7 +3,7 @@
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block stylesheets %} {% block stylesheets %}
<link rel="stylesheet" href="{% static 'YtManagerApp/import/jstree/dist/themes/default/style.min.js' %}" /> <link rel="stylesheet" href="{% static 'YtManagerApp/import/jstree/dist/themes/default/style.min.css' %}" />
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}

View File

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@ -1,9 +1,9 @@
def first_non_null(*iterable): def first_non_null(*iterable):
''' """
Returns the first element from the iterable which is not None. Returns the first element from the iterable which is not None.
If all the elements are 'None', 'None' is returned. If all the elements are 'None', 'None' is returned.
:param iterable: Iterable containing list of elements. :param iterable: Iterable containing list of elements.
:return: First non-null element, or None if all elements are 'None'. :return: First non-null element, or None if all elements are 'None'.
''' """
return next((item for item in iterable if item is not None), None) return next((item for item in iterable if item is not None), None)

View File

@ -1,4 +1,4 @@
from typing import Iterable from typing import Iterable, Optional
from xml.etree import ElementTree from xml.etree import ElementTree
import re import re
@ -12,7 +12,7 @@ class SubFileParser(object):
def probe(self, file_handle) -> bool: def probe(self, file_handle) -> bool:
""" """
Tests if file matches file format. Tests if file matches file format.
:param file: File path :param file_handle: File handle
:return: True if file matches, false otherwise :return: True if file matches, false otherwise
""" """
return False return False
@ -20,7 +20,7 @@ class SubFileParser(object):
def parse(self, file_handle) -> Iterable[str]: def parse(self, file_handle) -> Iterable[str]:
""" """
Parses file and returns a list of subscription URLs. Parses file and returns a list of subscription URLs.
:param file: :param file_handle:
:return: :return:
""" """
return [] return []
@ -63,7 +63,7 @@ class OPMLParser(SubFileParser):
""" """
def __init__(self): def __init__(self):
self.__cached_file = None self.__cached_file = None
self.__cached_tree: ElementTree.ElementTree = None self.__cached_tree: Optional[ElementTree.ElementTree] = None
def __parse(self, file_handle): def __parse(self, file_handle):
if file_handle == self.__cached_file: if file_handle == self.__cached_file:

View File

@ -7,8 +7,8 @@ class YoutubeAPI(YouTube):
@staticmethod @staticmethod
def build_public() -> 'YoutubeAPI': def build_public() -> 'YoutubeAPI':
from YtManagerApp.management.appconfig import youtube_api_key from YtManagerApp.management.appconfig import appconfig
return YoutubeAPI(key=youtube_api_key) return YoutubeAPI(key=appconfig.youtube_api_key)
# @staticmethod # @staticmethod
# def build_oauth() -> 'YoutubeAPI': # def build_oauth() -> 'YoutubeAPI':

View File

@ -39,8 +39,8 @@ class ModalMixin(ContextMixin):
result = {'success': success} result = {'success': success}
if not success: if not success:
result['errors'] = form.errors.get_json_data(escape_html=True) result['errors'] = form.errors.get_json_data(escape_html=True)
if error_msg is not None: if error_msg is not None:
result['errors']['__all__'] = [{'message': error_msg}] result['errors']['__all__'] = [{'message': error_msg}]
return JsonResponse(result) return JsonResponse(result)

View File

@ -14,7 +14,11 @@ from YtManagerApp.views.forms.first_time import WelcomeForm, ApiKeyForm, PickAdm
logger = logging.getLogger("FirstTimeWizard") logger = logging.getLogger("FirstTimeWizard")
class WizardStepMixin(object): class WizardStepMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
# Prevent access if application is already initialized # Prevent access if application is already initialized

View File

@ -227,6 +227,10 @@ class DeleteFolderModal(LoginRequiredMixin, ModalMixin, FormMixin, DeleteView):
model = SubscriptionFolder model = SubscriptionFolder
form_class = DeleteFolderForm form_class = DeleteFolderForm
def __init__(self, *args, **kwargs):
self.object = None
super().__init__(*args, **kwargs)
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
form = self.get_form() form = self.get_form()
@ -246,7 +250,7 @@ class CreateSubscriptionForm(forms.ModelForm):
class Meta: class Meta:
model = Subscription model = Subscription
fields = ['parent_folder', 'auto_download', fields = ['parent_folder', 'auto_download',
'download_limit', 'download_order', 'delete_after_watched'] 'download_limit', 'download_order', "automatically_delete_watched"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -313,7 +317,7 @@ class UpdateSubscriptionForm(forms.ModelForm):
class Meta: class Meta:
model = Subscription model = Subscription
fields = ['name', 'parent_folder', 'auto_download', fields = ['name', 'parent_folder', 'auto_download',
'download_limit', 'download_order', 'delete_after_watched'] 'download_limit', 'download_order', "automatically_delete_watched"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -346,6 +350,10 @@ class DeleteSubscriptionModal(LoginRequiredMixin, ModalMixin, FormMixin, DeleteV
model = Subscription model = Subscription
form_class = DeleteSubscriptionForm form_class = DeleteSubscriptionForm
def __init__(self, *args, **kwargs):
self.object = None
super().__init__(*args, **kwargs)
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
form = self.get_form() form = self.get_form()
@ -445,7 +453,7 @@ class ImportSubscriptionsModal(LoginRequiredMixin, ModalMixin, FormView):
sub.auto_download = form.cleaned_data['auto_download'] sub.auto_download = form.cleaned_data['auto_download']
sub.download_limit = form.cleaned_data['download_limit'] sub.download_limit = form.cleaned_data['download_limit']
sub.download_order = form.cleaned_data['download_order'] sub.download_order = form.cleaned_data['download_order']
sub.delete_after_watched = form.cleaned_data['delete_after_watched'] sub.automatically_delete_watched = form.cleaned_data["automatically_delete_watched"]
try: try:
sub.fetch_from_url(url, api) sub.fetch_from_url(url, api)
except Exception as e: except Exception as e: