Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit 58b704d8da2347e1db6930c80eb117dea1684d72 1 parent 4d4d68a
Jannis Leidel authored October 08, 2010
31  django/core/files/storage.py
@@ -2,6 +2,7 @@
2 2
 import errno
3 3
 import urlparse
4 4
 import itertools
  5
+from datetime import datetime
5 6
 
6 7
 from django.conf import settings
7 8
 from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
@@ -120,6 +121,27 @@ def url(self, name):
120 121
         """
121 122
         raise NotImplementedError()
122 123
 
  124
+    def accessed_time(self, name):
  125
+        """
  126
+        Returns the last accessed time (as datetime object) of the file
  127
+        specified by name.
  128
+        """
  129
+        raise NotImplementedError()
  130
+
  131
+    def created_time(self, name):
  132
+        """
  133
+        Returns the creation time (as datetime object) of the file
  134
+        specified by name.
  135
+        """
  136
+        raise NotImplementedError()
  137
+
  138
+    def modified_time(self, name):
  139
+        """
  140
+        Returns the last modified time (as datetime object) of the file
  141
+        specified by name.
  142
+        """
  143
+        raise NotImplementedError()
  144
+
123 145
 class FileSystemStorage(Storage):
124 146
     """
125 147
     Standard filesystem storage
@@ -220,6 +242,15 @@ def url(self, name):
220 242
             raise ValueError("This file is not accessible via a URL.")
221 243
         return urlparse.urljoin(self.base_url, name).replace('\\', '/')
222 244
 
  245
+    def accessed_time(self, name):
  246
+        return datetime.fromtimestamp(os.path.getatime(self.path(name)))
  247
+
  248
+    def created_time(self, name):
  249
+        return datetime.fromtimestamp(os.path.getctime(self.path(name)))
  250
+
  251
+    def modified_time(self, name):
  252
+        return datetime.fromtimestamp(os.path.getmtime(self.path(name)))
  253
+
223 254
 def get_storage_class(import_path=None):
224 255
     if import_path is None:
225 256
         import_path = settings.DEFAULT_FILE_STORAGE
27  docs/ref/files/storage.txt
@@ -13,6 +13,33 @@ The local filesystem path where the file can be opened using Python's standard
13 13
 ``open()``. For storage systems that aren't accessible from the local
14 14
 filesystem, this will raise ``NotImplementedError`` instead.
15 15
 
  16
+``Storage.accessed_time(name)``
  17
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18
+
  19
+.. versionadded:: 1.3
  20
+
  21
+Returns a ``datetime`` object containing the last accessed time of the file.
  22
+For storage systems that aren't able to return the last accessed time, this
  23
+will raise ``NotImplementedError`` instead.
  24
+
  25
+``Storage.created_time(name)``
  26
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27
+
  28
+.. versionadded:: 1.3
  29
+
  30
+Returns a ``datetime`` object containing the creation time of the file.
  31
+For storage systems that aren't able to return the creation time, this
  32
+will raise ``NotImplementedError`` instead.
  33
+
  34
+``Storage.modified_time(name)``
  35
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36
+
  37
+.. versionadded:: 1.3
  38
+
  39
+Returns a ``datetime`` object containing the last modified time. For storage
  40
+systems that aren't able to return the last modified time, this will raise
  41
+``NotImplementedError`` instead.
  42
+
16 43
 ``Storage.size(name)``
17 44
 ~~~~~~~~~~~~~~~~~~~~~~
18 45
 
61  tests/regressiontests/file_storage/tests.py
@@ -6,6 +6,7 @@
6 6
 import time
7 7
 import unittest
8 8
 from cStringIO import StringIO
  9
+from datetime import datetime, timedelta
9 10
 from django.conf import settings
10 11
 from django.core.exceptions import SuspiciousOperation
11 12
 from django.core.files.base import ContentFile, File
@@ -81,16 +82,16 @@ def test_get_nonexisting_storage_module(self):
81 82
 
82 83
 class FileStorageTests(unittest.TestCase):
83 84
     storage_class = FileSystemStorage
84  
-    
  85
+
85 86
     def setUp(self):
86 87
         self.temp_dir = tempfile.mktemp()
87 88
         os.makedirs(self.temp_dir)
88 89
         self.storage = self.storage_class(location=self.temp_dir,
89 90
             base_url='/test_media_url/')
90  
-    
  91
+
91 92
     def tearDown(self):
92 93
         shutil.rmtree(self.temp_dir)
93  
-        
  94
+
94 95
     def test_file_access_options(self):
95 96
         """
96 97
         Standard file access options are available, and work as expected.
@@ -104,10 +105,60 @@ def test_file_access_options(self):
104 105
         f = self.storage.open('storage_test', 'r')
105 106
         self.assertEqual(f.read(), 'storage contents')
106 107
         f.close()
107  
-        
  108
+
108 109
         self.storage.delete('storage_test')
109 110
         self.failIf(self.storage.exists('storage_test'))
110 111
 
  112
+    def test_file_accessed_time(self):
  113
+        """
  114
+        File storage returns a Datetime object for the last accessed time of
  115
+        a file.
  116
+        """
  117
+        self.failIf(self.storage.exists('test.file'))
  118
+
  119
+        f = ContentFile('custom contents')
  120
+        f_name = self.storage.save('test.file', f)
  121
+        atime = self.storage.accessed_time(f_name)
  122
+
  123
+        self.assertEqual(atime, datetime.fromtimestamp(
  124
+            os.path.getatime(self.storage.path(f_name))))
  125
+        self.assertTrue(datetime.now() - self.storage.accessed_time(f_name) < timedelta(seconds=2))
  126
+        self.storage.delete(f_name)
  127
+
  128
+    def test_file_created_time(self):
  129
+        """
  130
+        File storage returns a Datetime object for the creation time of
  131
+        a file.
  132
+        """
  133
+        self.failIf(self.storage.exists('test.file'))
  134
+
  135
+        f = ContentFile('custom contents')
  136
+        f_name = self.storage.save('test.file', f)
  137
+        ctime = self.storage.created_time(f_name)
  138
+
  139
+        self.assertEqual(ctime, datetime.fromtimestamp(
  140
+            os.path.getctime(self.storage.path(f_name))))
  141
+        self.assertTrue(datetime.now() - self.storage.created_time(f_name) < timedelta(seconds=2))
  142
+
  143
+        self.storage.delete(f_name)
  144
+
  145
+    def test_file_modified_time(self):
  146
+        """
  147
+        File storage returns a Datetime object for the last modified time of
  148
+        a file.
  149
+        """
  150
+        self.failIf(self.storage.exists('test.file'))
  151
+
  152
+        f = ContentFile('custom contents')
  153
+        f_name = self.storage.save('test.file', f)
  154
+        mtime = self.storage.modified_time(f_name)
  155
+
  156
+        self.assertEqual(mtime, datetime.fromtimestamp(
  157
+            os.path.getmtime(self.storage.path(f_name))))
  158
+        self.assertTrue(datetime.now() - self.storage.modified_time(f_name) < timedelta(seconds=2))
  159
+
  160
+        self.storage.delete(f_name)
  161
+
111 162
     def test_file_save_without_name(self):
112 163
         """
113 164
         File storage extracts the filename from the content object if no
@@ -215,7 +266,7 @@ def get_available_name(self, name):
215 266
 
216 267
 class CustomStorageTests(FileStorageTests):
217 268
     storage_class = CustomStorage
218  
-    
  269
+
219 270
     def test_custom_get_available_name(self):
220 271
         first = self.storage.save('custom_storage', ContentFile('custom contents'))
221 272
         self.assertEqual(first, 'custom_storage')

0 notes on commit 58b704d

Please sign in to comment.
Something went wrong with that request. Please try again.