diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..4489d186 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +exclude = .git,__pycache__,docs/source/conf.py,old,build,dist,migrations,south_migrations diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2baae02d..3ac8f467 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,7 +17,12 @@ are used for versioning (schema follows below): 0.11 ---- -2017-05-xx (not yet released) +2017-05-07 + +This release is dedicated to my beloved `wife `_ +for all the love and support she gave me through years. If you are a company +looking for (female) developers in Groningen area (the Netherlands), do not +hesitate to `contact her `_. - Django REST framework integration. - Documentation fixes. @@ -27,11 +32,12 @@ are used for versioning (schema follows below): testing with Firefox in headless mode in documentation. - Validate the ``decimal`` field plugin - quantize the decimal value to the configured precision. -- Minor fixes (``float`` field plugin). +- Minor fixes in the ``float`` field plugin. - Minor improvements in complex form element plugins (``select``, ``file``) and form handler plugins (``db_store``, ``mail``, ``http_respost``) in order to simplify integration plugins and reduce code duplication. -- Minor Python3 fixes in ``range_select`` and ``slider`` plugins. +- Minor Python3 fixes in ``range_select`` and ``slider`` form element plugins. +- Minor Python3 fixes in ``http_repost`` and ``mail`` form handler plugins. 0.10.7 ------ diff --git a/ROADMAP.rst b/ROADMAP.rst index 33368774..4c3b6acf 100644 --- a/ROADMAP.rst +++ b/ROADMAP.rst @@ -3,12 +3,6 @@ Roadmap ======= Upcoming releases road-map. -0.11 ----- -yyyy-mm-dd (upcoming). - -- Django REST framework integration. - 0.12 ---- yyyy-mm-dd (future). diff --git a/examples/requirements/style_checkers.txt b/examples/requirements/style_checkers.txt index cfbaac27..82deacbd 100644 --- a/examples/requirements/style_checkers.txt +++ b/examples/requirements/style_checkers.txt @@ -1,5 +1,7 @@ # Style checkers pydocstyle +pylint +pyflakes flake8 isort pre-commit diff --git a/examples/simple/settings/base.py b/examples/simple/settings/base.py index f643618c..2514ecd1 100644 --- a/examples/simple/settings/base.py +++ b/examples/simple/settings/base.py @@ -398,7 +398,6 @@ INSTALLED_APPS = [ 'fobi.contrib.apps.drf_integration', # DRF integration app # Form elements - # 'fobi.contrib.apps.drf_integration.form_elements.content.content_image', 'fobi.contrib.apps.drf_integration.form_elements.fields.boolean', 'fobi.contrib.apps.drf_integration.form_elements.fields' '.checkbox_select_multiple', @@ -418,8 +417,6 @@ INSTALLED_APPS = [ 'fobi.contrib.apps.drf_integration.form_elements.fields.range_select', 'fobi.contrib.apps.drf_integration.form_elements.fields.regex', 'fobi.contrib.apps.drf_integration.form_elements.fields.select', - # 'fobi.contrib.apps.drf_integration.form_elements.fields' - # '.select_model_object', 'fobi.contrib.apps.drf_integration.form_elements.fields.select_multiple', 'fobi.contrib.apps.drf_integration.form_elements.fields' '.select_multiple_with_max', diff --git a/scripts/flake8.sh b/scripts/flake8.sh new file mode 100755 index 00000000..bb00a155 --- /dev/null +++ b/scripts/flake8.sh @@ -0,0 +1,2 @@ +reset +flake8 src/fobi/ diff --git a/scripts/pyflakes.sh b/scripts/pyflakes.sh new file mode 100755 index 00000000..2ba062a7 --- /dev/null +++ b/scripts/pyflakes.sh @@ -0,0 +1,2 @@ +reset +pyflakes src/fobi/ diff --git a/src/fobi/base.py b/src/fobi/base.py index 49ba717f..816dc3bb 100644 --- a/src/fobi/base.py +++ b/src/fobi/base.py @@ -9,7 +9,10 @@ import traceback import uuid -from collections import OrderedDict, defaultdict +from collections import ( + defaultdict, + # OrderedDict, +) import simplejson as json @@ -543,14 +546,14 @@ class BaseTheme(object): :return str: """ return """ -
  • - {edit_text} -
  • - """.format( - edit_url="{edit_url}", - edit_option_class=cls.form_edit_form_entry_option_class, - edit_text="{edit_text}", - ) +
  • + {edit_text} +
  • + """.format( + edit_url="{edit_url}", + edit_option_class=cls.form_edit_form_entry_option_class, + edit_text="{edit_text}", + ) @classmethod def edit_form_entry_help_text_extra(cls): @@ -561,28 +564,28 @@ class BaseTheme(object): :return str: """ return """ - - - - """.format( - container_class=cls.form_list_container_class, - edit_option_html="{edit_option_html}", - delete_url="{delete_url}", - delete_option_class=cls.form_delete_form_entry_option_class, - delete_text="{delete_text}", - form_element_position="{form_element_position}", - counter="{counter}", - form_element_pk="{form_element_pk}", - ) + + + + """.format( + container_class=cls.form_list_container_class, + edit_option_html="{edit_option_html}", + delete_url="{delete_url}", + delete_option_class=cls.form_delete_form_entry_option_class, + delete_text="{delete_text}", + form_element_position="{form_element_position}", + counter="{counter}", + form_element_pk="{form_element_pk}", + ) def get_view_template_name(self, request=None, origin=None): """Get view template name. @@ -1044,7 +1047,7 @@ class BasePlugin(object): try: form_data.update( {field: self.plugin_data.get(field, default_value)} - ) + ) except Exception as err: logger.debug( "Error in class %s. Details: %s", @@ -2477,7 +2480,7 @@ class FormCallbackRegistry(object): raise InvalidRegistryItemType( "Invalid item type `{0}` for registry " "`{1}`".format(cls, self.__class__) - ) + ) # uid = self.uidfy(cls) # If item has not been forced yet, add/replace its' value in the @@ -2528,7 +2531,7 @@ class BasePluginWidgetRegistry(object): raise InvalidRegistryItemType( "Invalid item type `{0}` for registry " "`{1}`".format(cls, self.__class__) - ) + ) uid = BasePluginWidgetRegistry.namify(cls.theme_uid, cls.plugin_uid) @@ -2557,7 +2560,7 @@ class BasePluginWidgetRegistry(object): raise InvalidRegistryItemType( "Invalid item type `{0}` for registry " "`{1}`".format(cls, self.__class__) - ) + ) uid = BasePluginWidgetRegistry.namify(cls.theme_uid, cls.plugin_uid) @@ -3082,6 +3085,10 @@ def get_ordered_form_handler_plugins(): return form_handler_plugins +# For backwards compatibility, if someone had ever used this. +get_ordered_form_handlers = get_ordered_form_handler_plugins + + def run_form_handlers(form_entry, request, form, form_element_entries=None): """Run form handlers. @@ -3192,6 +3199,10 @@ def get_ordered_form_wizard_handler_plugins(): return form_wizard_handler_plugins +# For backwards compatibility, if someone had ever used this. +get_ordered_form_wizard_handlers = get_ordered_form_wizard_handler_plugins + + def run_form_wizard_handlers(form_wizard_entry, request, form_list, form_wizard, form_element_entries=None): """Run form wizard handlers. diff --git a/src/fobi/contrib/apps/drf_integration/README.rst b/src/fobi/contrib/apps/drf_integration/README.rst index 73d74acf..49a255a3 100644 --- a/src/fobi/contrib/apps/drf_integration/README.rst +++ b/src/fobi/contrib/apps/drf_integration/README.rst @@ -243,3 +243,9 @@ command: .. code-block:: sh ./runtests.py src/fobi/tests/test_drf_integration.py + +or use plain Django tests: + +.. code-block:: sh + + ./manage.py test fobi.tests.test_drf_integration --settings=settings.test diff --git a/src/fobi/contrib/apps/drf_integration/TODOS.rst b/src/fobi/contrib/apps/drf_integration/TODOS.rst index 145a2927..7dc8d395 100644 --- a/src/fobi/contrib/apps/drf_integration/TODOS.rst +++ b/src/fobi/contrib/apps/drf_integration/TODOS.rst @@ -23,7 +23,8 @@ Must haves + Add `mail` and `http_repost` DRF handler plugins. + Add/finish documentation. + In DRF listing view, if user isn't authenticated, show only public forms. -- Fix Python3 issues with ``slider`` and ``range`` select plugins. ++ Fix Python3 issues with ``slider`` and ``range`` select plugins. ++ Fixed Python3 issues with max_length for text fields. Should haves ------------ diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/email/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/email/base.py index 9a51250d..4078ce08 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/email/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/email/base.py @@ -39,8 +39,11 @@ class EmailInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=EmailField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/file/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/file/base.py index fa2741f9..2222def9 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/file/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/file/base.py @@ -41,8 +41,11 @@ class FileInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=FileField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/float/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/float/base.py index 31e129c0..57517b6d 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/float/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/float/base.py @@ -36,10 +36,12 @@ class FloatInputPlugin(IntegrationFormFieldPlugin, """Get form field instances.""" field_kwargs = { 'required': form_element_plugin.data.required, - 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, } + if form_element_plugin.data.initial: + field_kwargs['initial'] = float(form_element_plugin.data.initial) + if form_element_plugin.data.max_value: data_max_value = float(form_element_plugin.data.max_value) field_kwargs['max_value'] = data_max_value diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/input/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/input/base.py index 37bd0d23..66aa3fa5 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/input/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/input/base.py @@ -39,8 +39,11 @@ class InputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=CharField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/ip_address/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/ip_address/base.py index 34b94761..86a7c355 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/ip_address/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/ip_address/base.py @@ -39,8 +39,11 @@ class IPAddressInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=IPAddressField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/password/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/password/base.py index 5fc24975..9e9c57dc 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/password/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/password/base.py @@ -39,10 +39,11 @@ class PasswordInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - # 'max_length': form_element_plugin.data.max_length, } if form_element_plugin.data.max_length: - field_kwargs['max_length'] = form_element_plugin.data.max_length + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/slug/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/slug/base.py index ac9839c2..51ab2fe0 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/slug/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/slug/base.py @@ -40,6 +40,10 @@ class SlugInputPlugin(IntegrationFormFieldPlugin, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=SlugField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/text/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/text/base.py index ad1616f6..7141374e 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/text/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/text/base.py @@ -39,8 +39,11 @@ class TextInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update({ + 'max_length': int(form_element_plugin.data.max_length) + }) return [ DRFIntegrationFormElementPluginProcessor( field_class=CharField, diff --git a/src/fobi/contrib/apps/drf_integration/form_elements/fields/url/base.py b/src/fobi/contrib/apps/drf_integration/form_elements/fields/url/base.py index 3d759794..cdb256e1 100644 --- a/src/fobi/contrib/apps/drf_integration/form_elements/fields/url/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_elements/fields/url/base.py @@ -39,8 +39,11 @@ class URLInputPlugin(IntegrationFormFieldPlugin, 'initial': form_element_plugin.data.initial, 'label': form_element_plugin.data.label, 'help_text': form_element_plugin.data.help_text, - 'max_length': form_element_plugin.data.max_length, } + if form_element_plugin.data.max_length: + field_kwargs.update( + {'max_length': int(form_element_plugin.data.max_length)} + ) return [ DRFIntegrationFormElementPluginProcessor( field_class=URLField, diff --git a/src/fobi/contrib/apps/drf_integration/form_handlers/http_repost/base.py b/src/fobi/contrib/apps/drf_integration/form_handlers/http_repost/base.py index 13fbd26f..d16e16f2 100644 --- a/src/fobi/contrib/apps/drf_integration/form_handlers/http_repost/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_handlers/http_repost/base.py @@ -5,6 +5,8 @@ import os from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from six import PY3 + from ......base import IntegrationFormHandlerPlugin from ......helpers import extract_file_path @@ -57,9 +59,15 @@ class HTTPRepostHandlerPlugin(IntegrationFormHandlerPlugin): os.path.join(settings.MEDIA_ROOT, '') ) mime_type = guess_type(imf.name) + + if PY3: + imf_chunks = b''.join([c for c in imf.chunks()]) + else: + imf_chunks = ''.join([c for c in imf.chunks()]) + files[field_name] = ( imf.name, - ''.join([c for c in imf.chunks()]), + imf_chunks, mime_type[0] if mime_type else '' ) diff --git a/src/fobi/contrib/apps/drf_integration/form_handlers/mail/base.py b/src/fobi/contrib/apps/drf_integration/form_handlers/mail/base.py index 98c144e7..66db1b20 100644 --- a/src/fobi/contrib/apps/drf_integration/form_handlers/mail/base.py +++ b/src/fobi/contrib/apps/drf_integration/form_handlers/mail/base.py @@ -5,6 +5,8 @@ import os from django.conf import settings from django.utils.translation import ugettext_lazy as _ +from six import PY3 + from ......base import IntegrationFormHandlerPlugin from ......helpers import extract_file_path @@ -74,9 +76,15 @@ class MailHandlerPlugin(IntegrationFormHandlerPlugin): os.path.join(settings.MEDIA_ROOT, '') ) mime_type = guess_type(imf.name) + + if PY3: + imf_chunks = b''.join([c for c in imf.chunks()]) + else: + imf_chunks = ''.join([c for c in imf.chunks()]) + files[field_name] = ( imf.name, - ''.join([c for c in imf.chunks()]), + imf_chunks, mime_type[0] if mime_type else '' ) diff --git a/src/fobi/contrib/plugins/form_elements/fields/range_select/base.py b/src/fobi/contrib/plugins/form_elements/fields/range_select/base.py index 052c5556..fdeac2cf 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/range_select/base.py +++ b/src/fobi/contrib/plugins/form_elements/fields/range_select/base.py @@ -4,7 +4,9 @@ from django.forms.fields import ChoiceField from django.forms.widgets import Select from django.utils.translation import ugettext_lazy as _ -from fobi.base import FormFieldPlugin, get_theme +from six import PY3 + +from ......base import FormFieldPlugin, get_theme from . import UID from .forms import RangeSelectInputForm @@ -71,7 +73,11 @@ class RangeSelectInputPlugin(FormFieldPlugin): else INITIAL_MIN_VALUE step = int(self.data.step) if self.data.step else STEP - _choices = [__r for __r in range(min_value, max_value + 1, step)] - choices = [(__k, __v) for __k, __v in zip(_choices, _choices)] + if PY3: + _choices = [__r for __r in range(min_value, max_value + 1, step)] + choices = [(__k, __v) for __k, __v in zip(_choices, _choices)] + else: + _choices = range(min_value, max_value + 1, step) + choices = zip(_choices, _choices) return choices diff --git a/src/fobi/contrib/plugins/form_elements/fields/slider/base.py b/src/fobi/contrib/plugins/form_elements/fields/slider/base.py index 5ee8612d..c36efcfe 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/slider/base.py +++ b/src/fobi/contrib/plugins/form_elements/fields/slider/base.py @@ -1,6 +1,6 @@ from __future__ import absolute_import -from six import text_type +from six import text_type, PY3 from django.forms.fields import ChoiceField @@ -79,8 +79,12 @@ class SliderInputPlugin(FormFieldPlugin): else INITIAL_MIN_VALUE step = int(self.data.step) if self.data.step else STEP - _choices = [__r for __r in range(min_value, max_value + 1, step)] - choices = [(__k, __v) for __k, __v in zip(_choices, _choices)] + if PY3: + _choices = [__r for __r in range(min_value, max_value + 1, step)] + choices = [(__k, __v) for __k, __v in zip(_choices, _choices)] + else: + _choices = range(min_value, max_value + 1, step) + choices = zip(_choices, _choices) return choices diff --git a/src/fobi/contrib/plugins/form_elements/fields/slug/base.py b/src/fobi/contrib/plugins/form_elements/fields/slug/base.py index c16af360..82878dbb 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/slug/base.py +++ b/src/fobi/contrib/plugins/form_elements/fields/slug/base.py @@ -42,6 +42,6 @@ class SlugInputPlugin(FormFieldPlugin): 'widget': TextInput(attrs=widget_attrs), } if self.data.max_length: - field_kwargs['max_length'] = self.data.max_length + field_kwargs['max_length'] = int(self.data.max_length) return [(self.data.name, SlugField, field_kwargs)] diff --git a/src/fobi/contrib/plugins/form_elements/fields/text/base.py b/src/fobi/contrib/plugins/form_elements/fields/text/base.py index 1fdbef37..1aad7cab 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/text/base.py +++ b/src/fobi/contrib/plugins/form_elements/fields/text/base.py @@ -42,6 +42,6 @@ class TextInputPlugin(FormFieldPlugin): 'widget': TextInput(attrs=widget_attrs), } if self.data.max_length: - field_kwargs['max_length'] = self.data.max_length + field_kwargs['max_length'] = int(self.data.max_length) return [(self.data.name, CharField, field_kwargs)] diff --git a/src/fobi/contrib/plugins/form_elements/fields/url/base.py b/src/fobi/contrib/plugins/form_elements/fields/url/base.py index 7c52227c..efd119bd 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/url/base.py +++ b/src/fobi/contrib/plugins/form_elements/fields/url/base.py @@ -53,6 +53,6 @@ class URLInputPlugin(FormFieldPlugin): 'widget': URLInput(attrs=widget_attrs), } if self.data.max_length: - field_kwargs['max_length'] = self.data.max_length + field_kwargs['max_length'] = int(self.data.max_length) return [(self.data.name, URLField, field_kwargs)] diff --git a/src/fobi/contrib/plugins/form_handlers/http_repost/base.py b/src/fobi/contrib/plugins/form_handlers/http_repost/base.py index de12daf7..ab2c36cd 100644 --- a/src/fobi/contrib/plugins/form_handlers/http_repost/base.py +++ b/src/fobi/contrib/plugins/form_handlers/http_repost/base.py @@ -7,6 +7,8 @@ from django.conf import settings from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ +from six import PY3 + from .....base import ( form_handler_plugin_registry, form_wizard_handler_plugin_registry, diff --git a/src/fobi/contrib/plugins/form_handlers/mail/base.py b/src/fobi/contrib/plugins/form_handlers/mail/base.py index f329cbf3..e2616d45 100644 --- a/src/fobi/contrib/plugins/form_handlers/mail/base.py +++ b/src/fobi/contrib/plugins/form_handlers/mail/base.py @@ -4,7 +4,7 @@ import datetime from mimetypes import guess_type import os -from six import string_types +from six import string_types, PY3 from django.conf import settings from django.template.loader import render_to_string @@ -160,9 +160,13 @@ class MailHandlerPlugin(FormHandlerPlugin): os.path.join(settings.MEDIA_ROOT, '') ) mime_type = guess_type(imf.name) + if PY3: + imf_chunks = b''.join([c for c in imf.chunks()]) + else: + imf_chunks = ''.join([c for c in imf.chunks()]) files[field_name] = ( imf.name, - ''.join([c for c in imf.chunks()]), + imf_chunks, mime_type[0] if mime_type else '' ) @@ -296,9 +300,14 @@ class MailWizardHandlerPlugin(FormWizardHandlerPlugin): os.path.join(settings.MEDIA_ROOT, '') ) mime_type = guess_type(imf.name) + if PY3: + imf_chunks = b''.join([c for c in imf.chunks()]) + else: + imf_chunks = ''.join([c for c in imf.chunks()]) + files[field_name] = ( imf.name, - ''.join([c for c in imf.chunks()]), + imf_chunks, mime_type[0] if mime_type else '' ) diff --git a/src/fobi/forms.py b/src/fobi/forms.py index 41c83638..f28cb146 100644 --- a/src/fobi/forms.py +++ b/src/fobi/forms.py @@ -78,9 +78,11 @@ class FormEntryForm(forms.ModelForm): self.request = kwargs.pop('request', None) if self.request is None: raise ImproperlyConfigured( - ugettext("The {0} form requires a " - "request argument.".format(self.__class__.__name__)) + ugettext( + "The {0} form requires a " + "request argument.".format(self.__class__.__name__) ) + ) super(FormEntryForm, self).__init__(*args, **kwargs) theme = get_theme(request=None, as_instance=True) @@ -330,9 +332,11 @@ class FormWizardEntryForm(forms.ModelForm): self.request = kwargs.pop('request', None) if self.request is None: raise ImproperlyConfigured( - ugettext("The {0} form requires a " - "request argument.".format(self.__class__.__name__)) + ugettext( + "The {0} form requires a " + "request argument.".format(self.__class__.__name__) ) + ) super(FormWizardEntryForm, self).__init__(*args, **kwargs) theme = get_theme(request=None, as_instance=True) diff --git a/src/fobi/helpers.py b/src/fobi/helpers.py index bc6a0901..293bc690 100644 --- a/src/fobi/helpers.py +++ b/src/fobi/helpers.py @@ -400,7 +400,7 @@ def admin_change_url(app_label, module_name, object_id, extra_path='', return u'{1}'.format(url, url_title) else: return url - except: + except Exception: return None # ***************************************************************************** @@ -522,8 +522,10 @@ def validate_initial_for_multiple_choices(plugin_form, :return str: """ available_choices = dict( - get_select_field_choices(plugin_form.cleaned_data[field_name_choices]) - ).keys() + get_select_field_choices( + plugin_form.cleaned_data[field_name_choices] + ) + ).keys() if plugin_form.cleaned_data[field_name_initial]: for choice in plugin_form.cleaned_data[field_name_initial].split(','): diff --git a/src/fobi/tests/data.py b/src/fobi/tests/data.py index 1fc34b67..e2160f69 100644 --- a/src/fobi/tests/data.py +++ b/src/fobi/tests/data.py @@ -474,7 +474,7 @@ TEST_DYNAMIC_FORMS_DEFINITION_DATA = OrderedDict([ '{' '"name": "username", ' '"required": true, ' - '"max_length": "200", ' + '"max_length": 200, ' '"label": "Username"' '}' ) @@ -497,7 +497,7 @@ TEST_DYNAMIC_FORMS_DEFINITION_DATA = OrderedDict([ '{' '"name": "age", ' '"required": true, ' - '"max_value": "200", ' + '"max_value": 200, ' '"label": "Age"' '}' ) @@ -612,12 +612,12 @@ TEST_DYNAMIC_FORMS_OPTIONS_RESPONSE = OrderedDict([ (u'required', True), (u'read_only', False), (u'label', u'Username'), - (u'max_length', u'200')])), + (u'max_length', 200)])), (u'email', OrderedDict([(u'type', u'email'), (u'required', True), (u'read_only', False), (u'label', u'E-mail'), - (u'max_length', u'255')])), + (u'max_length', 255)])), (u'age', OrderedDict([(u'type', u'integer'), (u'required', True), (u'read_only', False), diff --git a/src/fobi/tests/helpers.py b/src/fobi/tests/helpers.py index 4607ab08..be769410 100644 --- a/src/fobi/tests/helpers.py +++ b/src/fobi/tests/helpers.py @@ -122,6 +122,9 @@ def create_form_with_entries(user=None, are being created even if form already exists (a database record). :param dict data: + :param bool is_public: + :param str name: + :param str slug: :return fobi.models.FormEntry: Instance of ``fobi.models.FormEntry`` with a number of form elements and handlers filled in. """ @@ -155,115 +158,6 @@ def create_form_with_entries(user=None, form_element_entry.save() position += 1 - # # ************************************************************************ - # # ******************************** Form elements ************************* - # # ************************************************************************ - # position = 1 - # # Text input - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=TextInputPlugin.uid, - # plugin_data='{"name": "username", "required": true, ' - # '"max_length": "200", "label": "Username"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Email - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=EmailInputPlugin.uid, - # plugin_data='{"name": "email", "required": true, "label": "E-mail"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Integer - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=IntegerInputPlugin.uid, - # plugin_data='{"name": "age", "required": true, ' - # '"max_value": "200", "label": "Age"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Boolean select - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=BooleanSelectPlugin.uid, - # plugin_data='{"name": "drivers_license", "required": false, ' - # '"label": "Drivers license?"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Hidden - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=HiddenInputPlugin.uid, - # plugin_data='{"name": "special_fields", "required": false, ' - # '"label": "Special fields"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Content image - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=ContentImagePlugin.uid, - # plugin_data='{"fit_method": "center", ' - # '"file": "fobi_plugins/content_plugin_images/04.jpg", ' - # '"alt": "Cute girl"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Integer - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=IntegerInputPlugin.uid, - # plugin_data='{"name": "number_of_children", "required": false, ' - # '"label": "Number of children"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Textarea - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=TextareaPlugin.uid, - # plugin_data='{"name": "bio", "required": true, "label": "Biography"}', - # position=position - # ) - # form_element_entry.save() - # position += 1 - # - # # Content text - # form_element_entry = FormElementEntry( - # form_entry=form_entry, - # plugin_uid=ContentTextPlugin.uid, - # plugin_data='' - # '{"text": "Suspendisse potenti. Etiam in nunc sodales, ' - # 'congue lectus ut, suscipit massa. In commodo fringilla ' - # 'orci, in varius eros gravida a! Aliquam erat volutpat. ' - # 'Donec sodales orci nec massa aliquam bibendum. Aenean ' - # 'sed condimentum velit. Mauris luctus bibendum nulla vel ' - # 'tempus. Integer tempor condimentum ligula sed feugiat. ' - # 'Aenean scelerisque ultricies vulputate. Donec semper ' - # 'lorem rhoncus sem cras amet."}', - # position=9 - # ) - # form_element_entry.save() - # position += 1 - # ************************************************************************ # ******************************** Form handlers ************************* # ************************************************************************ diff --git a/src/fobi/tests/test_form_importers_mailchimp.py b/src/fobi/tests/test_form_importers_mailchimp.py index c12ec3a2..08d8dca7 100644 --- a/src/fobi/tests/test_form_importers_mailchimp.py +++ b/src/fobi/tests/test_form_importers_mailchimp.py @@ -1,6 +1,6 @@ import unittest -from django.contrib.auth import get_user_model +# from django.contrib.auth import get_user_model from django.test import TestCase from fobi.contrib.plugins.form_importers \ diff --git a/src/fobi/utils.py b/src/fobi/utils.py index d6b385a5..126a575a 100644 --- a/src/fobi/utils.py +++ b/src/fobi/utils.py @@ -10,25 +10,28 @@ from django.conf import settings from django.contrib import messages from django.forms.widgets import TextInput from django.utils.encoding import force_text -from django.utils.translation import ugettext, ugettext_lazy as _ +from django.utils.translation import ( + ugettext, + # ugettext_lazy as _, +) from nine.versions import DJANGO_GTE_1_10 from six import PY3 from .base import ( + ensure_autodiscover, form_element_plugin_registry, form_handler_plugin_registry, form_wizard_handler_plugin_registry, get_registered_form_element_plugin_uids, get_registered_form_element_plugins, - ensure_autodiscover, - get_registered_form_handler_plugin_uids, - get_registered_form_wizard_handler_plugin_uids, - get_theme, - get_registered_form_handler_plugins, - get_registered_form_wizard_handler_plugins, get_registered_form_element_plugins_grouped, + get_registered_form_handler_plugin_uids, + get_registered_form_handler_plugins, + get_registered_form_wizard_handler_plugin_uids, + get_registered_form_wizard_handler_plugins, + get_theme, ) from .dynamic import assemble_form_class @@ -356,8 +359,8 @@ def get_user_form_element_plugins_grouped(user): ) -def get_user_form_field_plugin_uids(user): - """Get user form field plugin uids.""" +def get_user_form_element_plugin_uids(user): + """Get user form element plugin uids.""" return get_user_plugin_uids( get_allowed_form_element_plugin_uids, get_registered_form_element_plugin_uids, @@ -365,6 +368,11 @@ def get_user_form_field_plugin_uids(user): user ) + +# For backwards compatibility, if someone had ever used it. +get_user_form_field_plugin_uids = get_user_form_element_plugin_uids + + # **************************************************************************** # **************************************************************************** # *************************** Form handler specific ************************** @@ -573,7 +581,7 @@ def append_edit_and_delete_links_to_field(form_element_plugin, ) try: help_text = safe_text(form_element_plugin.data.help_text) - except: + except Exception: help_text = '' data_dict = { diff --git a/src/fobi/views.py b/src/fobi/views.py index 34ebda1c..b0f73771 100644 --- a/src/fobi/views.py +++ b/src/fobi/views.py @@ -8,7 +8,7 @@ from collections import OrderedDict import simplejson as json -from six import string_types +# from six import string_types from django.db import models, IntegrityError from django.contrib import messages @@ -82,7 +82,10 @@ from .utils import ( perform_form_entry_import, prepare_form_entry_export_data ) -from .wizard import DynamicSessionWizardView, DynamicCookieWizardView +from .wizard import ( + # DynamicCookieWizardView, + DynamicSessionWizardView, +) if versions.DJANGO_GTE_1_10: from django.shortcuts import render @@ -279,6 +282,7 @@ def dashboard(request, theme=None, template_name=None): template_name, context, context_instance=RequestContext(request) ) + # ***************************************************************************** # ****************************** Form wizards ********************************* # ***************************************************************************** @@ -326,6 +330,7 @@ def form_wizards_dashboard(request, theme=None, template_name=None): template_name, context, context_instance=RequestContext(request) ) + # ***************************************************************************** # ***************************************************************************** # ********************************** Builder ********************************** @@ -398,6 +403,7 @@ def create_form_entry(request, theme=None, template_name=None): template_name, context, context_instance=RequestContext(request) ) + # ************************************************************************** # ******************************* Edit form entry ************************** # ************************************************************************** @@ -487,14 +493,17 @@ def edit_form_entry(request, form_entry_id, theme=None, template_name=None): ) ) return redirect( - reverse('fobi.edit_form_entry', - kwargs={'form_entry_id': form_entry_id}) + reverse( + 'fobi.edit_form_entry', + kwargs={'form_entry_id': form_entry_id} ) + ) except IntegrityError as err: messages.info( request, - ugettext('Errors occurred while saving ' - 'the form: {0}.').format(str(err)) + ugettext( + 'Errors occurred while saving the form: {0}.' + ).format(str(err)) ) else: # The form entry form (does not contain form elements) @@ -578,6 +587,7 @@ def edit_form_entry(request, form_entry_id, theme=None, template_name=None): template_name, context, context_instance=RequestContext(request) ) + # ***************************************************************************** # ********************************* Delete form entry ************************* # ***************************************************************************** @@ -1119,6 +1129,7 @@ def delete_form_handler_entry(request, form_handler_entry_id): html_anchor='?active_tab=tab-form-handlers' ) + # ***************************************************************************** # ***************************************************************************** # ****************************** Form wizard ********************************** @@ -1194,6 +1205,7 @@ def create_form_wizard_entry(request, theme=None, template_name=None): template_name, context, context_instance=RequestContext(request) ) + # ************************************************************************** # *************************** Edit form wizard entry *********************** # ************************************************************************** @@ -1367,6 +1379,7 @@ def edit_form_wizard_entry(request, form_wizard_entry_id, theme=None, template_name, context, context_instance=RequestContext(request) ) + # ***************************************************************************** # **************************** Delete form wizard entry *********************** # ***************************************************************************** @@ -1431,7 +1444,7 @@ class FormWizardView(DynamicSessionWizardView): 'fobi_theme': self.fobi_theme, 'fobi_form_title': form_entry.title, 'fobi_form_wizard_title': self.form_wizard_entry.title, - 'steps_range': range(1, self.steps.count+1), + 'steps_range': range(1, self.steps.count + 1), }) return context_data @@ -1561,8 +1574,10 @@ class FormWizardView(DynamicSessionWizardView): field_key ) # Do not overwrite field data. Only empty or missing values. - if not (wizard_form_key in form.data - and form.data[wizard_form_key]): + if not ( + wizard_form_key in form.data + and form.data[wizard_form_key] + ): form.data[wizard_form_key] = field_value # This is dirty hack to make wizard validate empty multiple @@ -1844,10 +1859,10 @@ def delete_form_wizard_form_entry(request, form_wizard_form_entry_id): """ try: obj = FormWizardFormEntry \ - ._default_manager \ - .select_related('form_wizard_entry') \ - .get(pk=form_wizard_form_entry_id, - form_wizard_entry__user__pk=request.user.pk) + .objects \ + .select_related('form_wizard_entry') \ + .get(pk=form_wizard_form_entry_id, + form_wizard_entry__user__pk=request.user.pk) except ObjectDoesNotExist as err: raise Http404( ugettext("{0} not found.").format(