~cedric/newspipe

7a08a6b548e39a477aaf49b6213a2e06a0f3498a — Cédric Bonhomme 1 year, 2 months ago 188e43f
cleaned imports
65 files changed, 293 insertions(+), 216 deletions(-)

M manager.py
M migrations/env.py
M migrations/versions/16f8fc3cf0cc_add_column_webpage_in_the_user_table.py
M migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py
M migrations/versions/19bdaa6208e_add_icon_column.py
M migrations/versions/1b750a389c22_remove_email_notification_column.py
M migrations/versions/2472eddbf44b_update_of_the_user_model.py
M migrations/versions/25ca960a207_mv_icons_from_feed_tbl_to_icon_tbl.py
M migrations/versions/2c5cc05216fa_adding_tag_handling_capacities.py
M migrations/versions/3f83bfe93fc_add_updated_date_column_to_article_table.py
M migrations/versions/422da2d0234_adding_filters_field.py
M migrations/versions/48f561c0ce6_add_column_entry_id.py
M migrations/versions/5553a6c05fa7_add_column_twitter_in_the_user_table.py
M migrations/versions/661199d8768a_problem_with_the_last_upgrade.py
M migrations/versions/8bf5694c0b9e_add_column_automatic_crawling_to_the_.py
M migrations/versions/957d4c5b8ac9_add_column_is_public_profile_to_the_.py
M migrations/versions/ac35c979311a_removed_activation_key_from_the_user_.py
M migrations/versions/b329a1a7366f_add_new_tables_for_the_bookmarks_and_.py
M migrations/versions/bdd38bd755cb_remove_email_attribute_from_users_.py
M migrations/versions/be2b8b6f33dd_add_column_private_to_the_feeds_table.py
M migrations/versions/cde34831ea_adding_feed_and_user_attributes_for_.py
M migrations/versions/f700c4237e9d_remove_refresh_rate_column_from_the_.py
M migrations/versions/fa10b0bdd045_add_bio_column_to_user_table.py
M newspipe/bootstrap.py
M newspipe/controllers/abstract.py
M newspipe/controllers/article.py
M newspipe/controllers/bookmark.py
M newspipe/controllers/category.py
M newspipe/controllers/feed.py
M newspipe/controllers/icon.py
M newspipe/controllers/tag.py
M newspipe/controllers/user.py
M newspipe/crawler/default_crawler.py
M newspipe/lib/data.py
M newspipe/lib/feed_utils.py
M newspipe/lib/misc_utils.py
M newspipe/lib/utils.py
M newspipe/models/__init__.py
M newspipe/models/article.py
M newspipe/models/bookmark.py
M newspipe/models/category.py
M newspipe/models/feed.py
M newspipe/models/user.py
M newspipe/notifications/notifications.py
M newspipe/web/decorators.py
M newspipe/web/forms.py
M newspipe/web/lib/view_utils.py
M newspipe/web/views/__init__.py
M newspipe/web/views/admin.py
M newspipe/web/views/api/v2/__init__.py
M newspipe/web/views/api/v2/article.py
M newspipe/web/views/api/v2/category.py
M newspipe/web/views/api/v2/common.py
M newspipe/web/views/api/v2/feed.py
M newspipe/web/views/article.py
M newspipe/web/views/bookmark.py
M newspipe/web/views/category.py
M newspipe/web/views/common.py
M newspipe/web/views/feed.py
M newspipe/web/views/home.py
M newspipe/web/views/icon.py
M newspipe/web/views/session_mgmt.py
M newspipe/web/views/user.py
M newspipe/web/views/views.py
M runserver.py
M manager.py => manager.py +5 -4
@@ 1,16 1,17 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import logging
import os
from datetime import datetime
from werkzeug.security import generate_password_hash
from flask_script import Manager

from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
from werkzeug.security import generate_password_hash

import newspipe.models
from newspipe.controllers import UserController
from newspipe.bootstrap import application, db, set_logging
from newspipe.controllers import UserController

logger = logging.getLogger("manager")


M migrations/env.py => migrations/env.py +6 -5
@@ 1,5 1,11 @@
from __future__ import with_statement

from alembic import context
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
from sqlalchemy import engine_from_config, pool

# this is the Alembic Config object, which provides


@@ 10,11 16,6 @@ config = context.config
# This line sets up loggers basically.
# fileConfig("./alembic.ini")

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app

config.set_main_option(
    "sqlalchemy.url", current_app.config.get("SQLALCHEMY_DATABASE_URI")

M migrations/versions/16f8fc3cf0cc_add_column_webpage_in_the_user_table.py => migrations/versions/16f8fc3cf0cc_add_column_webpage_in_the_user_table.py +1 -1
@@ 12,8 12,8 @@ down_revision = "957d4c5b8ac9"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py => migrations/versions/17dcb75f3fe_changed_the_type_of_the_column_last_.py +4 -2
@@ 11,9 11,11 @@ revision = "17dcb75f3fe"
down_revision = "cde34831ea"

from datetime import datetime
import conf
from alembic import op

import sqlalchemy as sa
from alembic import op

import conf


def upgrade():

M migrations/versions/19bdaa6208e_add_icon_column.py => migrations/versions/19bdaa6208e_add_icon_column.py +1 -1
@@ 10,8 10,8 @@ Create Date: 2015-07-03 12:09:58.596010
revision = "19bdaa6208e"
down_revision = "422da2d0234"

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/1b750a389c22_remove_email_notification_column.py => migrations/versions/1b750a389c22_remove_email_notification_column.py +3 -2
@@ 10,9 10,10 @@ Create Date: 2015-02-25 23:01:07.253429
revision = "1b750a389c22"
down_revision = "48f561c0ce6"

import conf
from alembic import op
import sqlalchemy as sa
from alembic import op

import conf


def upgrade():

M migrations/versions/2472eddbf44b_update_of_the_user_model.py => migrations/versions/2472eddbf44b_update_of_the_user_model.py +1 -1
@@ 12,8 12,8 @@ down_revision = "ac35c979311a"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/25ca960a207_mv_icons_from_feed_tbl_to_icon_tbl.py => migrations/versions/25ca960a207_mv_icons_from_feed_tbl_to_icon_tbl.py +1 -1
@@ 10,8 10,8 @@ Create Date: 2015-08-03 14:36:21.626411
revision = "25ca960a207"
down_revision = "19bdaa6208e"

from alembic import op
import sqlalchemy as sa
from alembic import op

import conf


M migrations/versions/2c5cc05216fa_adding_tag_handling_capacities.py => migrations/versions/2c5cc05216fa_adding_tag_handling_capacities.py +1 -1
@@ 12,8 12,8 @@ down_revision = "be2b8b6f33dd"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/3f83bfe93fc_add_updated_date_column_to_article_table.py => migrations/versions/3f83bfe93fc_add_updated_date_column_to_article_table.py +1 -1
@@ 10,8 10,8 @@ Create Date: 2016-02-12 21:51:40.868539
revision = "3f83bfe93fc"
down_revision = "25ca960a207"

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/422da2d0234_adding_filters_field.py => migrations/versions/422da2d0234_adding_filters_field.py +1 -1
@@ 10,8 10,8 @@ Create Date: 2015-05-18 23:03:15.809549
revision = "422da2d0234"
down_revision = "17dcb75f3fe"

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/48f561c0ce6_add_column_entry_id.py => migrations/versions/48f561c0ce6_add_column_entry_id.py +3 -2
@@ 12,9 12,10 @@ down_revision = None
branch_labels = None
depends_on = None

import conf
from alembic import op
import sqlalchemy as sa
from alembic import op

import conf


def upgrade():

M migrations/versions/5553a6c05fa7_add_column_twitter_in_the_user_table.py => migrations/versions/5553a6c05fa7_add_column_twitter_in_the_user_table.py +1 -1
@@ 12,8 12,8 @@ down_revision = "f700c4237e9d"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/661199d8768a_problem_with_the_last_upgrade.py => migrations/versions/661199d8768a_problem_with_the_last_upgrade.py +1 -1
@@ 12,8 12,8 @@ down_revision = "3f83bfe93fc"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/8bf5694c0b9e_add_column_automatic_crawling_to_the_.py => migrations/versions/8bf5694c0b9e_add_column_automatic_crawling_to_the_.py +1 -1
@@ 12,8 12,8 @@ down_revision = "5553a6c05fa7"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/957d4c5b8ac9_add_column_is_public_profile_to_the_.py => migrations/versions/957d4c5b8ac9_add_column_is_public_profile_to_the_.py +1 -1
@@ 12,8 12,8 @@ down_revision = "2472eddbf44b"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/ac35c979311a_removed_activation_key_from_the_user_.py => migrations/versions/ac35c979311a_removed_activation_key_from_the_user_.py +1 -1
@@ 12,8 12,8 @@ down_revision = "661199d8768a"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/b329a1a7366f_add_new_tables_for_the_bookmarks_and_.py => migrations/versions/b329a1a7366f_add_new_tables_for_the_bookmarks_and_.py +2 -1
@@ 13,8 13,9 @@ branch_labels = None
depends_on = None

from datetime import datetime
from alembic import op

import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/bdd38bd755cb_remove_email_attribute_from_users_.py => migrations/versions/bdd38bd755cb_remove_email_attribute_from_users_.py +1 -1
@@ 12,8 12,8 @@ down_revision = "b329a1a7366f"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/be2b8b6f33dd_add_column_private_to_the_feeds_table.py => migrations/versions/be2b8b6f33dd_add_column_private_to_the_feeds_table.py +1 -1
@@ 12,8 12,8 @@ down_revision = "fa10b0bdd045"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/cde34831ea_adding_feed_and_user_attributes_for_.py => migrations/versions/cde34831ea_adding_feed_and_user_attributes_for_.py +3 -2
@@ 9,11 9,12 @@ Create Date: 2015-03-04 22:59:44.665979
# revision identifiers, used by Alembic.
revision = "cde34831ea"
down_revision = "1b750a389c22"
import conf
from datetime import datetime

from alembic import op
import sqlalchemy as sa
from alembic import op

import conf


def upgrade():

M migrations/versions/f700c4237e9d_remove_refresh_rate_column_from_the_.py => migrations/versions/f700c4237e9d_remove_refresh_rate_column_from_the_.py +1 -1
@@ 12,8 12,8 @@ down_revision = "16f8fc3cf0cc"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M migrations/versions/fa10b0bdd045_add_bio_column_to_user_table.py => migrations/versions/fa10b0bdd045_add_bio_column_to_user_table.py +1 -1
@@ 12,8 12,8 @@ down_revision = "8bf5694c0b9e"
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from alembic import op


def upgrade():

M newspipe/bootstrap.py => newspipe/bootstrap.py +4 -4
@@ 3,10 3,12 @@

# required imports and code execution for basic functionning

import os
import logging
from flask import request
import os

from flask import Flask, request
from flask_babel import Babel, format_datetime
from flask_sqlalchemy import SQLAlchemy


def set_logging(


@@ 43,8 45,6 @@ def set_logging(
        logger.setLevel(log_level)


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# Create Flask application
application = Flask(__name__, instance_relative_config=True)

M newspipe/controllers/abstract.py => newspipe/controllers/abstract.py +6 -4
@@ 1,11 1,13 @@
import logging
import dateutil.parser
from newspipe.bootstrap import db
from datetime import datetime
from collections import defaultdict
from sqlalchemy import or_, func
from datetime import datetime

import dateutil.parser
from sqlalchemy import func, or_
from werkzeug.exceptions import Forbidden, NotFound

from newspipe.bootstrap import db

logger = logging.getLogger(__name__)



M newspipe/controllers/article.py => newspipe/controllers/article.py +5 -3
@@ 1,14 1,16 @@
import logging
from collections import Counter

import sqlalchemy
from sqlalchemy import func
from collections import Counter

from newspipe.bootstrap import db
from .abstract import AbstractController
from newspipe.lib.article_utils import process_filters
from newspipe.controllers import CategoryController, FeedController
from newspipe.lib.article_utils import process_filters
from newspipe.models import Article

from .abstract import AbstractController

logger = logging.getLogger(__name__)



M newspipe/controllers/bookmark.py => newspipe/controllers/bookmark.py +2 -1
@@ 1,8 1,9 @@
import logging
import itertools
import logging

from newspipe.bootstrap import db
from newspipe.models import Bookmark

from .abstract import AbstractController
from .tag import BookmarkTagController


M newspipe/controllers/category.py => newspipe/controllers/category.py +2 -1
@@ 1,5 1,6 @@
from .abstract import AbstractController
from newspipe.models import Category

from .abstract import AbstractController
from .feed import FeedController



M newspipe/controllers/feed.py => newspipe/controllers/feed.py +4 -3
@@ 1,12 1,13 @@
import logging
import itertools
import logging
from datetime import datetime, timedelta

from newspipe.bootstrap import application
from newspipe.lib.utils import clear_string
from newspipe.models import Feed, User

from .abstract import AbstractController
from .icon import IconController
from newspipe.models import User, Feed
from newspipe.lib.utils import clear_string

logger = logging.getLogger(__name__)
DEFAULT_LIMIT = 5

M newspipe/controllers/icon.py => newspipe/controllers/icon.py +3 -0
@@ 1,6 1,9 @@
import base64

import requests

from newspipe.models import Icon

from .abstract import AbstractController



M newspipe/controllers/tag.py => newspipe/controllers/tag.py +3 -2
@@ 1,10 1,11 @@
import logging
import itertools
import logging

from newspipe.bootstrap import db
from .abstract import AbstractController
from newspipe.models.tag import BookmarkTag

from .abstract import AbstractController

logger = logging.getLogger(__name__)



M newspipe/controllers/user.py => newspipe/controllers/user.py +5 -2
@@ 1,8 1,11 @@
import logging
from werkzeug.security import generate_password_hash, check_password_hash
from .abstract import AbstractController

from werkzeug.security import check_password_hash, generate_password_hash

from newspipe.models import User

from .abstract import AbstractController

logger = logging.getLogger(__name__)



M newspipe/crawler/default_crawler.py => newspipe/crawler/default_crawler.py +10 -10
@@ 26,25 26,25 @@ __revision__ = "$Date: 2019/05/21 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "AGPLv3"

import io
import asyncio
import io
import logging
import feedparser
import dateutil.parser
from datetime import datetime, timedelta

import dateutil.parser
import feedparser
from sqlalchemy import or_

from newspipe.bootstrap import application
from newspipe.bootstrap import db
from newspipe.models import User
from newspipe.controllers import FeedController, ArticleController
from newspipe.lib.utils import newspipe_get
from newspipe.lib.feed_utils import construct_feed_from, is_parsing_ok
from newspipe.bootstrap import application, db
from newspipe.controllers import ArticleController, FeedController
from newspipe.lib.article_utils import (
    construct_article,
    extract_id,
    get_article_content,
    get_article_content
)
from newspipe.lib.feed_utils import construct_feed_from, is_parsing_ok
from newspipe.lib.utils import newspipe_get
from newspipe.models import User

logger = logging.getLogger(__name__)


M newspipe/lib/data.py => newspipe/lib/data.py +5 -5
@@ 30,17 30,17 @@ __license__ = "AGPLv3"
# This file contains the import/export functions of Newspipe.
#

import datetime
import json
import opml
import logging
import datetime

import opml
from flask import jsonify

from newspipe.bootstrap import db
from newspipe.models import User, Feed, Article
from newspipe.models.tag import BookmarkTag
from newspipe.controllers import BookmarkController, BookmarkTagController

from newspipe.models import Article, Feed, User
from newspipe.models.tag import BookmarkTag

logger = logging.getLogger(__name__)


M newspipe/lib/feed_utils.py => newspipe/lib/feed_utils.py +4 -3
@@ 1,12 1,13 @@
import html
import urllib
import logging
import requests
import urllib

import feedparser
import requests
from bs4 import BeautifulSoup, SoupStrainer

from newspipe.bootstrap import application
from newspipe.lib.utils import try_keys, try_get_icon_url, rebuild_url
from newspipe.lib.utils import rebuild_url, try_get_icon_url, try_keys

logger = logging.getLogger(__name__)
logging.captureWarnings(True)

M newspipe/lib/misc_utils.py => newspipe/lib/misc_utils.py +12 -10
@@ 26,28 26,30 @@ __revision__ = "$Date: 2016/11/22 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "AGPLv3"

import re
import os
import sys
import glob
import logging
import operator
import urllib
import os
import re
import subprocess
import sqlalchemy

try:
    from urlparse import urlparse, parse_qs, urlunparse
except:
    from urllib.parse import urlparse, parse_qs, urlunparse, urljoin
import sys
import urllib
from collections import Counter
from contextlib import contextmanager

import sqlalchemy
from flask import request

from newspipe.bootstrap import application
from newspipe.controllers import ArticleController
from newspipe.lib.utils import clear_string

try:
    from urlparse import urlparse, parse_qs, urlunparse
except:
    from urllib.parse import urlparse, parse_qs, urlunparse, urljoin


logger = logging.getLogger(__name__)

ALLOWED_EXTENSIONS = set(["xml", "opml", "json"])

M newspipe/lib/utils.py => newspipe/lib/utils.py +3 -2
@@ 1,9 1,10 @@
import logging
import re
import types
import urllib
import logging
import requests
from hashlib import md5

import requests
from flask import request, url_for

from newspipe.bootstrap import application

M newspipe/models/__init__.py => newspipe/models/__init__.py +14 -14
@@ 26,15 26,23 @@ __revision__ = "$Date: 2014/04/12 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "GPLv3"

from sqlalchemy.engine import reflection
from sqlalchemy.schema import (
    DropConstraint,
    DropTable,
    ForeignKeyConstraint,
    MetaData,
    Table
)

from .article import Article
from .bookmark import Bookmark
from .category import Category
from .feed import Feed
from .icon import Icon
from .role import Role
from .tag import ArticleTag, BookmarkTag
from .user import User
from .article import Article
from .icon import Icon
from .category import Category
from .tag import BookmarkTag
from .tag import ArticleTag
from .bookmark import Bookmark

__all__ = [
    "Feed",


@@ 49,14 57,6 @@ __all__ = [
]


from sqlalchemy.engine import reflection
from sqlalchemy.schema import (
    MetaData,
    Table,
    DropTable,
    ForeignKeyConstraint,
    DropConstraint,
)


def db_empty(db):

M newspipe/models/article.py => newspipe/models/article.py +2 -1
@@ 26,11 26,12 @@ __revision__ = "$Date: 2016/10/04 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "GPLv3"

from newspipe.bootstrap import db
from datetime import datetime

from sqlalchemy import Index
from sqlalchemy.ext.associationproxy import association_proxy

from newspipe.bootstrap import db
from newspipe.models.right_mixin import RightMixin



M newspipe/models/bookmark.py => newspipe/models/bookmark.py +4 -3
@@ 26,14 26,15 @@ __revision__ = "$Date: 2016/12/07 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "GPLv3"

from newspipe.bootstrap import db
from datetime import datetime

from sqlalchemy import desc
from sqlalchemy.orm import validates
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import validates

from newspipe.models.tag import BookmarkTag
from newspipe.bootstrap import db
from newspipe.models.right_mixin import RightMixin
from newspipe.models.tag import BookmarkTag


class Bookmark(db.Model, RightMixin):

M newspipe/models/category.py => newspipe/models/category.py +2 -1
@@ 1,8 1,9 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-

from newspipe.bootstrap import db
from sqlalchemy import Index

from newspipe.bootstrap import db
from newspipe.models.right_mixin import RightMixin



M newspipe/models/feed.py => newspipe/models/feed.py +5 -3
@@ 26,12 26,14 @@ __revision__ = "$Date: 2014/04/12 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "GPLv3"

from newspipe.bootstrap import db
from datetime import datetime
from sqlalchemy import desc, Index

from sqlalchemy import Index, desc
from sqlalchemy.orm import validates
from newspipe.models.right_mixin import RightMixin

from newspipe.bootstrap import db
from newspipe.models.article import Article
from newspipe.models.right_mixin import RightMixin


class Feed(db.Model, RightMixin):

M newspipe/models/user.py => newspipe/models/user.py +3 -2
@@ 28,14 28,15 @@ __license__ = "GPLv3"

import re
from datetime import datetime
from werkzeug.security import check_password_hash

from flask_login import UserMixin
from sqlalchemy.orm import validates
from werkzeug.security import check_password_hash

from newspipe.bootstrap import db
from newspipe.models.right_mixin import RightMixin
from newspipe.models.category import Category
from newspipe.models.feed import Feed
from newspipe.models.right_mixin import RightMixin


class User(db.Model, UserMixin, RightMixin):

M newspipe/notifications/notifications.py => newspipe/notifications/notifications.py +1 -0
@@ 20,6 20,7 @@
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import datetime

from flask import render_template

from newspipe.bootstrap import application

M newspipe/web/decorators.py => newspipe/web/decorators.py +1 -1
@@ 1,8 1,8 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-

from threading import Thread
from functools import wraps
from threading import Thread

from flask_login import login_required


M newspipe/web/forms.py => newspipe/web/forms.py +9 -9
@@ 26,25 26,25 @@ __revision__ = "$Date: 2015/05/06 $"
__copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "GPLv3"

from flask import flash, url_for, redirect
from flask_wtf import FlaskForm
from flask import flash, redirect, url_for
from flask_babel import lazy_gettext
from flask_wtf import FlaskForm
from werkzeug.exceptions import NotFound
from wtforms import (
    TextField,
    TextAreaField,
    PasswordField,
    BooleanField,
    SubmitField,
    HiddenField,
    IntegerField,
    PasswordField,
    SelectField,
    validators,
    HiddenField,
    SubmitField,
    TextAreaField,
    TextField,
    validators
)
from wtforms.fields.html5 import EmailField, URLField

from newspipe.lib import misc_utils
from newspipe.controllers import UserController
from newspipe.lib import misc_utils
from newspipe.models import User



M newspipe/web/lib/view_utils.py => newspipe/web/lib/view_utils.py +3 -1
@@ 1,5 1,7 @@
from functools import wraps
from flask import request, Response, make_response

from flask import Response, make_response, request

from newspipe.lib.utils import to_hash



M newspipe/web/views/__init__.py => newspipe/web/views/__init__.py +4 -4
@@ 1,9 1,9 @@
from newspipe.web.views import home, session_mgmt, views
from newspipe.web.views.admin import admin_bp
from newspipe.web.views.api import v2
from newspipe.web.views import views, home, session_mgmt
from newspipe.web.views.article import article_bp, articles_bp
from newspipe.web.views.bookmark import bookmark_bp, bookmarks_bp
from newspipe.web.views.category import categories_bp, category_bp
from newspipe.web.views.feed import feed_bp, feeds_bp
from newspipe.web.views.category import category_bp, categories_bp
from newspipe.web.views.icon import icon_bp
from newspipe.web.views.admin import admin_bp
from newspipe.web.views.user import user_bp, users_bp
from newspipe.web.views.bookmark import bookmark_bp, bookmarks_bp

M newspipe/web/views/admin.py => newspipe/web/views/admin.py +6 -5
@@ 1,12 1,13 @@
from datetime import datetime
from flask import Blueprint, render_template, redirect, flash, url_for
from flask_babel import gettext, format_timedelta
from flask_login import login_required, current_user

from newspipe.lib.utils import redirect_url
from flask import Blueprint, flash, redirect, render_template, url_for
from flask_babel import format_timedelta, gettext
from flask_login import current_user, login_required

from newspipe.controllers import UserController
from newspipe.web.views.common import admin_permission
from newspipe.lib.utils import redirect_url
from newspipe.web.forms import InformationMessageForm, UserForm
from newspipe.web.views.common import admin_permission

admin_bp = Blueprint("admin", __name__, url_prefix="/admin")


M newspipe/web/views/api/v2/__init__.py => newspipe/web/views/api/v2/__init__.py +1 -1
@@ 1,3 1,3 @@
from newspipe.web.views.api.v2 import article, feed, category
from newspipe.web.views.api.v2 import article, category, feed

__all__ = ["article", "feed", "category"]

M newspipe/web/views/api/v2/article.py => newspipe/web/views/api/v2/article.py +5 -4
@@ 1,17 1,18 @@
from newspipe.bootstrap import application
import dateutil.parser
from datetime import datetime

import dateutil.parser
from flask import current_app
from flask_restful import Api

from newspipe.web.views.common import api_permission
from newspipe.bootstrap import application
from newspipe.controllers import ArticleController
from newspipe.web.views.api.v2.common import (
    PyAggAbstractResource,
    PyAggResourceNew,
    PyAggResourceExisting,
    PyAggResourceMulti,
    PyAggResourceNew
)
from newspipe.web.views.common import api_permission


class ArticleNewAPI(PyAggResourceNew):

M newspipe/web/views/api/v2/category.py => newspipe/web/views/api/v2/category.py +1 -1
@@ 4,9 4,9 @@ from flask_restful import Api
from newspipe.bootstrap import application
from newspipe.controllers.category import CategoryController
from newspipe.web.views.api.v2.common import (
    PyAggResourceNew,
    PyAggResourceExisting,
    PyAggResourceMulti,
    PyAggResourceNew
)



M newspipe/web/views/api/v2/common.py => newspipe/web/views/api/v2/common.py +5 -4
@@ 20,18 20,19 @@ routes :
"""
import logging
from functools import wraps
from werkzeug.exceptions import Unauthorized, BadRequest, Forbidden, NotFound

from flask import request
from flask_restful import Resource, reqparse
from flask_login import current_user
from flask_restful import Resource, reqparse
from werkzeug.exceptions import BadRequest, Forbidden, NotFound, Unauthorized

from newspipe.controllers import UserController
from newspipe.web.views.common import (
    admin_permission,
    api_permission,
    login_user_bundle,
    jsonify,
    login_user_bundle
)
from newspipe.controllers import UserController

logger = logging.getLogger(__name__)


M newspipe/web/views/api/v2/feed.py => newspipe/web/views/api/v2/feed.py +7 -4
@@ 2,15 2,18 @@ from flask import current_app
from flask_restful import Api

from newspipe.bootstrap import application
from newspipe.web.views.common import api_permission
from newspipe.controllers.feed import FeedController, DEFAULT_MAX_ERROR, DEFAULT_LIMIT

from newspipe.controllers.feed import (
    DEFAULT_LIMIT,
    DEFAULT_MAX_ERROR,
    FeedController
)
from newspipe.web.views.api.v2.common import (
    PyAggAbstractResource,
    PyAggResourceNew,
    PyAggResourceExisting,
    PyAggResourceMulti,
    PyAggResourceNew
)
from newspipe.web.views.common import api_permission


class FeedNewAPI(PyAggResourceNew):

M newspipe/web/views/article.py => newspipe/web/views/article.py +12 -9
@@ 1,23 1,26 @@
from datetime import datetime, timedelta

from flask import (
    Blueprint,
    g,
    render_template,
    redirect,
    flash,
    url_for,
    g,
    make_response,
    redirect,
    render_template,
    request,
    url_for
)

from flask_babel import gettext
from flask_login import login_required, current_user

from flask_login import current_user, login_required

from newspipe.bootstrap import db
from newspipe.lib.utils import clear_string, redirect_url
from newspipe.controllers import (
    ArticleController,
    CategoryController,
    UserController
)
from newspipe.lib.data import export_json
from newspipe.controllers import ArticleController, UserController, CategoryController
from newspipe.lib.utils import clear_string, redirect_url
from newspipe.web.lib.view_utils import etag_match

articles_bp = Blueprint("articles", __name__, url_prefix="/articles")

M newspipe/web/views/bookmark.py => newspipe/web/views/bookmark.py +8 -8
@@ 27,28 27,28 @@ __copyright__ = "Copyright (c) Cedric Bonhomme"
__license__ = "AGPLv3"

import logging
from werkzeug.exceptions import BadRequest

from flask import (
    Blueprint,
    render_template,
    flash,
    make_response,
    redirect,
    render_template,
    request,
    url_for,
    make_response,
    url_for
)
from flask_babel import gettext
from flask_login import login_required, current_user
from flask_login import current_user, login_required
from flask_paginate import Pagination, get_page_args
from sqlalchemy import desc
from werkzeug.exceptions import BadRequest

from newspipe.lib.utils import redirect_url
from newspipe.lib.data import import_pinboard_json, export_bookmarks
from newspipe.bootstrap import db
from newspipe.web.forms import BookmarkForm
from newspipe.controllers import BookmarkController, BookmarkTagController
from newspipe.lib.data import export_bookmarks, import_pinboard_json
from newspipe.lib.utils import redirect_url
from newspipe.models import BookmarkTag
from newspipe.web.forms import BookmarkForm

logger = logging.getLogger(__name__)
bookmarks_bp = Blueprint("bookmarks", __name__, url_prefix="/bookmarks")

M newspipe/web/views/category.py => newspipe/web/views/category.py +8 -4
@@ 1,11 1,15 @@
from flask import Blueprint, render_template, flash, redirect, url_for
from flask import Blueprint, flash, redirect, render_template, url_for
from flask_babel import gettext
from flask_login import login_required, current_user
from flask_login import current_user, login_required

from newspipe.web.forms import CategoryForm
from newspipe.controllers import (
    ArticleController,
    CategoryController,
    FeedController
)
from newspipe.lib.utils import redirect_url
from newspipe.web.forms import CategoryForm
from newspipe.web.lib.view_utils import etag_match
from newspipe.controllers import ArticleController, FeedController, CategoryController

categories_bp = Blueprint("categories", __name__, url_prefix="/categories")
category_bp = Blueprint("category", __name__, url_prefix="/category")

M newspipe/web/views/common.py => newspipe/web/views/common.py +5 -3
@@ 1,15 1,17 @@
import json
from functools import wraps
from datetime import datetime
from flask import current_app, Response
from functools import wraps

from flask import Response, current_app
from flask_login import login_user
from flask_principal import (
    Identity,
    Permission,
    RoleNeed,
    session_identity_loader,
    identity_changed,
    session_identity_loader
)

from newspipe.controllers import UserController
from newspipe.lib.utils import default_handler


M newspipe/web/views/feed.py => newspipe/web/views/feed.py +13 -13
@@ 1,33 1,33 @@
import logging
import requests.exceptions
from datetime import datetime, timedelta
from sqlalchemy import desc
from werkzeug.exceptions import BadRequest

import requests.exceptions
from flask import (
    Blueprint,
    render_template,
    flash,
    make_response,
    redirect,
    render_template,
    request,
    url_for,
    make_response,
    url_for
)
from flask_babel import gettext
from flask_login import login_required, current_user
from flask_login import current_user, login_required
from flask_paginate import Pagination, get_page_args
from sqlalchemy import desc
from werkzeug.exceptions import BadRequest

from newspipe.bootstrap import application
from newspipe.lib import misc_utils, utils
from newspipe.lib.feed_utils import construct_feed_from
from newspipe.web.lib.view_utils import etag_match
from newspipe.web.forms import AddFeedForm
from newspipe.controllers import (
    UserController,
    ArticleController,
    CategoryController,
    FeedController,
    ArticleController,
    UserController
)
from newspipe.lib import misc_utils, utils
from newspipe.lib.feed_utils import construct_feed_from
from newspipe.web.forms import AddFeedForm
from newspipe.web.lib.view_utils import etag_match

logger = logging.getLogger(__name__)
feeds_bp = Blueprint("feeds", __name__, url_prefix="/feeds")

M newspipe/web/views/home.py => newspipe/web/views/home.py +17 -7
@@ 1,20 1,30 @@
import pytz
import logging
from datetime import datetime

from flask import current_app, render_template, request, flash, url_for, redirect
from flask_login import login_required, current_user
from flask_babel import gettext, get_locale
import pytz
from babel.dates import format_datetime, format_timedelta
from flask import (
    current_app,
    flash,
    redirect,
    render_template,
    request,
    url_for
)
from flask_babel import get_locale, gettext
from flask_login import current_user, login_required

from newspipe.bootstrap import application
from newspipe.lib.utils import redirect_url
from newspipe.controllers import (
    ArticleController,
    CategoryController,
    FeedController
)
from newspipe.lib import misc_utils
from newspipe.lib.utils import redirect_url
from newspipe.web.lib.view_utils import etag_match
from newspipe.web.views.common import jsonify

from newspipe.controllers import FeedController, ArticleController, CategoryController

localize = pytz.utc.localize
logger = logging.getLogger(__name__)


M newspipe/web/views/icon.py => newspipe/web/views/icon.py +1 -0
@@ 1,4 1,5 @@
import base64

from flask import Blueprint, Response, request

from newspipe.controllers import IconController

M newspipe/web/views/session_mgmt.py => newspipe/web/views/session_mgmt.py +13 -13
@@ 1,33 1,33 @@
import logging

from datetime import datetime
from werkzeug.security import generate_password_hash
from werkzeug.exceptions import NotFound

from flask import (
    render_template,
    current_app,
    flash,
    session,
    request,
    url_for,
    redirect,
    current_app,
    render_template,
    request,
    session,
    url_for
)
from flask_babel import gettext, lazy_gettext
from flask_login import LoginManager, logout_user, login_required, current_user
from flask_login import LoginManager, current_user, login_required, logout_user
from flask_principal import (
    Principal,
    AnonymousIdentity,
    Principal,
    UserNeed,
    identity_changed,
    identity_loaded,
    session_identity_loader,
    session_identity_loader
)
from werkzeug.exceptions import NotFound
from werkzeug.security import generate_password_hash

from newspipe.bootstrap import application
from newspipe.web.views.common import admin_role, api_role, login_user_bundle
from newspipe.controllers import UserController
from newspipe.web.forms import SignupForm, SigninForm
from newspipe.notifications import notifications
from newspipe.web.forms import SigninForm, SignupForm
from newspipe.web.views.common import admin_role, api_role, login_user_bundle

Principal(current_app)
# Create a permission with a single Need, in this case a RoleNeed.

M newspipe/web/views/user.py => newspipe/web/views/user.py +17 -10
@@ 1,22 1,29 @@
from flask import Blueprint, g, render_template, redirect, flash, url_for, request
from flask import (
    Blueprint,
    flash,
    g,
    redirect,
    render_template,
    request,
    url_for
)
from flask_babel import gettext
from flask_login import login_required, current_user
from flask_login import current_user, login_required
from flask_paginate import Pagination, get_page_args

from newspipe.bootstrap import application
from newspipe.notifications import notifications
from newspipe.lib import misc_utils
from newspipe.lib.data import import_opml, import_json
from newspipe.web.lib.user_utils import confirm_token
from newspipe.controllers import (
    UserController,
    FeedController,
    ArticleController,
    CategoryController,
    BookmarkController,
    CategoryController,
    FeedController,
    UserController
)

from newspipe.lib import misc_utils
from newspipe.lib.data import import_json, import_opml
from newspipe.notifications import notifications
from newspipe.web.forms import ProfileForm
from newspipe.web.lib.user_utils import confirm_token

users_bp = Blueprint("users", __name__, url_prefix="/users")
user_bp = Blueprint("user", __name__, url_prefix="/user")

M newspipe/web/views/views.py => newspipe/web/views/views.py +11 -3
@@ 1,14 1,22 @@
import sys
import logging
import operator
import sys
from datetime import datetime, timedelta
from flask import request, render_template, flash, url_for, redirect, current_app

from flask import (
    current_app,
    flash,
    redirect,
    render_template,
    request,
    url_for
)
from flask_babel import gettext
from sqlalchemy import desc

from newspipe.bootstrap import application
from newspipe.web import __version__
from newspipe.controllers import FeedController, UserController
from newspipe.web import __version__
from newspipe.web.lib.view_utils import etag_match

logger = logging.getLogger(__name__)

M runserver.py => runserver.py +5 -4
@@ 19,9 19,13 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
import calendar
from newspipe.bootstrap import application

from flask import g
from flask_babel import Babel, format_datetime
# Views
from flask_restful import Api

from newspipe.bootstrap import application

babel = Babel(application)



@@ 36,9 40,6 @@ application.jinja_env.filters["datetime"] = format_datetime
# inject application in Jinja env
application.jinja_env.globals["application"] = application

# Views
from flask_restful import Api
from flask import g

with application.app_context():
    g.api = Api(application, prefix="/api/v2.0")