Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django110 #185

Merged
merged 4 commits into from
Aug 5, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ python:
- 3.5

env:
- TOX_ENV=py27-django17
- TOX_ENV=py33-django17
- TOX_ENV=py34-django17
- TOX_ENV=py27-django18
- TOX_ENV=py33-django18
- TOX_ENV=py34-django18
- TOX_ENV=py35-django18
- TOX_ENV=py27-django19
- TOX_ENV=py34-django19
- TOX_ENV=py35-django19
- TOX_ENV=py27-django110
- TOX_ENV=py34-django110
- TOX_ENV=py35-django110

before_install:
- pip install codecov
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ django-storages change log
1.5.1 (XXXX-XX-XX)
******************

* **Drop support for Django 1.7** (`#185`_)
* Update ``S3Boto3Storage`` for Django 1.10 (`#181`_) (``get_modified_time`` and ``get_accessed_time``) thanks @JshWright

.. _#185: https://github.com/jschneier/django-storages/pull/185
.. _#181: https://github.com/jschneier/django-storages/pull/181

1.5.0 (2016-08-02)
Expand Down
6 changes: 3 additions & 3 deletions storages/backends/apache_libcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

from django.conf import settings
from django.core.files.base import File
from django.core.files.storage import Storage
from django.core.exceptions import ImproperlyConfigured
from django.utils.six import string_types
from django.utils.deconstruct import deconstructible
from django.utils.six import string_types, BytesIO
from django.utils.six.moves.urllib.parse import urljoin

from storages.compat import BytesIO, deconstructible, Storage

try:
from libcloud.storage.providers import get_driver
from libcloud.storage.types import ObjectDoesNotExistError, Provider
Expand Down
2 changes: 1 addition & 1 deletion storages/backends/azure_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from django.core.files.base import ContentFile
from django.core.exceptions import ImproperlyConfigured
from storages.compat import Storage
from django.core.files.storage import Storage

try:
import azure # noqa
Expand Down
13 changes: 7 additions & 6 deletions storages/backends/couchdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,29 @@

from django.conf import settings
from django.core.files import File
from django.core.files.storage import Storage
from django.core.exceptions import ImproperlyConfigured

from storages.compat import urlparse, BytesIO, Storage
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.six import BytesIO

try:
import couchdb
except ImportError:
raise ImproperlyConfigured("Could not load couchdb dependency.\
\nSee http://code.google.com/p/couchdb-python/")

DEFAULT_SERVER= getattr(settings, 'COUCHDB_DEFAULT_SERVER', 'http://couchdb.local:5984')
STORAGE_OPTIONS= getattr(settings, 'COUCHDB_STORAGE_OPTIONS', {})
DEFAULT_SERVER = getattr(settings, 'COUCHDB_DEFAULT_SERVER', 'http://couchdb.local:5984')
STORAGE_OPTIONS = getattr(settings, 'COUCHDB_STORAGE_OPTIONS', {})


class CouchDBStorage(Storage):
"""
CouchDBStorage - a Django Storage class for CouchDB.

The CouchDBStorage can be configured in settings.py, e.g.::

COUCHDB_STORAGE_OPTIONS = {
'server': "http://example.org",
'server': "http://example.org",
'database': 'database_name'
}

Expand Down
49 changes: 25 additions & 24 deletions storages/backends/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

from django.conf import settings
from django.core.files import File
from django.core.files.storage import Storage
from django.core.exceptions import ImproperlyConfigured

from storages.compat import urlparse, BytesIO, Storage
from django.utils.six import BytesIO
from django.utils.six.moves.urllib import parse as urlparse

try:
import pyodbc
Expand All @@ -18,26 +19,26 @@

class DatabaseStorage(Storage):
"""
Class DatabaseStorage provides storing files in the database.
Class DatabaseStorage provides storing files in the database.
"""

def __init__(self, option=settings.DB_FILES):
"""Constructor.
"""Constructor.

Constructs object using dictionary either specified in contucotr or
in settings.DB_FILES.
in settings.DB_FILES.

@param option dictionary with 'db_table', 'fname_column',
'blob_column', 'size_column', 'base_url' keys.
'blob_column', 'size_column', 'base_url' keys.

option['db_table']
Table to work with.
option['fname_column']
Column in the 'db_table' containing filenames (filenames can
contain pathes). Values should be the same as where FileField keeps
filenames.
filenames.
It is used to map filename to blob_column. In sql it's simply
used in where clause.
used in where clause.
option['blob_column']
Blob column (for example 'image' type), created manually in the
'db_table', used to store image.
Expand All @@ -46,7 +47,7 @@ def __init__(self, option=settings.DB_FILES):
method (another way is to open file and get size)
option['base_url']
Url prefix used with filenames. Should be mapped to the view,
that returns an image as result.
that returns an image as result.
"""

if not option or not all([field in option for field in REQUIRED_FIELDS]):
Expand All @@ -64,18 +65,18 @@ def __init__(self, option=settings.DB_FILES):
self.DATABASE_USER = settings.DATABASE_USER
self.DATABASE_PASSWORD = settings.DATABASE_PASSWORD
self.DATABASE_HOST = settings.DATABASE_HOST

self.connection = pyodbc.connect('DRIVER=%s;SERVER=%s;DATABASE=%s;UID=%s;PWD=%s'%(self.DATABASE_ODBC_DRIVER,self.DATABASE_HOST,self.DATABASE_NAME,
self.DATABASE_USER, self.DATABASE_PASSWORD) )
self.cursor = self.connection.cursor()

def _open(self, name, mode='rb'):
"""Open a file from database.
"""Open a file from database.

@param name filename or relative path to file based on base_url. path should contain only "/", but not "\". Apache sends pathes with "/".
If there is no such file in the db, returs None
"""

assert mode == 'rb', "You've tried to open binary file without specifying binary mode! You specified: %s"%mode

row = self.cursor.execute("SELECT %s from %s where %s = '%s'"%(self.blob_column,self.db_table,self.fname_column,name) ).fetchone()
Expand All @@ -84,23 +85,23 @@ def _open(self, name, mode='rb'):
inMemFile = BytesIO(row[0])
inMemFile.name = name
inMemFile.mode = mode

retFile = File(inMemFile)
return retFile

def _save(self, name, content):
"""Save 'content' as file named 'name'.
@note '\' in path will be converted to '/'.

@note '\' in path will be converted to '/'.
"""

name = name.replace('\\', '/')
binary = pyodbc.Binary(content.read())
size = len(binary)

#todo: check result and do something (exception?) if failed.
if self.exists(name):
self.cursor.execute("UPDATE %s SET %s = ?, %s = ? WHERE %s = '%s'"%(self.db_table,self.blob_column,self.size_column,self.fname_column,name),
self.cursor.execute("UPDATE %s SET %s = ?, %s = ? WHERE %s = '%s'"%(self.db_table,self.blob_column,self.size_column,self.fname_column,name),
(binary, size) )
else:
self.cursor.execute("INSERT INTO %s VALUES(?, ?, ?)"%(self.db_table), (name, binary, size) )
Expand All @@ -110,7 +111,7 @@ def _save(self, name, content):
def exists(self, name):
row = self.cursor.execute("SELECT %s from %s where %s = '%s'"%(self.fname_column,self.db_table,self.fname_column,name)).fetchone()
return row is not None

def get_available_name(self, name, max_length=None):
return name

Expand All @@ -123,7 +124,7 @@ def url(self, name):
if self.base_url is None:
raise ValueError("This file is not accessible via a URL.")
return urlparse.urljoin(self.base_url, name).replace('\\', '/')

def size(self, name):
row = self.cursor.execute("SELECT %s from %s where %s = '%s'"%(self.size_column,self.db_table,self.fname_column,name)).fetchone()
if row is None:
Expand Down
4 changes: 2 additions & 2 deletions storages/backends/dropbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
from tempfile import SpooledTemporaryFile
from shutil import copyfileobj

from django.core.files.base import File
from django.core.exceptions import ImproperlyConfigured
from django.core.files.base import File
from django.core.files.storage import Storage
from django.utils._os import safe_join

from storages.compat import Storage
from storages.utils import setting

from dropbox.client import DropboxClient
Expand Down
4 changes: 3 additions & 1 deletion storages/backends/ftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

from django.conf import settings
from django.core.files.base import File
from django.core.files.storage import Storage
from django.core.exceptions import ImproperlyConfigured
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.six import BytesIO

from storages.compat import urlparse, BytesIO, Storage
from storages.utils import setting


Expand Down
2 changes: 1 addition & 1 deletion storages/backends/gs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from django.core.exceptions import ImproperlyConfigured
from django.utils.six import BytesIO

from storages.backends.s3boto import S3BotoStorage, S3BotoStorageFile
from storages.utils import setting
from storages.compat import BytesIO

try:
from boto.gs.connection import GSConnection, SubdomainCallingFormat
Expand Down
6 changes: 4 additions & 2 deletions storages/backends/hashpath.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import os, hashlib, errno
import errno
import hashlib
import os

from django.core.files.storage import FileSystemStorage
from django.utils.encoding import force_text, force_bytes
from storages.compat import FileSystemStorage


class HashPathStorage(FileSystemStorage):
Expand Down
24 changes: 12 additions & 12 deletions storages/backends/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os

from django.core.exceptions import ImproperlyConfigured
from storages.compat import FileSystemStorage
from django.core.files.storage import FileSystemStorage

try:
from PIL import ImageFile as PILImageFile
Expand All @@ -14,25 +14,25 @@
class ImageStorage(FileSystemStorage):
"""
A FileSystemStorage which normalizes extensions for images.

Comes from http://www.djangosnippets.org/snippets/965/
"""

def find_extension(self, format):
"""Normalizes PIL-returned format into a standard, lowercase extension."""
format = format.lower()

if format == 'jpeg':
format = 'jpg'

return format

def save(self, name, content, max_length=None):
dirname = os.path.dirname(name)
basename = os.path.basename(name)

# Use PIL to determine filetype

p = PILImageFile.Parser()
while 1:
data = content.read(1024)
Expand All @@ -42,14 +42,14 @@ def save(self, name, content, max_length=None):
if p.image:
im = p.image
break

extension = self.find_extension(im.format)

# Does the basename already have an extension? If so, replace it.
# bare as in without extension
bare_basename, _ = os.path.splitext(basename)
basename = bare_basename + '.' + extension

name = os.path.join(dirname, basename)
return super(ImageStorage, self).save(name, content)

Loading