diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e1d97aed..5cd2b3d1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,22 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.10.8 +------ +yyyy-mm-dd (not yet released) + +- Documentation fixes. +- PEP8 code fixes. +- Minor setup fixes related to moved screen-shots file. +- Added helper scripts to test with Firefox in headless mode. Describe + testing with Firefox in headless mode in documentation. + +0.10.7 +------ +2017-03-13 + +- Several Django deprecation/moves fixes for better future compatibility. + 0.10.6 ------ 2017-02-14 diff --git a/QUICK_START.rst b/QUICK_START.rst index 4084fb25..554797bc 100644 --- a/QUICK_START.rst +++ b/QUICK_START.rst @@ -16,14 +16,14 @@ Installation and configuration ------------------------------ Install the package in your environment. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: none +.. code-block:: sh pip install django-fobi INSTALLED_APPS ^^^^^^^^^^^^^^ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your -`settings` module. +``settings`` module. 1. The core. @@ -47,7 +47,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your `_ would require additional packages to be installed. If so, make sure to have installed and configured those dependencies prior adding the dependant - add-ons to the `settings` module. + add-ons to the ``settings`` module. .. code-block:: python @@ -82,7 +82,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your .. code-block:: python - 'easy_thumbnails', # Required by `content_image` plugin + 'easy_thumbnails', # Required by `content_image` plugin 'fobi.contrib.plugins.form_elements.content.content_image', 'fobi.contrib.plugins.form_elements.content.content_text', 'fobi.contrib.plugins.form_elements.content.content_video', @@ -145,7 +145,7 @@ Putting all together, you would have something like this. 'fobi.contrib.plugins.form_elements.fields.url', # Form element plugins - 'easy_thumbnails', # Required by `content_image` plugin + 'easy_thumbnails', # Required by ``content_image`` plugin 'fobi.contrib.plugins.form_elements.content.content_image', 'fobi.contrib.plugins.form_elements.content.content_text', 'fobi.contrib.plugins.form_elements.content.content_video', @@ -162,21 +162,21 @@ TEMPLATE_CONTEXT_PROCESSORS ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add ``django.core.context_processors.request`` and ``fobi.context_processors.theme`` to ``TEMPLATE_CONTEXT_PROCESSORS`` of -your `settings` module. +your ``settings`` module. .. code-block:: python TEMPLATE_CONTEXT_PROCESSORS = ( # ... "django.core.context_processors.request", - "fobi.context_processors.theme", # Obligatory - "fobi.context_processors.dynamic_values", # Optional + "fobi.context_processors.theme", # Obligatory + "fobi.context_processors.dynamic_values", # Optional # ... ) urlpatterns ^^^^^^^^^^^ -Add the following line to ``urlpatterns`` of your `urls` module. +Add the following line to ``urlpatterns`` of your ``urls`` module. .. code-block:: python @@ -201,21 +201,21 @@ Update the database 1. First you should be syncing/migrating the database. Depending on your Django version and migration app, this step may vary. Typically as follows: -.. code-block:: none +.. code-block:: sh - $ ./manage.py syncdb - $ ./manage.py migrate --fake-initial + ./manage.py syncdb + ./manage.py migrate --fake-initial 2. Sync installed ``fobi`` plugins. Go to terminal and type the following command. -.. code-block:: none +.. code-block:: sh - $ ./manage.py fobi_sync_plugins + ./manage.py fobi_sync_plugins Specify the active theme ^^^^^^^^^^^^^^^^^^^^^^^^ -Specify the default theme in your `settings` module. +Specify the default theme in your ``settings`` module. .. code-block:: python diff --git a/README.rst b/README.rst index 5f3f0b38..6e55e84f 100644 --- a/README.rst +++ b/README.rst @@ -302,8 +302,9 @@ Add the following line to urlpatterns of your `urls` module. url(r'^fobi/', include('fobi.urls.edit')), Note, that some plugins require additional URL includes. For instance, if you -listed the `fobi.contrib.plugins.form_handlers.db_store` form handler plugin -in the ``INSTALLED_APPS``, you should mention the following in `urls` module. +listed the ``fobi.contrib.plugins.form_handlers.db_store`` form handler plugin +in the ``INSTALLED_APPS``, you should mention the following in ``urls`` +module. .. code-block:: python @@ -344,8 +345,8 @@ There are several properties, each textarea should have. They are: - `required` (bool): Flag, which tells us whether the field is required or optional. -Let's name that plugin `sample_textarea`. The plugin directory should then have -the following structure. +Let's name that plugin ``sample_textarea``. The plugin directory should then +have the following structure. .. code-block:: sh @@ -368,7 +369,7 @@ Define and register the form element plugin ------------------------------------------- Step by step review of a how to create and register a plugin and plugin widgets. Note, that `django-fobi` auto-discovers your plugins if you place -them into a file named `fobi_form_elements.py` of any Django app listed in +them into a file named ``fobi_form_elements.py`` of any Django app listed in ``INSTALLED_APPS`` of your Django projects' settings module. path/to/sample_textarea/fobi_form_elements.py @@ -475,11 +476,11 @@ path/to/sample_textarea/forms.py ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Why to have another file for defining forms? Just to keep the code clean and less messy, although you could perfectly define all your plugin forms in the -module `fobi_form_elements.py`, it's recommended to keep it separate. +module ``fobi_form_elements.py``, it's recommended to keep it separate. -Take into consideration, that `forms.py` is not an auto-discovered file pattern. -All your form element plugins should be registered in modules named -`fobi_form_elements.py`. +Take into consideration, that ``forms.py`` is not an auto-discovered file +pattern. All your form element plugins should be registered in modules named +``fobi_form_elements.py``. Required imports. @@ -631,7 +632,7 @@ Do check the source code as example. Define and register the form handler plugin ------------------------------------------- -Let's name that plugin `sample_mail`. The plugin directory should then have +Let's name that plugin ``sample_mail``. The plugin directory should then have the following structure. .. code-block:: text @@ -704,11 +705,11 @@ plugin is configurable, it should have a form. Why to have another file for defining forms? Just to keep the code clean and less messy, although you could perfectly define all your plugin forms in the -module `fobi_form_handlers.py`, it's recommended to keep it separate. +module ``fobi_form_handlers.py``, it's recommended to keep it separate. -Take into consideration, that `forms.py` is not an auto-discovered file pattern. -All your form handler plugins should be registered in modules named -`fobi_form_handlers.py`. +Take into consideration, that ``forms.py`` is not an auto-discovered file +pattern. All your form handler plugins should be registered in modules named +``fobi_form_handlers.py``. Required imports. @@ -837,8 +838,8 @@ existing MailChimp forms into `django-fobi`. Define and register the form importer plugin -------------------------------------------- -Let's name that plugin `sample_importer`. The plugin directory should then have -the following structure. +Let's name that plugin ``sample_importer``. The plugin directory should then +have the following structure. .. code-block:: text @@ -938,7 +939,7 @@ Required imports. from django import forms from django.utils.translation import ugettext_lazy as _ - from sample_service_api import sample_api # Just an imaginary API client + from sample_service_api import sample_api # Just an imaginary API client Defining the form for Sample importer plugin. @@ -988,7 +989,8 @@ Required imports. from formtools.wizard.views import SessionWizardView from path.to.sample_importer.forms import ( - SampleImporterStep1Form, SampleImporterStep2Form + SampleImporterStep1Form, + SampleImporterStep2Form, ) Defining the wizard view for Sample importer plugin. @@ -1076,9 +1078,8 @@ Creating a form callback Form callbacks are additional hooks, that are executed on various stages of the form submission. -Let's place the callback in the `foo` module. The plugin directory should then -have the following -structure. +Let's place the callback in the ``foo`` module. The plugin directory should +then have the following structure. .. code-block:: text @@ -1162,7 +1163,7 @@ themes: - "Foundation 5" theme - "Simple" theme in (with editing interface in style of the Django admin) - "DjangoCMS admin style" theme (which is another simple theme with editing - interface in style of `djangocms-admin-style`) + interface in style of ``djangocms-admin-style``) Obviously, there are two sorts of views when it comes to editing and viewing the form. @@ -1192,7 +1193,7 @@ the "Simple" theme is the best start, since it looks just like django-admin. Create a new theme ------------------ -Let's place the theme in the `sample_theme` module. The theme directory +Let's place the theme in the ``sample_theme`` module. The theme directory should then have the following structure. .. code-block:: text @@ -1292,7 +1293,7 @@ Registering the ``SampleTheme`` plugin. Sometimes you would want to attach additional properties to the theme in order to use them later in templates (remember, current theme object -is always available in templates under name `fobi_theme`). +is always available in templates under name ``fobi_theme``). For such cases you would need to define a variable in your project's settings module, called ``FOBI_CUSTOM_THEME_DATA``. See the following code as example: @@ -1742,7 +1743,7 @@ The following HTML5 fields are supported in corresponding bundled plugins: - placeholder - type -With the `fobi.contrib.plugins.form_elements.fields.input` support for +With the ``fobi.contrib.plugins.form_elements.fields.input`` support for HTML5 fields is extended to the following fields: - autocomplete @@ -1769,7 +1770,7 @@ Dynamic initial values It's possible to provide a dynamic initial value for any of the text elements. In order to do that, you should use the build-in context processor or make your own one. The only requirement is that you should store all values that -should be exposes in the form as a dict for `fobi_dynamic_values` dictionary +should be exposes in the form as a dict for ``fobi_dynamic_values`` dictionary key. Beware, that passing the original request object might be unsafe in many ways. Currently, a stripped down version of the request object is being passed as a context variable. @@ -1793,7 +1794,8 @@ passed as a context variable. } } -In your GUI, you should be refering to the initial values in the following way: +In your GUI, you should be referring to the initial values in the following +way: .. code-block:: html @@ -1807,21 +1809,21 @@ Currently, the following variables are available in the - request: Stripped HttpRequest object. - - request.path: A string representing the full path to the requested page, - not including the scheme or domain. + - request.path: A string representing the full path to the requested + page, not including the scheme or domain. - - request.get_full_path(): Returns the path, plus an appended query string, - if applicable. + - request.get_full_path(): Returns the path, plus an appended query + string, if applicable. - - request.is_secure(): Returns True if the request is secure; that is, if - it was made with HTTPS. + - request.is_secure(): Returns True if the request is secure; that + is, if it was made with HTTPS. - request.is_ajax(): Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. - - request.META: A stripped down standard Python dictionary containing the - available HTTP headers. + - request.META: A stripped down standard Python dictionary containing + the available HTTP headers. - HTTP_ACCEPT_ENCODING: Acceptable encodings for the response. @@ -1833,7 +1835,7 @@ Currently, the following variables are available in the - HTTP_USER_AGENT: The client’s user-agent string. - - QUERY_STRING: The query string, as a single (unparsed) string. + - QUERY_STRING: The query string, as a single (un-parsed) string. - REMOTE_ADDR: The IP address of the client. @@ -1841,9 +1843,9 @@ Currently, the following variables are available in the - request.user.email: - - request.user.get_username(): Returns the username for the user. Since - the User model can be swapped out, you should use this method - instead of referencing the username attribute directly. + - request.user.get_username(): Returns the username for the user. + Since the User model can be swapped out, you should use this + method instead of referencing the username attribute directly. - request.user.get_full_name(): Returns the first_name plus the last_name, with a space in between. @@ -2038,10 +2040,11 @@ install the test requirements: Browser tests ------------- -For browser tests you may choose between Firefox and PhantomJS. PhantomJS is -faster, Firefox tests tell you more. Both cases require some effort and both -have disadvantages regarding the installation (although once you have them -installed they work perfect). +For browser tests you may choose between Firefox, headless Firefox and +PhantomJS. PhantomJS is faster, headless Firefox is fast as well, but +normal Firefox tests tell you more (as you see what exactly happens on the +screen). Both cases require some effort and both have disadvantages regarding +the installation (although once you have them installed they work perfect). Latest versions of Firefox are often not supported by Selenium. Current version of the Selenium for Python (2.53.6) works fine with Firefox 47. @@ -2063,10 +2066,31 @@ Set up Firefox 47 FIREFOX_BIN_PATH = '/usr/lib/firefox47/firefox' - If you set ``FIREFOX_BIN_PATH`` to None, system Firefox would be used. + If you set to use system Firefox, remove or comment-out the + ``FIREFOX_BIN_PATH`` setting. After that your Selenium tests would work. +Set up headless Firefox +~~~~~~~~~~~~~~~~~~~~~~~ +1. Install ``xvfb`` package which is used to start Firefox in headless mode. + + .. code-block:: sh + + sudo apt-get install xvfb + +2. Run the tests using headless Firefox. + + .. code-block:: sh + + ./scripts/runtests.sh + + Or run tox tests using headless Firefox. + + .. code-block:: sh + + ./scripts/tox.sh + Setup PhantomJS ~~~~~~~~~~~~~~~ You could also run tests in headless mode (faster). For that you will need @@ -2088,14 +2112,14 @@ PhantomJS. PHANTOM_JS_EXECUTABLE_PATH = "" - If you want to use Firefox for testing, set - ``PHANTOM_JS_EXECUTABLE_PATH`` to None. + If you want to use Firefox for testing, remove or comment-out the + ``PHANTOM_JS_EXECUTABLE_PATH`` setting. Troubleshooting =============== If you get a ``FormElementPluginDoesNotExist`` or a ``FormHandlerPluginDoesNotExist`` exception, make sure you have listed your -plugin in the `settings` module of your project. +plugin in the ``settings`` module of your project. License ======= diff --git a/docs/index.rst b/docs/index.rst index 1136d1e2..e0efc2bf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -302,8 +302,9 @@ Add the following line to urlpatterns of your `urls` module. url(r'^fobi/', include('fobi.urls.edit')), Note, that some plugins require additional URL includes. For instance, if you -listed the `fobi.contrib.plugins.form_handlers.db_store` form handler plugin -in the ``INSTALLED_APPS``, you should mention the following in `urls` module. +listed the ``fobi.contrib.plugins.form_handlers.db_store`` form handler plugin +in the ``INSTALLED_APPS``, you should mention the following in ``urls`` +module. .. code-block:: python @@ -344,8 +345,8 @@ There are several properties, each textarea should have. They are: - `required` (bool): Flag, which tells us whether the field is required or optional. -Let's name that plugin `sample_textarea`. The plugin directory should then have -the following structure. +Let's name that plugin ``sample_textarea``. The plugin directory should then +have the following structure. .. code-block:: sh @@ -368,7 +369,7 @@ Define and register the form element plugin ------------------------------------------- Step by step review of a how to create and register a plugin and plugin widgets. Note, that `django-fobi` auto-discovers your plugins if you place -them into a file named `fobi_form_elements.py` of any Django app listed in +them into a file named ``fobi_form_elements.py`` of any Django app listed in ``INSTALLED_APPS`` of your Django projects' settings module. path/to/sample_textarea/fobi_form_elements.py @@ -475,11 +476,11 @@ path/to/sample_textarea/forms.py ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Why to have another file for defining forms? Just to keep the code clean and less messy, although you could perfectly define all your plugin forms in the -module `fobi_form_elements.py`, it's recommended to keep it separate. +module ``fobi_form_elements.py``, it's recommended to keep it separate. -Take into consideration, that `forms.py` is not an auto-discovered file pattern. -All your form element plugins should be registered in modules named -`fobi_form_elements.py`. +Take into consideration, that ``forms.py`` is not an auto-discovered file +pattern. All your form element plugins should be registered in modules named +``fobi_form_elements.py``. Required imports. @@ -631,7 +632,7 @@ Do check the source code as example. Define and register the form handler plugin ------------------------------------------- -Let's name that plugin `sample_mail`. The plugin directory should then have +Let's name that plugin ``sample_mail``. The plugin directory should then have the following structure. .. code-block:: text @@ -704,11 +705,11 @@ plugin is configurable, it should have a form. Why to have another file for defining forms? Just to keep the code clean and less messy, although you could perfectly define all your plugin forms in the -module `fobi_form_handlers.py`, it's recommended to keep it separate. +module ``fobi_form_handlers.py``, it's recommended to keep it separate. -Take into consideration, that `forms.py` is not an auto-discovered file pattern. -All your form handler plugins should be registered in modules named -`fobi_form_handlers.py`. +Take into consideration, that ``forms.py`` is not an auto-discovered file +pattern. All your form handler plugins should be registered in modules named +``fobi_form_handlers.py``. Required imports. @@ -837,8 +838,8 @@ existing MailChimp forms into `django-fobi`. Define and register the form importer plugin -------------------------------------------- -Let's name that plugin `sample_importer`. The plugin directory should then have -the following structure. +Let's name that plugin ``sample_importer``. The plugin directory should then +have the following structure. .. code-block:: text @@ -938,7 +939,7 @@ Required imports. from django import forms from django.utils.translation import ugettext_lazy as _ - from sample_service_api import sample_api # Just an imaginary API client + from sample_service_api import sample_api # Just an imaginary API client Defining the form for Sample importer plugin. @@ -988,7 +989,8 @@ Required imports. from formtools.wizard.views import SessionWizardView from path.to.sample_importer.forms import ( - SampleImporterStep1Form, SampleImporterStep2Form + SampleImporterStep1Form, + SampleImporterStep2Form, ) Defining the wizard view for Sample importer plugin. @@ -1076,9 +1078,8 @@ Creating a form callback Form callbacks are additional hooks, that are executed on various stages of the form submission. -Let's place the callback in the `foo` module. The plugin directory should then -have the following -structure. +Let's place the callback in the ``foo`` module. The plugin directory should +then have the following structure. .. code-block:: text @@ -1162,7 +1163,7 @@ themes: - "Foundation 5" theme - "Simple" theme in (with editing interface in style of the Django admin) - "DjangoCMS admin style" theme (which is another simple theme with editing - interface in style of `djangocms-admin-style`) + interface in style of ``djangocms-admin-style``) Obviously, there are two sorts of views when it comes to editing and viewing the form. @@ -1192,7 +1193,7 @@ the "Simple" theme is the best start, since it looks just like django-admin. Create a new theme ------------------ -Let's place the theme in the `sample_theme` module. The theme directory +Let's place the theme in the ``sample_theme`` module. The theme directory should then have the following structure. .. code-block:: text @@ -1292,7 +1293,7 @@ Registering the ``SampleTheme`` plugin. Sometimes you would want to attach additional properties to the theme in order to use them later in templates (remember, current theme object -is always available in templates under name `fobi_theme`). +is always available in templates under name ``fobi_theme``). For such cases you would need to define a variable in your project's settings module, called ``FOBI_CUSTOM_THEME_DATA``. See the following code as example: @@ -1742,7 +1743,7 @@ The following HTML5 fields are supported in corresponding bundled plugins: - placeholder - type -With the `fobi.contrib.plugins.form_elements.fields.input` support for +With the ``fobi.contrib.plugins.form_elements.fields.input`` support for HTML5 fields is extended to the following fields: - autocomplete @@ -1769,7 +1770,7 @@ Dynamic initial values It's possible to provide a dynamic initial value for any of the text elements. In order to do that, you should use the build-in context processor or make your own one. The only requirement is that you should store all values that -should be exposes in the form as a dict for `fobi_dynamic_values` dictionary +should be exposes in the form as a dict for ``fobi_dynamic_values`` dictionary key. Beware, that passing the original request object might be unsafe in many ways. Currently, a stripped down version of the request object is being passed as a context variable. @@ -1793,7 +1794,8 @@ passed as a context variable. } } -In your GUI, you should be refering to the initial values in the following way: +In your GUI, you should be referring to the initial values in the following +way: .. code-block:: html @@ -1807,21 +1809,21 @@ Currently, the following variables are available in the - request: Stripped HttpRequest object. - - request.path: A string representing the full path to the requested page, - not including the scheme or domain. + - request.path: A string representing the full path to the requested + page, not including the scheme or domain. - - request.get_full_path(): Returns the path, plus an appended query string, - if applicable. + - request.get_full_path(): Returns the path, plus an appended query + string, if applicable. - - request.is_secure(): Returns True if the request is secure; that is, if - it was made with HTTPS. + - request.is_secure(): Returns True if the request is secure; that + is, if it was made with HTTPS. - request.is_ajax(): Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. - - request.META: A stripped down standard Python dictionary containing the - available HTTP headers. + - request.META: A stripped down standard Python dictionary containing + the available HTTP headers. - HTTP_ACCEPT_ENCODING: Acceptable encodings for the response. @@ -1833,7 +1835,7 @@ Currently, the following variables are available in the - HTTP_USER_AGENT: The client’s user-agent string. - - QUERY_STRING: The query string, as a single (unparsed) string. + - QUERY_STRING: The query string, as a single (un-parsed) string. - REMOTE_ADDR: The IP address of the client. @@ -1841,9 +1843,9 @@ Currently, the following variables are available in the - request.user.email: - - request.user.get_username(): Returns the username for the user. Since - the User model can be swapped out, you should use this method - instead of referencing the username attribute directly. + - request.user.get_username(): Returns the username for the user. + Since the User model can be swapped out, you should use this + method instead of referencing the username attribute directly. - request.user.get_full_name(): Returns the first_name plus the last_name, with a space in between. @@ -2038,10 +2040,11 @@ install the test requirements: Browser tests ------------- -For browser tests you may choose between Firefox and PhantomJS. PhantomJS is -faster, Firefox tests tell you more. Both cases require some effort and both -have disadvantages regarding the installation (although once you have them -installed they work perfect). +For browser tests you may choose between Firefox, headless Firefox and +PhantomJS. PhantomJS is faster, headless Firefox is fast as well, but +normal Firefox tests tell you more (as you see what exactly happens on the +screen). Both cases require some effort and both have disadvantages regarding +the installation (although once you have them installed they work perfect). Latest versions of Firefox are often not supported by Selenium. Current version of the Selenium for Python (2.53.6) works fine with Firefox 47. @@ -2063,10 +2066,31 @@ Set up Firefox 47 FIREFOX_BIN_PATH = '/usr/lib/firefox47/firefox' - If you set ``FIREFOX_BIN_PATH`` to None, system Firefox would be used. + If you set to use system Firefox, remove or comment-out the + ``FIREFOX_BIN_PATH`` setting. After that your Selenium tests would work. +Set up headless Firefox +~~~~~~~~~~~~~~~~~~~~~~~ +1. Install ``xvfb`` package which is used to start Firefox in headless mode. + + .. code-block:: sh + + sudo apt-get install xvfb + +2. Run the tests using headless Firefox. + + .. code-block:: sh + + ./scripts/runtests.sh + + Or run tox tests using headless Firefox. + + .. code-block:: sh + + ./scripts/tox.sh + Setup PhantomJS ~~~~~~~~~~~~~~~ You could also run tests in headless mode (faster). For that you will need @@ -2088,14 +2112,14 @@ PhantomJS. PHANTOM_JS_EXECUTABLE_PATH = "" - If you want to use Firefox for testing, set - ``PHANTOM_JS_EXECUTABLE_PATH`` to None. + If you want to use Firefox for testing, remove or comment-out the + ``PHANTOM_JS_EXECUTABLE_PATH`` setting. Troubleshooting =============== If you get a ``FormElementPluginDoesNotExist`` or a ``FormHandlerPluginDoesNotExist`` exception, make sure you have listed your -plugin in the `settings` module of your project. +plugin in the ``settings`` module of your project. License ======= diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 4084fb25..554797bc 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -16,14 +16,14 @@ Installation and configuration ------------------------------ Install the package in your environment. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: none +.. code-block:: sh pip install django-fobi INSTALLED_APPS ^^^^^^^^^^^^^^ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your -`settings` module. +``settings`` module. 1. The core. @@ -47,7 +47,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your `_ would require additional packages to be installed. If so, make sure to have installed and configured those dependencies prior adding the dependant - add-ons to the `settings` module. + add-ons to the ``settings`` module. .. code-block:: python @@ -82,7 +82,7 @@ Add ``fobi`` core and the plugins to the ``INSTALLED_APPS`` of the your .. code-block:: python - 'easy_thumbnails', # Required by `content_image` plugin + 'easy_thumbnails', # Required by `content_image` plugin 'fobi.contrib.plugins.form_elements.content.content_image', 'fobi.contrib.plugins.form_elements.content.content_text', 'fobi.contrib.plugins.form_elements.content.content_video', @@ -145,7 +145,7 @@ Putting all together, you would have something like this. 'fobi.contrib.plugins.form_elements.fields.url', # Form element plugins - 'easy_thumbnails', # Required by `content_image` plugin + 'easy_thumbnails', # Required by ``content_image`` plugin 'fobi.contrib.plugins.form_elements.content.content_image', 'fobi.contrib.plugins.form_elements.content.content_text', 'fobi.contrib.plugins.form_elements.content.content_video', @@ -162,21 +162,21 @@ TEMPLATE_CONTEXT_PROCESSORS ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add ``django.core.context_processors.request`` and ``fobi.context_processors.theme`` to ``TEMPLATE_CONTEXT_PROCESSORS`` of -your `settings` module. +your ``settings`` module. .. code-block:: python TEMPLATE_CONTEXT_PROCESSORS = ( # ... "django.core.context_processors.request", - "fobi.context_processors.theme", # Obligatory - "fobi.context_processors.dynamic_values", # Optional + "fobi.context_processors.theme", # Obligatory + "fobi.context_processors.dynamic_values", # Optional # ... ) urlpatterns ^^^^^^^^^^^ -Add the following line to ``urlpatterns`` of your `urls` module. +Add the following line to ``urlpatterns`` of your ``urls`` module. .. code-block:: python @@ -201,21 +201,21 @@ Update the database 1. First you should be syncing/migrating the database. Depending on your Django version and migration app, this step may vary. Typically as follows: -.. code-block:: none +.. code-block:: sh - $ ./manage.py syncdb - $ ./manage.py migrate --fake-initial + ./manage.py syncdb + ./manage.py migrate --fake-initial 2. Sync installed ``fobi`` plugins. Go to terminal and type the following command. -.. code-block:: none +.. code-block:: sh - $ ./manage.py fobi_sync_plugins + ./manage.py fobi_sync_plugins Specify the active theme ^^^^^^^^^^^^^^^^^^^^^^^^ -Specify the default theme in your `settings` module. +Specify the default theme in your ``settings`` module. .. code-block:: python diff --git a/scripts/runtests.sh b/scripts/runtests.sh new file mode 100755 index 00000000..d82c3774 --- /dev/null +++ b/scripts/runtests.sh @@ -0,0 +1 @@ +xvfb-run python runtests.py diff --git a/scripts/tox.sh b/scripts/tox.sh new file mode 100755 index 00000000..813a3044 --- /dev/null +++ b/scripts/tox.sh @@ -0,0 +1 @@ +xvfb-run python toxtests.py diff --git a/setup.py b/setup.py index b9e61e51..4e329c5e 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import sys from distutils.version import LooseVersion from setuptools import setup, find_packages -version = '0.10.6' +version = '0.10.7' # *************************************************************************** # ************************** Python version ********************************* @@ -78,7 +78,7 @@ except Exception as err: try: readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read() screenshots = open( - os.path.join(os.path.dirname(__file__), 'SCREENSHOTS.rst') + os.path.join(os.path.dirname(__file__), 'docs/screenshots.rst.distrib') ).read() screenshots = screenshots.replace( '.. image:: _static', diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index 69733cf5..748ba227 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.10.6' -__build__ = 0x000079 +__version__ = '0.10.7' +__build__ = 0x00007a __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/admin.py b/src/fobi/admin.py index 4b1dfa87..c9aa113b 100644 --- a/src/fobi/admin.py +++ b/src/fobi/admin.py @@ -81,7 +81,7 @@ def base_bulk_change_plugins(PluginForm, named_url, modeladmin, request, post = dict(request.POST) if selected: post['selected_plugins'] = ','.join(selected) - if 'POST' == request.method: + if request.method == 'POST': form = PluginForm( data=post, files=request.FILES, @@ -455,7 +455,7 @@ class BasePluginModelAdmin(admin.ModelAdmin): This is where the data is actually processed. """ changelist_named_url = self._get_changelist_named_url() - if 'POST' == request.method: + if request.method == 'POST': form_cls = self._get_bulk_change_form_class() form = form_cls( data=request.POST, diff --git a/src/fobi/contrib/plugins/form_handlers/db_store/fobi_form_handlers.py b/src/fobi/contrib/plugins/form_handlers/db_store/fobi_form_handlers.py index 5895ad42..a8b64099 100644 --- a/src/fobi/contrib/plugins/form_handlers/db_store/fobi_form_handlers.py +++ b/src/fobi/contrib/plugins/form_handlers/db_store/fobi_form_handlers.py @@ -2,9 +2,10 @@ import datetime import simplejson as json -from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ +from nine.versions import DJANGO_GTE_1_10 + from fobi.base import ( # General get_processed_form_data, @@ -24,6 +25,11 @@ from fobi.helpers import get_form_element_entries_for_form_wizard_entry from . import UID from .models import SavedFormDataEntry, SavedFormWizardDataEntry +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.contrib.plugins.form_handlers.db_store.fobi_form_handlers' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/contrib/plugins/form_importers/mailchimp_importer/views.py b/src/fobi/contrib/plugins/form_importers/mailchimp_importer/views.py index daa37006..a3ce6234 100644 --- a/src/fobi/contrib/plugins/form_importers/mailchimp_importer/views.py +++ b/src/fobi/contrib/plugins/form_importers/mailchimp_importer/views.py @@ -1,16 +1,22 @@ import logging -import mailchimp - from django.contrib import messages -from django.core.urlresolvers import reverse from django.shortcuts import redirect from django.utils.translation import ugettext_lazy as _ +import mailchimp + from fobi.wizard import SessionWizardView +from nine.versions import DJANGO_GTE_1_10 + from .forms import MailchimpAPIKeyForm, MailchimpListIDForm +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.contrib.plugins.form_importers.mailchimp_importer.views' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/dynamic.py b/src/fobi/dynamic.py index 35f01a09..2e0be25f 100644 --- a/src/fobi/dynamic.py +++ b/src/fobi/dynamic.py @@ -1,21 +1,28 @@ -from six import with_metaclass - -from django.core.urlresolvers import reverse from django.forms.forms import BaseForm from django.forms.widgets import media_property from django.http import HttpResponseRedirect -from nine.versions import DJANGO_GTE_1_7, DJANGO_GTE_1_8 +from nine.versions import ( + DJANGO_GTE_1_7, + DJANGO_GTE_1_8, + DJANGO_GTE_1_10, +) + +from six import with_metaclass from .constants import WIZARD_TYPE_COOKIE, WIZARD_TYPE_SESSION if DJANGO_GTE_1_8: from formtools.wizard.views import ( - WizardView, SessionWizardView, CookieWizardView + CookieWizardView, + SessionWizardView, + WizardView, ) else: from django.contrib.formtools.wizard.views import ( - WizardView, SessionWizardView, CookieWizardView + CookieWizardView, + SessionWizardView, + WizardView, ) if DJANGO_GTE_1_7: @@ -23,6 +30,11 @@ if DJANGO_GTE_1_7: else: from django.utils.datastructures import SortedDict as OrderedDict +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.dynamic' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/form_importers.py b/src/fobi/form_importers.py index d2d3135b..39f0ca0f 100644 --- a/src/fobi/form_importers.py +++ b/src/fobi/form_importers.py @@ -1,12 +1,17 @@ -from six import text_type +from nine.versions import DJANGO_GTE_1_10 import simplejson as json -from django.core.urlresolvers import reverse +from six import text_type from .base import BaseRegistry from .discover import autodiscover +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.form_importers' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/helpers.py b/src/fobi/helpers.py index 51bd6a62..a97a570d 100644 --- a/src/fobi/helpers.py +++ b/src/fobi/helpers.py @@ -3,47 +3,50 @@ Helpers module. This module can be safely imported from any fobi (sub)module, since it never imports from any of the fobi (sub)modules (except for the `fobi.constants` and `fobi.exceptions` modules). """ -import os import glob import logging -import uuid +import os import shutil - -from six import text_type, PY3 - -import simplejson as json - -from django.conf import settings -from django.core.urlresolvers import reverse -from django.core.files.base import File -from django.contrib.contenttypes.models import ContentType -from django.db.utils import DatabaseError -from django.utils.encoding import force_text -from django.utils.html import format_html_join -from django import forms -from django.utils.translation import ugettext_lazy as _ -from django.contrib.auth.models import AnonymousUser -from django.test.client import RequestFactory -from django.http import HttpResponse +import uuid from autoslug.settings import slugify -from nine.user import User -from nine.versions import DJANGO_GTE_1_7 +from django import forms +from django.conf import settings +from django.contrib.auth.models import AnonymousUser +# from django.contrib.contenttypes.models import ContentType +from django.core.files.base import File +# from django.db.utils import DatabaseError +from django.http import HttpResponse +from django.test.client import RequestFactory +from django.utils.encoding import force_text +from django.utils.html import format_html_join +from django.utils.translation import ugettext_lazy as _ -from fobi.constants import ( - SUBMIT_VALUE_AS_VAL, +from nine.user import User +from nine.versions import DJANGO_GTE_1_7, DJANGO_GTE_1_10 + +import simplejson as json + +from six import text_type, PY3 + +from .constants import ( + SUBMIT_VALUE_AS_MIX, SUBMIT_VALUE_AS_REPR, - SUBMIT_VALUE_AS_MIX + SUBMIT_VALUE_AS_VAL, ) -from fobi.exceptions import ImproperlyConfigured +from .exceptions import ImproperlyConfigured if DJANGO_GTE_1_7: import django.apps - else: from django.db import models +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.helpers' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' @@ -873,7 +876,7 @@ def get_wizard_form_field_value_from_request(request, return value # Then try POST - if 'POST' == request.method: + if request.method == 'POST': value = get_wizard_form_field_value_from_post( request, wizard_view_name, @@ -884,7 +887,7 @@ def get_wizard_form_field_value_from_request(request, else: # First try POST - if 'POST' == request.method: + if request.method == 'POST': value = get_wizard_form_field_value_from_post( request, wizard_view_name, diff --git a/src/fobi/integration/helpers.py b/src/fobi/integration/helpers.py index 8263b568..60cf0a1b 100644 --- a/src/fobi/integration/helpers.py +++ b/src/fobi/integration/helpers.py @@ -1,4 +1,4 @@ -from fobi.base import get_theme +from ..base import get_theme __title__ = 'fobi.integration.helpers' __author__ = 'Artur Barseghyan ' diff --git a/src/fobi/integration/processors.py b/src/fobi/integration/processors.py index 68d9b438..e45a8653 100644 --- a/src/fobi/integration/processors.py +++ b/src/fobi/integration/processors.py @@ -5,18 +5,22 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ -from fobi.base import ( - fire_form_callbacks, run_form_handlers, - submit_plugin_form_data, get_theme +from ..base import ( + fire_form_callbacks, + get_theme, + run_form_handlers, + submit_plugin_form_data, ) -from fobi.constants import ( - CALLBACK_BEFORE_FORM_VALIDATION, CALLBACK_FORM_INVALID, - CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, CALLBACK_FORM_VALID, - CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS +from ..constants import ( + CALLBACK_BEFORE_FORM_VALIDATION, + CALLBACK_FORM_INVALID, + CALLBACK_FORM_VALID, + CALLBACK_FORM_VALID_AFTER_FORM_HANDLERS, + CALLBACK_FORM_VALID_BEFORE_SUBMIT_PLUGIN_FORM_DATA, ) -from fobi.dynamic import assemble_form_class -from fobi.exceptions import ImproperlyConfigured -from fobi.settings import GET_PARAM_INITIAL_DATA +from ..dynamic import assemble_form_class +from ..exceptions import ImproperlyConfigured +from ..settings import GET_PARAM_INITIAL_DATA __title__ = 'fobi.integration.processors' __author__ = 'Artur Barseghyan ' @@ -70,6 +74,7 @@ class IntegrationProcessor(object): ) def get_context_data(self, request, instance, **kwargs): + """Get context data.""" context = { 'form_entry': instance.form_entry, } @@ -77,12 +82,15 @@ class IntegrationProcessor(object): return context def get_form_template_name(self, request, instance): + """Get form template name.""" return instance.form_template_name or None def get_success_page_template_name(self, request, instance): + """Get succes page template name.""" return instance.success_page_template_name or None def get_login_required_template_name(self, request, instance): + """Get login required template name.""" return self.login_required_template_name or None def _process_form(self, request, instance, **kwargs): @@ -121,7 +129,7 @@ class IntegrationProcessor(object): request=request ) - if 'POST' == request.method: + if request.method == 'POST': form = FormClass(request.POST, request.FILES) # Fire pre form validation callbacks @@ -133,8 +141,7 @@ class IntegrationProcessor(object): ) if form.is_valid(): - # Fire form valid callbacks, before handling sufrom - # django.http import HttpResponseRedirectbmitted plugin + # Fire form valid callbacks, before handling submitted plugin # form data form = fire_form_callbacks( form_entry=instance.form_entry, diff --git a/src/fobi/models.py b/src/fobi/models.py index 4533054a..cdea0001 100644 --- a/src/fobi/models.py +++ b/src/fobi/models.py @@ -2,13 +2,14 @@ from __future__ import absolute_import import logging +from autoslug import AutoSlugField + from django.conf import settings from django.contrib.auth.models import Group -from django.core.urlresolvers import reverse from django.db import models from django.utils.translation import ugettext_lazy as _ -from autoslug import AutoSlugField +from nine.versions import DJANGO_GTE_1_10 from six import python_2_unicode_compatible @@ -18,10 +19,15 @@ from .base import ( form_wizard_handler_plugin_registry, get_registered_form_element_plugins, get_registered_form_handler_plugins, - get_registered_form_wizard_handler_plugins + get_registered_form_wizard_handler_plugins, ) from .constants import WIZARD_TYPES, DEFAULT_WIZARD_TYPE +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.models' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/templatetags/fobi_tags.py b/src/fobi/templatetags/fobi_tags.py index c8dfce81..d2282e19 100644 --- a/src/fobi/templatetags/fobi_tags.py +++ b/src/fobi/templatetags/fobi_tags.py @@ -30,7 +30,7 @@ __all__ = ( THEME = get_theme(request=None, as_instance=True) -REGISTER = Library() +register = Library() # ***************************************************************************** # ***************************************************************************** @@ -63,7 +63,7 @@ class GetFobiPluginNode(Node): return '' -@REGISTER.tag +@register.tag def get_fobi_plugin(parser, token): """Get the plugin. @@ -126,7 +126,7 @@ class GetFobiFormHandlerPluginCustomActionsNode(Node): return '' -@REGISTER.tag +@register.tag def get_fobi_form_handler_plugin_custom_actions(parser, token): """Get the form handler plugin custom actions. @@ -192,7 +192,7 @@ class GetFobiFormWizardHandlerPluginCustomActionsNode(Node): return '' -@REGISTER.tag +@register.tag def get_fobi_form_wizard_handler_plugin_custom_actions(parser, token): """Get the form wizard handler plugin custom actions. @@ -275,12 +275,12 @@ def render_auth_link(context): } -REGISTER.inclusion_tag( +register.inclusion_tag( 'fobi/snippets/render_auth_link.html', takes_context=True )(render_auth_link) -@REGISTER.inclusion_tag(THEME.forms_list_template, takes_context=True) +@register.inclusion_tag(THEME.forms_list_template, takes_context=True) def render_fobi_forms_list(context, queryset, *args, **kwargs): """Render the list of fobi forms. @@ -366,7 +366,7 @@ class HasEditFormEntryPermissionsNode(Node): return False -@REGISTER.tag +@register.tag def has_edit_form_entry_permissions(parser, token): """Checks the permissions @@ -456,7 +456,7 @@ class GetFormFieldTypeNode(Node): return '' -@REGISTER.tag +@register.tag def get_form_field_type(parser, token): """Get form field type. @@ -515,7 +515,7 @@ class GetFormHiddenFieldsErrorsNode(Node): return '' -@REGISTER.tag +@register.tag def get_form_hidden_fields_errors(parser, token): """Get form hidden fields errors. diff --git a/src/fobi/templatetags/future_compat.py b/src/fobi/templatetags/future_compat.py index 3053061f..3d16a3b2 100644 --- a/src/fobi/templatetags/future_compat.py +++ b/src/fobi/templatetags/future_compat.py @@ -20,7 +20,7 @@ except ImportError: from django.utils.safestring import mark_safe, EscapeData, SafeData from django.utils.timezone import template_localtime - REGISTER = Library() + register = Library() def render_value_in_context(value, context): """Render value in context. @@ -56,7 +56,7 @@ except ImportError: return render_value_in_context(value, context) return '' - @REGISTER.tag + @register.tag def firstof(parser, token, escape=False): """Outputs the first variable passed that is not False. diff --git a/src/fobi/tests/test_browser_build_dynamic_forms.py b/src/fobi/tests/test_browser_build_dynamic_forms.py index 57fde797..4469ec8c 100644 --- a/src/fobi/tests/test_browser_build_dynamic_forms.py +++ b/src/fobi/tests/test_browser_build_dynamic_forms.py @@ -11,12 +11,13 @@ from selenium.webdriver.support.wait import WebDriverWait from selenium.common.exceptions import WebDriverException from django.core.management import call_command -from django.core.urlresolvers import reverse from django.test import LiveServerTestCase from django.conf import settings from fobi.models import FormEntry +from nine.versions import DJANGO_GTE_1_10 + from . import constants from .base import print_info, skip from .data import ( @@ -31,6 +32,10 @@ from .helpers import ( phantom_js_clean_up ) +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse __title__ = 'fobi.tests.test_browser_build_dynamic_forms' __author__ = 'Artur Barseghyan ' diff --git a/src/fobi/utils.py b/src/fobi/utils.py index 7f136ac8..d6b385a5 100644 --- a/src/fobi/utils.py +++ b/src/fobi/utils.py @@ -3,18 +3,19 @@ Another helper module. This module can NOT be safely imported from any fobi (sub)module - thus should be imported carefully. """ import datetime -import os import logging - -from six import PY3 +import os from django.conf import settings from django.contrib import messages -from django.core.urlresolvers import reverse from django.forms.widgets import TextInput from django.utils.encoding import force_text from django.utils.translation import ugettext, ugettext_lazy as _ +from nine.versions import DJANGO_GTE_1_10 + +from six import PY3 + from .base import ( form_element_plugin_registry, form_handler_plugin_registry, @@ -42,6 +43,11 @@ from .models import ( ) from .settings import RESTRICT_PLUGIN_ACCESS, DEBUG, WIZARD_FILES_UPLOAD_DIR +if DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + __title__ = 'fobi.utils' __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' diff --git a/src/fobi/views.py b/src/fobi/views.py index 7120e608..3daae4a8 100644 --- a/src/fobi/views.py +++ b/src/fobi/views.py @@ -15,7 +15,6 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.core.exceptions import ObjectDoesNotExist from django.core.files.storage import FileSystemStorage -from django.core.urlresolvers import reverse from django.forms import ValidationError from django.http import Http404, HttpResponseRedirect from django.shortcuts import redirect @@ -87,7 +86,9 @@ from .wizard import DynamicSessionWizardView, DynamicCookieWizardView if versions.DJANGO_GTE_1_10: from django.shortcuts import render + from django.urls import reverse else: + from django.core.urlresolvers import reverse from django.shortcuts import render_to_response if versions.DJANGO_GTE_1_8: @@ -352,7 +353,7 @@ def create_form_entry(request, theme=None, template_name=None): :param str template_name: :return django.http.HttpResponse: """ - if 'POST' == request.method: + if request.method == 'POST': form = FormEntryForm(request.POST, request.FILES, request=request) if form.is_valid(): form_entry = form.save(commit=False) @@ -429,7 +430,7 @@ def edit_form_entry(request, form_entry_id, theme=None, template_name=None): except ObjectDoesNotExist as err: raise Http404(ugettext("Form entry not found.")) - if 'POST' == request.method: + if request.method == 'POST': # The form entry form (does not contain form elements) form = FormEntryForm(request.POST, request.FILES, instance=form_entry, request=request) @@ -672,7 +673,7 @@ def add_form_element_entry(request, save_object = True # If POST - elif 'POST' == request.method: + elif request.method == 'POST': # If element has a form form = form_element_plugin.get_initialised_create_form_or_404( data=request.POST, @@ -759,7 +760,7 @@ def edit_form_element_entry(request, :param django.http.HttpRequest request: :param int form_element_entry_id: - :param fobi.base.BaseTheme: Theme instance. + :param fobi.base.BaseTheme theme: Theme instance. :param string template_name: :return django.http.HttpResponse: """ @@ -787,7 +788,7 @@ def edit_form_element_entry(request, ) return redirect('fobi.edit_form_entry', form_entry_id=form_entry.pk) - elif 'POST' == request.method: + elif request.method == 'POST': form = form_element_plugin.get_initialised_edit_form_or_404( data=request.POST, files=request.FILES @@ -942,7 +943,7 @@ def add_form_handler_entry(request, if not form_handler_plugin_form_cls: save_object = True - elif 'POST' == request.method: + elif request.method == 'POST': form = form_handler_plugin.get_initialised_create_form_or_404( data=request.POST, files=request.FILES @@ -1042,7 +1043,7 @@ def edit_form_handler_entry(request, ) return redirect('fobi.edit_form_entry', form_entry_id=form_entry.pk) - elif 'POST' == request.method: + elif request.method == 'POST': form = form_handler_plugin.get_initialised_edit_form_or_404( data=request.POST, files=request.FILES @@ -1146,7 +1147,7 @@ def create_form_wizard_entry(request, theme=None, template_name=None): :param str template_name: :return django.http.HttpResponse: """ - if 'POST' == request.method: + if request.method == 'POST': form = FormWizardEntryForm(request.POST, request.FILES, request=request) @@ -1231,7 +1232,7 @@ def edit_form_wizard_entry(request, form_wizard_entry_id, theme=None, except ObjectDoesNotExist as err: raise Http404(ugettext("Form wizard entry not found.")) - if 'POST' == request.method: + if request.method == 'POST': # The form entry form (does not contain form elements) form = FormWizardEntryForm(request.POST, request.FILES, instance=form_wizard_entry, @@ -1952,7 +1953,7 @@ def add_form_wizard_handler_entry(request, if not form_wizard_handler_plugin_form_cls: save_object = True - elif 'POST' == request.method: + elif request.method == 'POST': form = form_wizard_handler_plugin.get_initialised_create_form_or_404( data=request.POST, files=request.FILES @@ -2059,7 +2060,7 @@ def edit_form_wizard_handler_entry(request, form_wizard_entry_id=form_wizard_entry.pk ) - elif 'POST' == request.method: + elif request.method == 'POST': form = form_wizard_handler_plugin.get_initialised_edit_form_or_404( data=request.POST, files=request.FILES @@ -2176,7 +2177,7 @@ def view_form_entry(request, form_entry_slug, theme=None, template_name=None): request=request ) - if 'POST' == request.method: + if request.method == 'POST': form = form_cls(request.POST, request.FILES) # Fire pre form validation callbacks @@ -2405,7 +2406,7 @@ def import_form_entry(request, template_name=None): :param string template_name: :return django.http.HttpResponse: """ - if 'POST' == request.method: + if request.method == 'POST': form = ImportFormEntryForm(request.POST, request.FILES) if form.is_valid(): @@ -2610,7 +2611,7 @@ def import_form_wizard_entry(request, template_name=None): :param string template_name: :return django.http.HttpResponse: """ - if 'POST' == request.method: + if request.method == 'POST': form = ImportFormWizardEntryForm(request.POST, request.FILES) if form.is_valid(): diff --git a/src/fobi/wizard/views/dynamic.py b/src/fobi/wizard/views/dynamic.py index fe029cb0..f333a96d 100644 --- a/src/fobi/wizard/views/dynamic.py +++ b/src/fobi/wizard/views/dynamic.py @@ -4,7 +4,6 @@ import re from django import forms from django.shortcuts import redirect -from django.core.urlresolvers import reverse from django.forms import formsets, ValidationError from django.views.generic import TemplateView from django.utils.decorators import classonlymethod @@ -24,6 +23,11 @@ else: ) from django.contrib.formtools.wizard.forms import ManagementForm +if versions.DJANGO_GTE_1_10: + from django.urls import reverse +else: + from django.core.urlresolvers import reverse + logger = logging.getLogger(__name__) __all__ = ( diff --git a/toxtests.py b/toxtests.py new file mode 100644 index 00000000..c0bc55ef --- /dev/null +++ b/toxtests.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from tox.session import main + +if __name__ == "__main__": + main()