summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Leidel <jannis@leidel.info>2010-10-08 15:11:59 +0000
committerJannis Leidel <jannis@leidel.info>2010-10-08 15:11:59 +0000
commit58b704d8da2347e1db6930c80eb117dea1684d72 (patch)
treeef1eddf94456c871dda8e90bef06d8bf062e4ce0
parent4d4d68a2cd8d93ce4bc4280b47051f294b280e73 (diff)
Fixed #10497 -- Added a few time-related methods to the storage API. Thanks for the report and patch to Stephan Jaekel.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14012 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/core/files/storage.py31
-rw-r--r--docs/ref/files/storage.txt27
-rw-r--r--tests/regressiontests/file_storage/tests.py61
3 files changed, 114 insertions, 5 deletions
diff --git a/django/core/files/storage.py b/django/core/files/storage.py
index 4f27502167..0cc895d230 100644
--- a/django/core/files/storage.py
+++ b/django/core/files/storage.py
@@ -2,6 +2,7 @@ import os
import errno
import urlparse
import itertools
+from datetime import datetime
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
@@ -120,6 +121,27 @@ class Storage(object):
"""
raise NotImplementedError()
+ def accessed_time(self, name):
+ """
+ Returns the last accessed time (as datetime object) of the file
+ specified by name.
+ """
+ raise NotImplementedError()
+
+ def created_time(self, name):
+ """
+ Returns the creation time (as datetime object) of the file
+ specified by name.
+ """
+ raise NotImplementedError()
+
+ def modified_time(self, name):
+ """
+ Returns the last modified time (as datetime object) of the file
+ specified by name.
+ """
+ raise NotImplementedError()
+
class FileSystemStorage(Storage):
"""
Standard filesystem storage
@@ -220,6 +242,15 @@ class FileSystemStorage(Storage):
raise ValueError("This file is not accessible via a URL.")
return urlparse.urljoin(self.base_url, name).replace('\\', '/')
+ def accessed_time(self, name):
+ return datetime.fromtimestamp(os.path.getatime(self.path(name)))
+
+ def created_time(self, name):
+ return datetime.fromtimestamp(os.path.getctime(self.path(name)))
+
+ def modified_time(self, name):
+ return datetime.fromtimestamp(os.path.getmtime(self.path(name)))
+
def get_storage_class(import_path=None):
if import_path is None:
import_path = settings.DEFAULT_FILE_STORAGE
diff --git a/docs/ref/files/storage.txt b/docs/ref/files/storage.txt
index 2b055bb60b..b27ea1556b 100644
--- a/docs/ref/files/storage.txt
+++ b/docs/ref/files/storage.txt
@@ -13,6 +13,33 @@ The local filesystem path where the file can be opened using Python's standard
``open()``. For storage systems that aren't accessible from the local
filesystem, this will raise ``NotImplementedError`` instead.
+``Storage.accessed_time(name)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.3
+
+Returns a ``datetime`` object containing the last accessed time of the file.
+For storage systems that aren't able to return the last accessed time, this
+will raise ``NotImplementedError`` instead.
+
+``Storage.created_time(name)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.3
+
+Returns a ``datetime`` object containing the creation time of the file.
+For storage systems that aren't able to return the creation time, this
+will raise ``NotImplementedError`` instead.
+
+``Storage.modified_time(name)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.3
+
+Returns a ``datetime`` object containing the last modified time. For storage
+systems that aren't able to return the last modified time, this will raise
+``NotImplementedError`` instead.
+
``Storage.size(name)``
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py
index 46411aca87..f83b26792f 100644
--- a/tests/regressiontests/file_storage/tests.py
+++ b/tests/regressiontests/file_storage/tests.py
@@ -6,6 +6,7 @@ import tempfile
import time
import unittest
from cStringIO import StringIO
+from datetime import datetime, timedelta
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.core.files.base import ContentFile, File
@@ -81,16 +82,16 @@ class GetStorageClassTests(unittest.TestCase):
class FileStorageTests(unittest.TestCase):
storage_class = FileSystemStorage
-
+
def setUp(self):
self.temp_dir = tempfile.mktemp()
os.makedirs(self.temp_dir)
self.storage = self.storage_class(location=self.temp_dir,
base_url='/test_media_url/')
-
+
def tearDown(self):
shutil.rmtree(self.temp_dir)
-
+
def test_file_access_options(self):
"""
Standard file access options are available, and work as expected.
@@ -104,10 +105,60 @@ class FileStorageTests(unittest.TestCase):
f = self.storage.open('storage_test', 'r')
self.assertEqual(f.read(), 'storage contents')
f.close()
-
+
self.storage.delete('storage_test')
self.failIf(self.storage.exists('storage_test'))
+ def test_file_accessed_time(self):
+ """
+ File storage returns a Datetime object for the last accessed time of
+ a file.
+ """
+ self.failIf(self.storage.exists('test.file'))
+
+ f = ContentFile('custom contents')
+ f_name = self.storage.save('test.file', f)
+ atime = self.storage.accessed_time(f_name)
+
+ self.assertEqual(atime, datetime.fromtimestamp(
+ os.path.getatime(self.storage.path(f_name))))
+ self.assertTrue(datetime.now() - self.storage.accessed_time(f_name) < timedelta(seconds=2))
+ self.storage.delete(f_name)
+
+ def test_file_created_time(self):
+ """
+ File storage returns a Datetime object for the creation time of
+ a file.
+ """
+ self.failIf(self.storage.exists('test.file'))
+
+ f = ContentFile('custom contents')
+ f_name = self.storage.save('test.file', f)
+ ctime = self.storage.created_time(f_name)
+
+ self.assertEqual(ctime, datetime.fromtimestamp(
+ os.path.getctime(self.storage.path(f_name))))
+ self.assertTrue(datetime.now() - self.storage.created_time(f_name) < timedelta(seconds=2))
+
+ self.storage.delete(f_name)
+
+ def test_file_modified_time(self):
+ """
+ File storage returns a Datetime object for the last modified time of
+ a file.
+ """
+ self.failIf(self.storage.exists('test.file'))
+
+ f = ContentFile('custom contents')
+ f_name = self.storage.save('test.file', f)
+ mtime = self.storage.modified_time(f_name)
+
+ self.assertEqual(mtime, datetime.fromtimestamp(
+ os.path.getmtime(self.storage.path(f_name))))
+ self.assertTrue(datetime.now() - self.storage.modified_time(f_name) < timedelta(seconds=2))
+
+ self.storage.delete(f_name)
+
def test_file_save_without_name(self):
"""
File storage extracts the filename from the content object if no
@@ -215,7 +266,7 @@ class CustomStorage(FileSystemStorage):
class CustomStorageTests(FileStorageTests):
storage_class = CustomStorage
-
+
def test_custom_get_available_name(self):
first = self.storage.save('custom_storage', ContentFile('custom contents'))
self.assertEqual(first, 'custom_storage')