From d1a6a9a3c15324c0d48a6617a91a1ed6f52b8b98 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 22 Nov 2018 23:18:36 -0200 Subject: [PATCH 1/6] removing files unused in this project --- quokka/admin/ajax.py | 36 -- quokka/admin/formatters.py | 87 ---- quokka/admin/forms.py | 84 ---- quokka/admin/widgets.py | 50 --- quokka/admin/wtforms_html5.py | 279 ------------ quokka/core/content/formats.py | 408 ------------------ .../quokka_module_template/admin.py | 90 ---- 7 files changed, 1034 deletions(-) delete mode 100644 quokka/admin/ajax.py delete mode 100644 quokka/admin/formatters.py delete mode 100644 quokka/admin/forms.py delete mode 100644 quokka/admin/widgets.py delete mode 100644 quokka/admin/wtforms_html5.py delete mode 100644 quokka/core/content/formats.py delete mode 100644 quokka/module_template/quokka_module_template/admin.py diff --git a/quokka/admin/ajax.py b/quokka/admin/ajax.py deleted file mode 100644 index b223a3572..000000000 --- a/quokka/admin/ajax.py +++ /dev/null @@ -1,36 +0,0 @@ -# coding: utf-8 -# TODO: adapt to tinymongo - -# from flask_admin.contrib.mongoengine.ajax import QueryAjaxModelLoader -# from flask_admin.model.ajax import DEFAULT_PAGE_SIZE - - -# class AjaxModelLoader(object): # QueryAjaxModelLoader): -# """ -# """ -# def __init__(self, name, model, **options): -# self.filters = options.pop('filters', None) -# super(AjaxModelLoader, self).__init__(name, model, **options) - -# def get_list(self, term, offset=0, limit=DEFAULT_PAGE_SIZE): -# query = self.model.objects - -# criteria = None - -# for field in self._cached_fields: -# flt = {u'%s__icontains' % field.name: term} - -# if not criteria: -# criteria = mongoengine.Q(**flt) -# else: -# criteria |= mongoengine.Q(**flt) - -# query = query.filter(criteria) - -# if self.filters: -# query = query.filter(**self.filters) - -# if offset: -# query = query.skip(offset) - -# return query.limit(limit).all() diff --git a/quokka/admin/formatters.py b/quokka/admin/formatters.py deleted file mode 100644 index 0f5b6b3f0..000000000 --- a/quokka/admin/formatters.py +++ /dev/null @@ -1,87 +0,0 @@ -from flask import current_app as app -from flask_htmlbuilder.htmlbuilder import html -from quokka.core.content.models import make_model - - -def format_datetime(self, request, obj, fieldname, *args, **kwargs): - """Returns the formated datetime in string from object""" - model = make_model(obj) - return html.div(style='min-width:130px;')( - getattr(model, fieldname).strftime( - app.config.get('ADMIN_DATE_FORMAT', '%Y-%m-%d') - ) - ) - - -def format_view_on_site(self, request, obj, fieldname, *args, **kwargs): - """Returns button to view or preview depending on content status""" - model = make_model(obj) - return html.a( - href=model.external_url, - target='_blank', - )(html.i(class_="icon fa fa-globe glyphicon glyphicon-globe", - style="margin-right: 5px;")(), - 'View' if model.published else 'Preview') - - -def format_ul(self, request, obj, fieldname, *args, **kwars): - """Given a list of data format it is ul/li""" - model = make_model(obj) - field = getattr(model, fieldname) - column_formatters_args = getattr(self, 'column_formatters_args', {}) - _args = column_formatters_args.get('ul', {}).get(fieldname, {}) - ul = html.ul(style=_args.get('style', "min-width:200px;max-width:300px;")) - placeholder = _args.get('placeholder', u"{i}") - lis = [html.li(placeholder.format(item=item)) for item in field] - return ul(*lis) - - -def format_link(self, request, obj, fieldname, *args, **kwars): - """Format a link from the model""" - model = make_model(obj) - value = getattr(model, fieldname) - return html.a(href=value, title=value, target='_blank')( - html.i(class_="icon icon-resize-small", - style="margin-right: 5px;")() - ) - - -def format_status(self, request, obj, fieldname, *args, **kwargs): - """Format the status published or not published and other booleans""" - model = make_model(obj) - status = getattr(model, fieldname) - column_formatters_args = getattr(self, 'column_formatters_args', {}) - _args = column_formatters_args.get('status', {}).get(fieldname, {}) - labels = _args.get('labels', {}) - return html.span( - class_="label label-{0}".format(labels.get(status, 'default')), - style=_args.get('style', 'min-height:18px;') - )(status) - - -def format_url(self, request, obj, fieldname, *args, **kwargs): - """Get the url of a content object""" - column_formatters_args = getattr(self, 'column_formatters_args', {}) - _args = column_formatters_args.get('get_url', {}).get(fieldname, {}) - attribute = _args.get('attribute', 'url') - method = _args.get('method', 'url') - model = make_model(obj) - text = getattr(model, fieldname, '') - if attribute: - target = getattr(model, attribute, None) - else: - target = model - - url = getattr(target, method, lambda: '#')() - - return html.a(href=url)(text if text not in [None, 'None'] else '') - - -def format_custom_vars(self, request, obj, fieldname, *args, **kwargs): - ul = html.ul(style="min-width:200px;max-width:300px;") - lis = [ - html.li( - html.strong(f'{item["key"]}:'), f' {item["value"]}' - ) for item in obj.get('custom_vars', []) - ] - return ul(*lis) diff --git a/quokka/admin/forms.py b/quokka/admin/forms.py deleted file mode 100644 index a782d8d97..000000000 --- a/quokka/admin/forms.py +++ /dev/null @@ -1,84 +0,0 @@ -# coding: utf-8 - -from flask_admin.babel import Translations -from flask_admin.form import rules # noqa -from flask_admin.form.fields import (DateTimeField, JSONField, Select2Field, - Select2TagsField, TimeField) -from flask_admin.form.widgets import Select2TagsWidget -from flask_admin.model.fields import InlineFieldList, InlineFormField -from flask_wtf import FlaskForm -from quokka.admin.fields import SmartSelect2Field -from quokka.admin.wtforms_html5 import AutoAttrMeta -from wtforms import fields as _fields -from wtforms import widgets as _widgets -from wtforms import validators # noqa -from wtforms.validators import ValidationError - -# from wtforms_components import read_only # noqa -# from wtforms_components import ReadOnlyWidgetProxy # noqa - - -class PassiveField(object): - """ - Passive field that does not populate obj values. - """ - def populate_obj(self, obj, name): - pass - - -class PassiveHiddenField(PassiveField, _fields.HiddenField): - pass - - -class PassiveStringField(PassiveField, _fields.StringField): - pass - - -fields = _fields # noqa -fields.SmartSelect2Field = SmartSelect2Field -fields.DateTimeField = DateTimeField -fields.TimeField = TimeField -fields.Select2Field = Select2Field -fields.Select2TagsField = Select2TagsField -fields.JSONField = JSONField -fields.InlineFieldList = InlineFieldList -fields.InlineFormField = InlineFormField -fields.PassiveHiddenField = PassiveHiddenField -fields.PassiveStringField = PassiveStringField - -widgets = _widgets -widgets.Select2TagsWidget = Select2TagsWidget - - -READ_ONLY = {'readonly': True} - - -class Form(FlaskForm): - """Base class to customize wtforms""" - _translations = Translations() - Meta = AutoAttrMeta - - def _get_translations(self): - return self._translations - - -class CallableValidator(object): - """ - Takes a callable and validates using it - """ - def __init__(self, function, message=None): - self.function = function - self.message = message - - def __call__(self, form, field): - validation = self.function(form, field) - if validation is not None: - raise ValidationError(self.message or validation) - - -validators.CallableValidator = CallableValidator - -rules.csrf_token = rules.Field( - 'csrf_token', - render_field='quokka_macros.render_hidden_field' -) diff --git a/quokka/admin/widgets.py b/quokka/admin/widgets.py deleted file mode 100644 index b03e2bddc..000000000 --- a/quokka/admin/widgets.py +++ /dev/null @@ -1,50 +0,0 @@ - -from flask import current_app -from quokka.core.template import render_template -from wtforms.widgets import TextArea, TextInput - - -class TextEditor(TextArea): - def __init__(self, *args, **kwargs): - super(TextEditor, self).__init__() - self.rows = kwargs.get('rows', 20) - self.cols = kwargs.get('cols', 20) - self.css_cls = kwargs.get('css_cls', 'text_editor') - self.style_ = kwargs.get( - 'style_', - "margin: 0px; width: 725px; height: 360px;" - ) - self.editor = kwargs.pop('editor', 'texteditor') - - def __call__(self, field, **kwargs): - c = kwargs.pop('class', '') or kwargs.pop('class_', '') - kwargs['class'] = u'%s %s' % (self.css_cls, c) - kwargs['rows'] = self.rows - kwargs['cols'] = self.cols - s = kwargs.pop('style', '') or kwargs.pop('style_', '') - kwargs['style'] = u"%s %s" % (self.style_, s) - html = super(TextEditor, self).__call__(field, **kwargs) - html += render_template( - 'admin/texteditor/%s.html' % self.editor, - theme=current_app.config.get('ADMIN_THEME', 'admin'), - selector='.' + self.css_cls - ) - return html - - -class PrepopulatedText(TextInput): - def __init__(self, *args, **kwargs): - self.master = kwargs.pop('master', '') - super(PrepopulatedText, self).__init__(*args, **kwargs) - - def __call__(self, *args, **kwargs): - html = super(PrepopulatedText, self).__call__(*args, **kwargs) - slave = args[0].id - if self.master: - html += render_template( - 'admin/custom/prepopulated.html', - theme=current_app.config.get('ADMIN_THEME', 'admin'), - master=self.master, - slave=slave - ) - return html diff --git a/quokka/admin/wtforms_html5.py b/quokka/admin/wtforms_html5.py deleted file mode 100644 index ccc3a1c09..000000000 --- a/quokka/admin/wtforms_html5.py +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding: UTF-8 -*- - -""" -Generates render keywords for `WTForms`_ HTML5 field's widgets. - -The :func:`get_html5_kwargs` adds the automatically generated keys to the -*render keywords* of a `WTForms`_ field. - -The :cls:`AutoAttrMeta` can be included as a base class for the `Meta` class -in your forms, to handle this automatically for each field of the form. - - -Supported Auto–Attributes -------------------------- - -- *required* - - Is set if the field has the _required_ flag set. This happens i.e. if you - use the _DataRequired_ or _InputRequired_ validator. The `required` - attribute is used by browsers to indicate a required field (and most - browsers won't activate the forms action unless all required fields have - content). - -- *invalid* - - If the field got any validation errors, the CSS class _invalid_ is added. - The `invalid` class is also set by browsers if they detect errors on a - field. This validation errors detected by your code, are by default styled - in the same way as browser generated errors. - -- *min* and *max* - - If either _Length_ or _NumberRange_ is used as a validator to set minimal - and / or maximal values, the corresponding `min` / `max` INPUT attribute is - set. This allows for browser based validation of the values. - -- *title* - - If no _title_ is provided for a field, the _description_ (if one is set) is - used for the `title` attribute. - - -An Example ----------- - -Declare your form just like in vanilla *WTForms*, but include `AutoAttrMeta` -as your meta class: - ->>> from wtforms import Form, StringField ->>> from wtforms.validators import InputRequired, Length ->>> from wtforms_html5 import AutoAttrMeta - ->>> class MyForm(Form): -... class Meta(AutoAttrMeta): -... pass -... test_field = StringField( -... 'Testfield', -... validators=[InputRequired(), Length(min=3, max=12)], -... description='Just a test field.', -... ) - ->>> form = MyForm() - -**The only difference is, that you include a `Meta` class, that inherits from -`AutoAttrMeta`.** - -This meta class sets the above mentioned attributes automatically for all the -fields of the form: - ->>> f = form.test_field() ->>> exp = ( -... '' -... ) ->>> assert f == exp - - - -The _min_ and _max_ attributes are created because the `Length` validator was -used. And the field is marked _required_ because of the `InputRequired` -validator. The field also gets a _title_ taken from the fields `description`. - -If you validate the form and any errors pop up, the field also get `invalid` -added to its class: - ->>> form.validate() -False ->>> exp = ( -... '' -... ) ->>> f = form.test_field() ->>> assert f == exp - - -.. _WTForms: https://wtforms.readthedocs.io/ - -""" - -from __future__ import absolute_import, unicode_literals - -from wtforms.fields.core import UnboundField -from wtforms.meta import DefaultMeta -from wtforms.validators import Length, NumberRange - -__version__ = '0.3.0' -__author__ = 'Brutus [DMC] ' -__license__ = 'GNU General Public License v3 or above - '\ - 'http://www.opensource.org/licenses/gpl-3.0.html' - - -MINMAX_VALIDATORS = ( - Length, - NumberRange, -) - - -def set_required(field, render_kw=None, force=False): - """ - Returns *render_kw* with *required* set if the field is required. - - Sets the *required* key if the `required` flag is set for the field (this - is mostly the case if it is set by validators). The `required` attribute - is used by browsers to indicate a required field. - - ..note:: - - This won't change keys already present unless *force* is used. - - """ - if render_kw is None: - render_kw = {} - if 'required' in render_kw and not force: - return render_kw - if field.flags.required: - render_kw['required'] = True - return render_kw - - -def set_invalid(field, render_kw=None): - """ - Returns *render_kw* with `invalid` added to *class* on validation errors. - - Set (or appends) 'invalid' to the fields CSS class(es), if the *field* got - any errors. 'invalid' is also set by browsers if they detect errors on a - field. - - """ - if render_kw is None: - render_kw = {} - if field.errors: - classes = render_kw.get('class') or render_kw.pop('class_', '') - if classes: - render_kw['class'] = 'invalid {}'.format(classes) - else: - render_kw['class'] = 'invalid' - return render_kw - - -def set_minmax(field, render_kw=None, force=False): - """ - Returns *render_kw* with *min* and *max* set if validators use them. - - Sets *min* and / or *max* keys if a `Length` or `NumberRange` validator is - using them. - - ..note:: - - This won't change keys already present unless *force* is used. - - """ - if render_kw is None: - render_kw = {} - for validator in field.validators: - if isinstance(validator, MINMAX_VALIDATORS): - if 'min' not in render_kw or force: - v_min = getattr(validator, 'min', -1) - if v_min not in (-1, None): - render_kw['min'] = v_min - if 'max' not in render_kw or force: - v_max = getattr(validator, 'max', -1) - if v_max not in (-1, None): - render_kw['max'] = v_max - return render_kw - - -def set_title(field, render_kw=None): - """ - Returns *render_kw* with *min* and *max* set if required. - - If the field got a *description* but no *title* key is set, the *title* is - set to *description*. - - """ - if render_kw is None: - render_kw = {} - if 'title' not in render_kw and getattr(field, 'description'): - render_kw['title'] = '{}'.format(field.description) - return render_kw - - -def get_html5_kwargs(field, render_kw=None, force=False): - """ - Returns a copy of *render_kw* with keys added for a bound *field*. - - If some *render_kw* are given, the new keys are added to a copy of them, - which is then returned. If none are given, a dictionary containing only - the automatically generated keys is returned. - - .. important:: - - This might add new keys but won't changes any values if a key is - already in *render_kw*, unless *force* is used. - - Raises: - - ValueError: if *field* is an :cls:`UnboundField`. - - The following keys are set automatically: - - :required: - Sets the *required* key if the `required` flag is set for the - field (this is mostly the case if it is set by validators). The - `required` attribute is used by browsers to indicate a required field. - - :invalid: - Set (or appends) 'invalid' to the fields CSS class(es), if the *field* - got any errors. 'invalid' is also set by browsers if they detect - errors on a field. - - :min / max: - Sets *min* and / or *max* keys if a `Length` or `NumberRange` - validator is using them. - - :title: - If the field got a *description* but no *title* key is set, the - *title* is set to *description*. - - """ - if isinstance(field, UnboundField): - msg = 'This function needs a bound field not: {}' - raise ValueError(msg.format(field)) - kwargs = render_kw.copy() if render_kw else {} - kwargs = set_required(field, kwargs, force) # is field required? - kwargs = set_invalid(field, kwargs) # is field invalid? - kwargs = set_minmax(field, kwargs, force) # check validators for min/max - kwargs = set_title(field, kwargs) # missing tile? - return kwargs - - -class AutoAttrMeta(DefaultMeta): - """ - Meta class for WTForms :cls:`Form` classes. - - It uses :func:`get_html5_kwargs` to automatically add some render - keywords for each field's widget when it gets rendered. - - """ - - def render_field(self, field, render_kw): - """ - Returns the rendered field after adding auto–attributes. - - Calls the field`s widget with the following kwargs: - - 1. the *render_kw* set on the field are used as based - 2. and are updated with the *render_kw* arguments from the render call - 3. this is used as an argument for a call to `get_html5_kwargs` - 4. the return value of the call is used as final *render_kw* - - """ - field_kw = getattr(field, 'render_kw', None) - if callable(field_kw): - field_kw = field_kw(field) - if field_kw is not None: - render_kw = dict(field_kw, **render_kw) - render_kw = get_html5_kwargs(field, render_kw) - return field.widget(field, **render_kw) diff --git a/quokka/core/content/formats.py b/quokka/core/content/formats.py deleted file mode 100644 index 2c6292dd5..000000000 --- a/quokka/core/content/formats.py +++ /dev/null @@ -1,408 +0,0 @@ -import datetime as dt -import getpass -import json -from .parsers import markdown -from flask import current_app as app, Markup -from flask_admin.helpers import get_form_data -from flask_admin.model.fields import InlineFieldList, InlineFormField -from quokka.admin.forms import Form, fields, rules, validators -from werkzeug.utils import import_string - - -# Utils - - -def get_content_formats(instances=False): - content_formats = app.config.get( - 'CONTENT_FORMATS', - { - 'markdown': { - 'choice_text': 'Markdown', - 'help_text': 'Markdown text editor', - 'content_format_class': - 'quokka.core.content.formats.MarkdownFormat' - } - } - ) - if instances: - for _, data in content_formats: - data['content_format_instance'] = import_string( - data['content_format_class'] - )() - return content_formats - - -def get_content_format_choices(): - content_formats = get_content_formats() - return [ - # ('value', 'TEXT') - (identifier, data['choice_text']) - for identifier, data - in content_formats.items() - ] - - -def get_format(obj): - content_formats = get_content_formats() - try: - obj_content_format = content_formats[obj['content_format']] - content_format = import_string( - obj_content_format['content_format_class'] - )() - return content_format - except (KeyError): - return PlainFormat() - - -def get_edit_form(obj): - return get_format(obj).get_edit_form(obj) - - -def validate_category(form, field): - denied_categories = app.config.get( - 'DENIED_CATEGORIES', - ['tag', 'tags', 'categories', 'author', 'authors', 'user', - 'index', 'feed', 'admin', 'adm', 'login', 'logout', 'sitemap', - 'block'] - ) - if field.data is not None: - items = field.data.split(',') - if len(items) > 1: - return 'You can select only one category' - for item in items: - root_name = item.split('/')[0] - if root_name in denied_categories or root_name.startswith('@'): - return f'You cannot use `{root_name}` as a category start name' - - -def get_category_kw(field): - categories = list(app.db.category_set(sort=False)) - categories.extend(app.config.get('CATEGORIES', [])) - categories = sorted(list(set(categories))) - return {'data-tags': json.dumps(categories), - 'data-placeholder': 'One category or leave blank'} - - -def validate_block_item(form, field): - if field.data is not None: - items = field.data.split(',') - if len(items) > 1: - return 'You can select only one URL for each item' - - -def get_block_item_kw(field): - items = [ - f"{d['content_type']}::{d['title']}::{d['category']}/{d['slug']}" - for d in app.db.content_set() - if d['title'] not in app.theme_context.get('TEXTBLOCKS', []) - ] - index = app.theme_context.get('INDEX_CATEGORY') - items.append(f"category::{index}") - items.extend([ - f"category::{category}" - for category in app.db.category_set() if category - ]) - items.extend([ - f"tag::{tag}" for tag in app.db.tag_set() - ]) - items.extend([ - f"author::{author}" for author in app.db.author_set() - ]) - items.extend([ - f"url::{item[0]}::{item[1]}" - for item in app.config.get('INTERNAL_URLS', []) - ]) - items.extend([ - f"url::category_feed_{category}::{category}/index.{ext}" - for ext in ['rss', 'atom'] - for category in app.db.category_set() if category - ]) - items.extend([ - f"url::tag_feed_{tag}::{tag}/index.{ext}" - for ext in ['rss', 'atom'] - for tag in app.db.tag_set() - ]) - block_items = sorted(list(set(items))) - return {'data-tags': json.dumps(block_items), - 'data-placeholder': 'Start typing, select existing or add new URL'} - - -def get_default_category(): - return app.config.get('DEFAULT_CATEGORY') - - -def get_authors_kw(field): - authors = app.db.author_set(sort=False) - authors.extend(app.config.get('AUTHORS', [])) - authors.append(getpass.getuser()) - authors = sorted(list(set(authors))) - return {'data-tags': json.dumps(authors), - 'data-placeholder': - 'Enter one or more comma separated author names'} - - -def get_default_author(): - authors = app.config.get('AUTHORS') - return authors[0] if authors else getpass.getuser() - - -def get_tags_kw(field): - tags = app.db.tag_set(sort=False) - tags.extend(app.config.get('TAGS', [])) - tags = sorted(list(set(tags))) - return {'data-tags': json.dumps(tags), - 'data-placeholder': 'Comma separated tags'} - - -def get_default_language(): - return app.config.get('BABEL_DEFAULT_LOCALE', 'en') - -# classes - - -class BaseForm(Form): - - title = fields.StringField( - 'Title', [validators.required()], - description='TIP: `My Title` turns to`my-title.html` url' - ) - summary = fields.TextAreaField('Summary') - category = fields.Select2TagsField( - 'Category', - [validators.CallableValidator(validate_category)], - save_as_list=False, - render_kw=get_category_kw, - default=get_default_category, - description=( - 'TIP: Leave blank and url will be `/my-title.html`
' - '`foo` url will be `/foo/my-title.html`
' - '`foo/bar` url will be `/foo/bar/my-title.html`
' - ) - ) - authors = fields.Select2TagsField( - 'Authors', - [validators.required()], - save_as_list=True, - render_kw=get_authors_kw, - default=get_default_author - ) - - -class CreateForm(BaseForm): - """Default create form where content format is chosen""" - # TODO: Make content_type an optional field by ASK_CONTENT_TYPE config - # content_type = fields.SelectField( - # 'Type', - # [validators.required()], - # choices=[('article', 'Article'), ('page', 'Page')] - # ) - content_format = fields.SmartSelect2Field( - 'Format', - [validators.required()], - choices=get_content_format_choices, - # TODO: remove this `allow_blank` once select2 submit on enter is fix - allow_blank=True - ) - - -class CustomVariablesForm(Form): - key = fields.StringField( - 'Key', [validators.required()], - description='lower_snake_case' - ) - value = fields.StringField( - 'Value', [validators.required()], - description=( - 'Optionally define format using @int,@float,@bool,@json ' - 'ex:`@float 42.1` or `@int 42` or `@bool false` ' - 'or `@json ["item1", "item2"]`' - ) - ) - - -class BlockItemForm(Form): - item = fields.Select2TagsField( - 'Item', - [validators.required(), - validators.CallableValidator(validate_block_item)], - save_as_list=False, - render_kw=get_block_item_kw, - description=( - 'Enter absolute URL `http://..` or `/foo/bar.html` ' - 'or select existing content.' - ) - ) - name = fields.StringField('Name', description='optional') - order = fields.IntegerField('Order', default=0) - item_type = fields.SmartSelect2Field( - 'Type', - [validators.required()], - default='link', - choices=lambda: [ - item for item in - app.config.get('BLOCK_ITEM_TYPES', [('link', 'Link')]) - ] - ) - - custom_vars = InlineFieldList( - InlineFormField(CustomVariablesForm), label='Custom Variables' - ) - - index_id = fields.HiddenField('index_id') - category_id = fields.HiddenField('category_id') - tag_id = fields.HiddenField('tag_id') - author_id = fields.HiddenField('author_id') - url_id = fields.HiddenField('url_id') - content_type = fields.HiddenField('content_type', default='block_item') - - -class BaseEditForm(BaseForm): - """Edit form with all missing fields except `content`""" - - # content_type = fields.PassiveStringField( - # 'Type', - # render_kw=READ_ONLY - # ) - # content_format = fields.PassiveStringField( - # 'Format', - # render_kw=READ_ONLY - # ) - - tags = fields.Select2TagsField( - 'Tags', - save_as_list=True, - render_kw=get_tags_kw - ) - date = fields.DateTimeField( - 'Date', - [validators.required()], - default=dt.datetime.now - ) - modified = fields.HiddenField('Modified') - slug = fields.StringField('Slug') - language = fields.SmartSelect2Field( - 'Language', - choices=lambda: [ - (lng, lng) - for lng in app.config.get('BABEL_LANGUAGES', ['en']) - ], - default=get_default_language - ) - # translations = fields.HiddenField('Translations') - # todo: ^ create action 'add translation' - published = fields.BooleanField( - 'Status', - render_kw={ - 'data-toggle': "toggle", - 'data-on': "Published", - 'data-off': "Draft", - "data-onstyle": 'success' - } - ) - comments = fields.BooleanField( - 'Comments', - default=True, - render_kw={ - 'data-toggle': "toggle", - 'data-on': "Enabled", - 'data-off': "Disabled", - "data-onstyle": 'success' - } - ) - - # to be used only for Block type - block_items = InlineFieldList( - InlineFormField(BlockItemForm), label='Items' - ) - - custom_vars = InlineFieldList( - InlineFormField(CustomVariablesForm), label='Custom Variables' - ) - - -class BaseFormat(object): - identifier = None - edit_form = BaseEditForm - form_edit_rules = [ - rules.FieldSet(('title', 'summary')), - rules.Field('content'), - rules.FieldSet(('category', 'authors', 'tags')), - rules.FieldSet(('date',)), - rules.FieldSet(('slug',)), - rules.Field('published'), - rules.Field('comments'), - rules.Field('custom_vars'), - rules.csrf_token - ] - - def get_edit_form(self, obj): - return self.edit_form(get_form_data(), **obj) - - def get_edit_template(self, obj): - return 'admin/quokka/edit.html' - - def get_identifier(self): - return self.identifier or self.__class__.__name__ - - def get_form_edit_rules(self, obj): - return self.form_edit_rules - - def before_save(self, form, model, is_created): - """optional""" - - def after_save(self, form, model, is_created): - """optional""" - - def extra_js(self): - return [] - - def render_content(self, obj): - - if not isinstance(obj, dict): - content = obj.data - else: - content = obj - - if 'content' not in content: - content = app.db.get_with_content(_id=content['_id']) - - return content['content'] - - def render(self, obj): - # TODO: PRE-RENDER - rv = self.render_content(obj) - # TODO: POST-RENDER - return rv - - -# Customs - - -class PlainEditForm(BaseEditForm): - content = fields.TextAreaField('Plain Content') - - -class PlainFormat(BaseFormat): - edit_form = PlainEditForm - - -class HTMLEditForm(BaseEditForm): - content = fields.TextAreaField('HTML Content') - - -class HTMLFormat(BaseFormat): - edit_form = HTMLEditForm - - -class MarkdownEditForm(BaseEditForm): - content = fields.TextAreaField('Markdown Content') - - -class MarkdownFormat(BaseFormat): - edit_form = MarkdownEditForm - - def render_content(self, obj): - content = super().render_content(obj) - if content: - return Markup(markdown(content)) - return content or '' diff --git a/quokka/module_template/quokka_module_template/admin.py b/quokka/module_template/quokka_module_template/admin.py deleted file mode 100644 index 16db05372..000000000 --- a/quokka/module_template/quokka_module_template/admin.py +++ /dev/null @@ -1,90 +0,0 @@ -from flask import current_app -from flask_admin.contrib.pymongo import filters -from flask_admin.form import Select2Widget -from flask_admin.model.fields import InlineFieldList, InlineFormField -from quokka.admin.forms import Form, fields -from quokka.admin.views import ModelView - - -# User admin -class InnerForm(Form): - username = fields.StringField('Username') - test = fields.StringField('Test') - - -class UserForm(Form): - username = fields.StringField('Username') - email = fields.StringField('Email') - password = fields.StringField('Password') - - # Inner form - inner = InlineFormField(InnerForm) - - # Form list - form_list = InlineFieldList(InlineFormField(InnerForm)) - - -class UserView(ModelView): - column_list = ('username', 'email', 'password') - column_sortable_list = ('username', 'email', 'password') - - form = UserForm - - page_size = 20 - can_set_page_size = True - - # Correct user_id reference before saving - def on_model_change(self, form, model): - model['_id'] = model.get('username') - return model - - -# Tweet view -class TweetForm(Form): - name = fields.StringField('Name') - user_id = fields.SelectField('User', widget=Select2Widget()) - text = fields.StringField('Text') - testie = fields.BooleanField('Test') - - -class TweetView(ModelView): - column_list = ('name', 'user_name', 'text') - column_sortable_list = ('name', 'text') - - column_filters = (filters.FilterEqual('name', 'Name'), - filters.FilterNotEqual('name', 'Name'), - filters.FilterLike('name', 'Name'), - filters.FilterNotLike('name', 'Name'), - filters.BooleanEqualFilter('testie', 'Testie')) - - # column_searchable_list = ('name', 'text') - - form = TweetForm - - def get_list(self, *args, **kwargs): - # not necessary but kept as example - count, data = super(TweetView, self).get_list(*args, **kwargs) - - # Contribute user_name to the models - for item in data: - user = current_app.db.users.find_one( - {'_id': item['user_id']} - ) - if user: - item['user_name'] = user['_id'] - - return count, data - - # Contribute list of user choices to the forms - def _feed_user_choices(self, form): - users = current_app.db.users.find(fields=('_id',)) - form.user_id.choices = [(str(x['_id']), x['_id']) for x in users] - return form - - def create_form(self): - form = super(TweetView, self).create_form() - return self._feed_user_choices(form) - - def edit_form(self, obj): - form = super(TweetView, self).edit_form(obj) - return self._feed_user_choices(form) From c94b0af8012be143edb15215d0f888bf54578976 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 6 Jun 2019 05:52:59 -0300 Subject: [PATCH 2/6] fixing pep8 - quokka/core/content/models.py - quokka/core/content/utils.py - quokka/core/content/views.py - quokka/core/views/sitemap.py - quokka/utils/upload.py --- quokka/core/content/models.py | 14 +++++++------- quokka/core/content/utils.py | 6 ++++-- quokka/core/content/views.py | 5 +++-- quokka/core/views/sitemap.py | 10 +++++----- quokka/utils/upload.py | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/quokka/core/content/models.py b/quokka/core/content/models.py index 6d2fcc4d9..5358ed079 100644 --- a/quokka/core/content/models.py +++ b/quokka/core/content/models.py @@ -230,13 +230,13 @@ def metadata(self): # TODO: get metadata from database # TODO: implement libratar/gravatar # return { - # 'cover': 'foo', - # 'author_gravatar': 'http://i.pravatar.cc/300', - # 'about_author': 'About Author', - # 'translations': ['en'], - # 'og_image': 'foo', - # 'series': 'aa', - # 'asides': 'aaa' + # 'cover': 'foo', + # 'author_gravatar': 'http://i.pravatar.cc/300', + # 'about_author': 'About Author', + # 'translations': ['en'], + # 'og_image': 'foo', + # 'series': 'aa', + # 'asides': 'aaa' # } data = {} data.update(custom_var_dict(self.data.get('custom_vars'))) diff --git a/quokka/core/content/utils.py b/quokka/core/content/utils.py index 57aaef312..d4c5ff1e7 100644 --- a/quokka/core/content/utils.py +++ b/quokka/core/content/utils.py @@ -10,10 +10,12 @@ def url_for_content(content, include_ext=True): else: data = content + category_slug_data = data.get('category_slug') + category_data = slugify_category(data.get('category') or '') category_slug = ( - data.get('category_slug') or - slugify_category(data.get('category') or '') + category_slug_data or category_data ) + slug = data.get('slug') or slugify(data.get('title')) if category_slug: diff --git a/quokka/core/content/views.py b/quokka/core/content/views.py index 74c72d288..08d6d9bc1 100644 --- a/quokka/core/content/views.py +++ b/quokka/core/content/views.py @@ -255,6 +255,8 @@ def render_rss(self, content_type, templates, **context): for content in contents: content = make_model(content) + content_data = content.title.encode('utf-8') + content_data += content.url.encode('utf-8') if content.date > rss_pubdate: rss_pubdate = content.date @@ -267,8 +269,7 @@ def render_rss(self, content_type, templates, **context): author=str(content.author), categories=[str(content.tags)], guid=hashlib.sha1( - content.title.encode('utf-8') + - content.url.encode('utf-8') + content_data ).hexdigest(), pubDate=content.date, ) diff --git a/quokka/core/views/sitemap.py b/quokka/core/views/sitemap.py index 871372817..2cdca943b 100644 --- a/quokka/core/views/sitemap.py +++ b/quokka/core/views/sitemap.py @@ -11,12 +11,12 @@ def get_contents(self): TODO: Should include extra paths, fixed paths config based paths, static paths """ + content = self.get_index() + self.get_categories() + content += self.get_tags() + self.get_authors() + content += self.get_articles_and_pages() + return ( - self.get_index() + - self.get_categories() + - self.get_tags() + - self.get_authors() + - self.get_articles_and_pages() + content ) def get_index(self): diff --git a/quokka/utils/upload.py b/quokka/utils/upload.py index 251e1c50f..bc8042679 100644 --- a/quokka/utils/upload.py +++ b/quokka/utils/upload.py @@ -9,7 +9,7 @@ def dated_path(obj, file_data): try: - prefix = getattr(obj, 'model_name') + prefix = getattr(obj, 'model_name', None) except BaseException: prefix = "undefined" From 7a2e9fc434cb2c4fba9a27efe9f10d426bb918e2 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 6 Jun 2019 05:58:27 -0300 Subject: [PATCH 3/6] fixing pep8 - quokka/core/db.py --- quokka/core/db.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/quokka/core/db.py b/quokka/core/db.py index 431c55aea..afc09ad77 100644 --- a/quokka/core/db.py +++ b/quokka/core/db.py @@ -183,17 +183,14 @@ def page_set(self, *args, **kwargs): return self.content_set(*args, **kwargs) def block_set(self, *args, **kwargs): - kwargs.setdefault( - 'sort', - self.app.theme_context.get( - 'BLOCK_ORDER_BY', [('title', -1)] - ) - ) - if not args: - args = [{'content_type': 'block'}] - elif isinstance(args[0], dict): - args[0]['content_type'] = 'block' - return self.content_set(*args, **kwargs) + kwargs.setdefault('sort', self.app.theme_context.get( + 'BLOCK_ORDER_BY', [('title', -1)] + )) + if not args: + args = [{'content_type': 'block'}] + elif isinstance(args[0], dict): + args[0]['content_type'] = 'block' + return self.content_set(*args, **kwargs) def select(self, colname, *args, **kwargs): return self.get_collection(colname).find(*args, **kwargs) From 3adb90462ae027351eea4e430ece63ee6b84f7d5 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 6 Jun 2019 07:11:13 -0300 Subject: [PATCH 4/6] fixing basic tests to pass in travisCI --- tests/__init__.py | 0 tests/quokka/__init__.py | 0 tests/quokka/project_template/__init__.py | 0 tests/test_basic.py | 143 +++++++++++++++++++++- 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/quokka/__init__.py create mode 100644 tests/quokka/project_template/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/quokka/__init__.py b/tests/quokka/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/quokka/project_template/__init__.py b/tests/quokka/project_template/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_basic.py b/tests/test_basic.py index 1f9418114..5814d2fe6 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,3 +1,142 @@ +import mock +import quokka +from quokka import create_app, create_app_base +from pytest_mock import mocker +from quokka.core.app import QuokkaApp +from quokka.core.flask_dynaconf import configure_dynaconf + +################################ +#pytest - fixtures - setUp(); # +################################ +class MockTestApp(object): + + def __init__(self, config): + self.config = config + return self.config + + +##################################### +#pytest - Quokka - test__init__.py # +##################################### +def test_create_app_called_params_default(mocker): + mocker.patch("quokka.create_app_base") + mocker.patch("quokka.core.configure_extensions") + quokka.create_app() + quokka.create_app_base.assert_called_once_with(test=False) + +def test_create_app_called_test_false(mocker): + mocker.patch("quokka.create_app_base") + mocker.patch("quokka.core.configure_extensions") + quokka.create_app(test=False) + quokka.create_app_base.assert_called_once_with(test=False) + +def test_create_app_called_test_true(mocker): + mocker.patch("quokka.create_app_base") + mocker.patch("quokka.core.configure_extensions") + quokka.create_app(test=True) + quokka.create_app_base.assert_called_once_with(test=True) + +def test_create_app_called_test_true_and_settings_dict(mocker): + mocker.patch("quokka.create_app_base") + mocker.patch("quokka.core.configure_extensions") + quokka.create_app(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + quokka.create_app_base.assert_called_once_with(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_quokkaapp_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + quokka.create_app_base(test=False, ext_list=None) + assert mock_QuokkaApp.called is False + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_dynaconf_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + quokka.create_app_base(test=False, ext_list=None) + assert mock_configure_dynaconf.called is False + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_configure_extension_called_is_false(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + quokka.create_app_base(test=False, ext_list=None) + assert mock_configure_extension.called is False + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_quokkaapp_called_is_false_and_test_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + quokka.create_app_base(test=True, ext_list=[]) + assert mock_QuokkaApp.called is False + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_dynaconf_called_is_false_test_true_and_ext_list(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + quokka.create_app_base(test=True, ext_list=['quokka.core.configure_extension']) + assert mock_configure_dynaconf.called is False + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_configure_dynaconf_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext) + assert mock_configure_dynaconf.called is True + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_quokkaapp_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext) + assert mock_QuokkaApp.called is True + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_configure_extension_called_is_true(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext) + assert mock_configure_extension.called is True + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_configure_extension_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + assert mock_configure_extension.called is True + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_configure_dynaconf_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + assert mock_configure_dynaconf.called is True + +@mock.patch("quokka.core.app.QuokkaApp") +@mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") +@mock.patch("quokka.core.configure_extension") +def test_create_app_base_function_quokkaapp_called_is_true_and_settings(mock_configure_extension, mock_configure_dynaconf, mock_QuokkaApp): + list_ext = ['quokka.core.app.QuokkaApp', + 'quokka.core.flask_dynaconf.configure_dynaconf', + 'quokka.core.configure_extension'] + quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + assert mock_QuokkaApp.called is True + + + -def test_basic(app): - assert app.name == 'quokka' From 712d9019981e389d381fb44fcfdc51dc9e05ca42 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 6 Jun 2019 07:26:48 -0300 Subject: [PATCH 5/6] fixing pep8 from tests/test_basic.py --- tests/test_basic.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/test_basic.py b/tests/test_basic.py index 5814d2fe6..aa9515152 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,22 +1,23 @@ import mock import quokka from quokka import create_app, create_app_base -from pytest_mock import mocker +from pytest_mock import mocker from quokka.core.app import QuokkaApp from quokka.core.flask_dynaconf import configure_dynaconf + ################################ -#pytest - fixtures - setUp(); # +# pytest - fixtures - setUp(); # ################################ class MockTestApp(object): - + def __init__(self, config): self.config = config return self.config ##################################### -#pytest - Quokka - test__init__.py # +# pytest - Quokka - test__init__.py # ##################################### def test_create_app_called_params_default(mocker): mocker.patch("quokka.create_app_base") @@ -24,24 +25,28 @@ def test_create_app_called_params_default(mocker): quokka.create_app() quokka.create_app_base.assert_called_once_with(test=False) + def test_create_app_called_test_false(mocker): mocker.patch("quokka.create_app_base") mocker.patch("quokka.core.configure_extensions") quokka.create_app(test=False) quokka.create_app_base.assert_called_once_with(test=False) + def test_create_app_called_test_true(mocker): mocker.patch("quokka.create_app_base") mocker.patch("quokka.core.configure_extensions") quokka.create_app(test=True) quokka.create_app_base.assert_called_once_with(test=True) - + + def test_create_app_called_test_true_and_settings_dict(mocker): mocker.patch("quokka.create_app_base") mocker.patch("quokka.core.configure_extensions") quokka.create_app(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) quokka.create_app_base.assert_called_once_with(test=True, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -49,6 +54,7 @@ def test_create_app_base_function_quokkaapp_called_is_false(mock_configure_exten quokka.create_app_base(test=False, ext_list=None) assert mock_QuokkaApp.called is False + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -56,6 +62,7 @@ def test_create_app_base_function_dynaconf_called_is_false(mock_configure_extens quokka.create_app_base(test=False, ext_list=None) assert mock_configure_dynaconf.called is False + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -63,6 +70,7 @@ def test_create_app_base_function_configure_extension_called_is_false(mock_confi quokka.create_app_base(test=False, ext_list=None) assert mock_configure_extension.called is False + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -70,6 +78,7 @@ def test_create_app_base_function_quokkaapp_called_is_false_and_test_true(mock_c quokka.create_app_base(test=True, ext_list=[]) assert mock_QuokkaApp.called is False + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -77,6 +86,7 @@ def test_create_app_base_function_dynaconf_called_is_false_test_true_and_ext_lis quokka.create_app_base(test=True, ext_list=['quokka.core.configure_extension']) assert mock_configure_dynaconf.called is False + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -87,6 +97,7 @@ def test_create_app_base_function_configure_dynaconf_called_is_true(mock_configu quokka.create_app_base(test=True, ext_list=list_ext) assert mock_configure_dynaconf.called is True + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -97,6 +108,7 @@ def test_create_app_base_function_quokkaapp_called_is_true(mock_configure_extens quokka.create_app_base(test=True, ext_list=list_ext) assert mock_QuokkaApp.called is True + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -107,6 +119,7 @@ def test_create_app_base_function_configure_extension_called_is_true(mock_config quokka.create_app_base(test=True, ext_list=list_ext) assert mock_configure_extension.called is True + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -117,6 +130,7 @@ def test_create_app_base_function_configure_extension_called_is_true_and_setting quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) assert mock_configure_extension.called is True + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -127,6 +141,7 @@ def test_create_app_base_function_configure_dynaconf_called_is_true_and_settings quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) assert mock_configure_dynaconf.called is True + @mock.patch("quokka.core.app.QuokkaApp") @mock.patch("quokka.core.flask_dynaconf.configure_dynaconf") @mock.patch("quokka.core.configure_extension") @@ -137,6 +152,3 @@ def test_create_app_base_function_quokkaapp_called_is_true_and_settings(mock_con quokka.create_app_base(test=True, ext_list=list_ext, settings={'a':'1', 'b':'2', 'c':'3', 'd':'4', 'e':'5'}) assert mock_QuokkaApp.called is True - - - From 2936a8f89ec8b633c48d3058e1dd6c8cf52c03b4 Mon Sep 17 00:00:00 2001 From: marcosptf Date: Thu, 6 Jun 2019 07:32:01 -0300 Subject: [PATCH 6/6] add pytest_mock to req-dev --- requirements-dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index ba32aa2f0..7eda9b364 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -12,3 +12,4 @@ twine>=1.9.1 wheel>=0.30.0 flask>=1.0 logzero +pytest_mock