diff --git a/.gitignore b/.gitignore index e3a53f70..1b052a28 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ local_settings.py build/ dist/ forms_builder/example_project/static/ +.tox/ +.cache/ +.coverage +coverage.xml +junit*.xml diff --git a/README.rst b/README.rst index acfb7042..3ab1fa4f 100644 --- a/README.rst +++ b/README.rst @@ -4,6 +4,10 @@ django-forms-builder ==================== +** This package was forked to provide a `FILE_STORAGE` setting. ** + +The `file-storage` branch is the current branch for this. + Created by `Stephen McDonald `_ A Django reusable app providing the ability for admin users to create @@ -126,10 +130,11 @@ in the CSV export. By default these uploaded files are stored in an obscured location under your project's ``MEDIA_ROOT`` directory but ideally the should be stored somewhere inaccessible to the public. To set the location where files are stored to be somewhere outside of your -project's ``MEDIA_ROOT`` directory you just need to define the +project's ``MEDIA_ROOT`` directory you just need to define the either the ``FORMS_BUILDER_UPLOAD_ROOT`` setting in your project's ``settings`` -module. Its value should be an absolute path on the web server that -isn't accessible to the public. +module or the ``FORMS_BUILDER_FILE_STORAGE`` setting. The +``FORMS_BUILDER_UPLOAD_ROOT`` value should be an absolute path on the web +server that isn't accessible to the public. Configuration @@ -146,6 +151,9 @@ module. will be added to the form field types. Defaults to ``()`` * ``FORMS_BUILDER_UPLOAD_ROOT`` - The absolute path where files will be uploaded to. Defaults to ``None`` +* ``FORMS_BUILDER_FILE_STORAGE`` - The class path of the Django storage class + to use for storing files. Defaults to ``None`` which uses the default file + storage. * ``FORMS_BUILDER_USE_HTML5`` - Boolean controlling whether HTML5 form fields are used. Defaults to ``True`` * ``FORMS_BUILDER_USE_SITES`` - Boolean controlling whether forms are diff --git a/forms_builder/example_project/__init__.py b/example_project/__init__.py similarity index 100% rename from forms_builder/example_project/__init__.py rename to example_project/__init__.py diff --git a/forms_builder/example_project/manage.py b/example_project/manage.py similarity index 100% rename from forms_builder/example_project/manage.py rename to example_project/manage.py diff --git a/forms_builder/example_project/settings.py b/example_project/settings.py similarity index 100% rename from forms_builder/example_project/settings.py rename to example_project/settings.py diff --git a/forms_builder/example_project/templates/index.html b/example_project/templates/index.html similarity index 100% rename from forms_builder/example_project/templates/index.html rename to example_project/templates/index.html diff --git a/forms_builder/example_project/urls.py b/example_project/urls.py similarity index 100% rename from forms_builder/example_project/urls.py rename to example_project/urls.py diff --git a/forms_builder/__init__.py b/forms_builder/__init__.py index f23a6b39..af6b6096 100644 --- a/forms_builder/__init__.py +++ b/forms_builder/__init__.py @@ -1 +1,3 @@ -__version__ = "0.13.0" +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +__version__ = "0.14.0b4" diff --git a/forms_builder/forms/admin.py b/forms_builder/forms/admin.py index cf904f39..7d43cc38 100644 --- a/forms_builder/forms/admin.py +++ b/forms_builder/forms/admin.py @@ -1,5 +1,7 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from future.builtins import bytes, open +import os from csv import writer from mimetypes import guess_type @@ -18,7 +20,7 @@ from forms_builder.forms.forms import EntriesForm from forms_builder.forms.models import Form, Field, FormEntry, FieldEntry -from forms_builder.forms.settings import CSV_DELIMITER, UPLOAD_ROOT +from forms_builder.forms.settings import CSV_DELIMITER, UPLOAD_ROOT, FILE_STORAGE from forms_builder.forms.settings import USE_SITES, EDITABLE_SLUGS from forms_builder.forms.utils import now, slugify @@ -29,15 +31,17 @@ except ImportError: XLWT_INSTALLED = False - -fs = FileSystemStorage(location=UPLOAD_ROOT) +if UPLOAD_ROOT is not None: + fs = FileSystemStorage(location=UPLOAD_ROOT) +else: + fs = FILE_STORAGE() form_admin_filter_horizontal = () form_admin_fieldsets = [ (None, {"fields": ("title", ("status", "login_required",), ("publish_date", "expiry_date",), "intro", "button_text", "response", "redirect_url")}), (_("Email"), {"fields": ("send_email", "email_from", "email_copies", - "email_subject", "email_message")}),] + "email_subject", "email_message")}), ] if EDITABLE_SLUGS: form_admin_fieldsets.append( @@ -190,10 +194,14 @@ def file_view(self, request, field_entry_id): """ model = self.fieldentry_model field_entry = get_object_or_404(model, id=field_entry_id) - path = join(fs.location, field_entry.value) + if hasattr(fs, 'location'): + path = join(fs.location, field_entry.value) + else: + path = field_entry.value response = HttpResponse(content_type=guess_type(path)[0]) - f = open(path, "r+b") - response["Content-Disposition"] = "attachment; filename=%s" % f.name + f = fs.open(path, "rb") + filename = os.path.basename(field_entry.value) + response["Content-Disposition"] = "attachment; filename=%s" % filename response.write(f.read()) f.close() return response diff --git a/forms_builder/forms/forms.py b/forms_builder/forms/forms.py index 3823cecb..d620d68f 100644 --- a/forms_builder/forms/forms.py +++ b/forms_builder/forms/forms.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from future.builtins import int, range, str @@ -8,7 +9,6 @@ import django from django import forms from django.forms.extras import SelectDateWidget -from django.core.files.storage import default_storage from django.core.urlresolvers import reverse from django.template import Template from django.utils.safestring import mark_safe @@ -20,9 +20,10 @@ from forms_builder.forms.utils import now, split_choices -fs = default_storage if settings.UPLOAD_ROOT is not None: - fs = default_storage.__class__(location=settings.UPLOAD_ROOT) + fs = settings.FILE_STORAGE(location=settings.UPLOAD_ROOT) +else: + fs = settings.FILE_STORAGE() ############################## diff --git a/forms_builder/forms/settings.py b/forms_builder/forms/settings.py index 7a16ba3f..92736d8d 100644 --- a/forms_builder/forms/settings.py +++ b/forms_builder/forms/settings.py @@ -1,8 +1,9 @@ +# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.conf import settings from django.core.exceptions import ImproperlyConfigured - +from django.core.files.storage import get_storage_class if not ("django.contrib.sites" in settings.INSTALLED_APPS): raise ImproperlyConfigured("django.contrib.sites is required") @@ -23,6 +24,9 @@ # The absolute path where files will be uploaded to. UPLOAD_ROOT = getattr(settings, "FORMS_BUILDER_UPLOAD_ROOT", None) +# The File Storage class to use, uses default file storage if None +FILE_STORAGE = get_storage_class(getattr(settings, "FORMS_BUILDER_FILE_STORAGE", None)) + # Boolean controlling whether HTML5 form fields are used. USE_HTML5 = getattr(settings, "FORMS_BUILDER_USE_HTML5", True) diff --git a/setup.py b/setup.py index 79a2db23..91a9125f 100644 --- a/setup.py +++ b/setup.py @@ -5,77 +5,51 @@ from setuptools import setup, find_packages -exclude = ["forms_builder/example_project/dev.db", - "forms_builder/example_project/local_settings.py"] -exclude = dict([(e, None) for e in exclude]) -for e in exclude: - if e.endswith(".py"): - try: - os.remove("%sc" % e) - except: - pass - try: - with open(e, "r") as f: - exclude[e] = (f.read(), os.stat(e)) - os.remove(e) - except Exception: - pass +version = __import__('forms_builder').__version__ -if sys.argv[:2] == ["setup.py", "bdist_wheel"]: - # Remove previous build dir when creating a wheel build, - # since if files have been removed from the project, - # they'll still be cached in the build dir and end up - # as part of the build, which is unexpected. - try: +if sys.argv[-1] == 'publish': + if os.path.exists("build"): rmtree("build") - except: - pass + os.system('python setup.py bdist_wheel upload -r natgeo') + print("You probably want to also tag the version now:") + print(" python setup.py tag") + sys.exit() +elif sys.argv[-1] == 'tag': + cmd = "git tag -a %s -m 'version %s';git push --tags" % (version, version) + os.system(cmd) + sys.exit() -try: - setup( - name = "django-forms-builder", - version = __import__("forms_builder").__version__, - author = "Stephen McDonald", - author_email = "stephen.mc@gmail.com", - description = ("A Django reusable app providing the ability for " - "admin users to create their own forms and report " - "on their collected data."), - long_description = open("README.rst").read(), - license = "BSD", - url = "http://github.com/stephenmcd/django-forms-builder", - zip_safe = False, - include_package_data = True, - packages = find_packages(), - install_requires = [ - "sphinx-me >= 0.1.2", - "unidecode", - "django-email-extras >= 0.2", - "django >= 1.8, < 1.11", - "future <= 0.15.0", - ], - classifiers = [ - "Development Status :: 5 - Production/Stable", - "Environment :: Web Environment", - "Intended Audience :: Developers", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Framework :: Django", - "Topic :: Internet :: WWW/HTTP :: Dynamic Content", - "Topic :: Internet :: WWW/HTTP :: Site Management", - ] - ) -finally: - for e in exclude: - if exclude[e] is not None: - data, stat = exclude[e] - try: - with open(e, "w") as f: - f.write(data) - os.chown(e, stat.st_uid, stat.st_gid) - os.chmod(e, stat.st_mode) - except: - pass +setup( + name="django-forms-builder", + version=__import__("forms_builder").__version__, + author="Stephen McDonald", + author_email="stephen.mc@gmail.com", + description=("A Django reusable app providing the ability for " + "admin users to create their own forms and report " + "on their collected data."), + long_description=open("README.rst").read(), + license="BSD", + url="http://github.com/stephenmcd/django-forms-builder", + zip_safe=False, + include_package_data=True, + packages=find_packages(exclude=['*example*', ]), + install_requires=[ + "unidecode", + "django-email-extras >= 0.2", + "future >= 0.16.0", + ], + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Framework :: Django", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Internet :: WWW/HTTP :: Site Management", + ] +) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..265bca3b --- /dev/null +++ b/tox.ini @@ -0,0 +1,21 @@ +[tox] +envlist = py{27,36}-django{19,110,111} + +[testenv] +commands = pytest --cov=forms_builder \ + --cov-report term-missing \ + --cov-report xml \ + --junitxml=junit-{envname}.xml \ + --ds=example_project.settings {posargs} +setenv = + PYTHONPATH={toxinidir}:{toxinidir}/example_project +deps = + pytest + pytest-cov + pytest-django + django19: Django<1.10 + django110: Django<1.11 + django111: Django<2.0 + +[pytest] +python_files = tests.py **/tests.py **/tests/*.py **/tests.py