# HG changeset patch # User ymh # Date 1441124867 -7200 # Node ID 0637048db5d4e621adc394d054d1e9008c85bff3 # Parent 3880aba1b2b14c8017be17dc96b10eacbca0d9ff Add a monkey patch to " django.db.models.fields.files.FileDescriptor.__get__ (cf django bug #24823 https://code.djangoproject.com/ticket/24823) This is done in order to avoid maintaining a django fork diff -r 3880aba1b2b1 -r 0637048db5d4 .settings/org.eclipse.core.resources.prefs --- a/.settings/org.eclipse.core.resources.prefs Fri Aug 28 18:04:30 2015 +0200 +++ b/.settings/org.eclipse.core.resources.prefs Tue Sep 01 18:27:47 2015 +0200 @@ -1,5 +1,6 @@ eclipse.preferences.version=1 encoding//src/ldt/ldt/api/ldt/tests/tests_project.py=utf-8 +encoding//src/ldt/ldt/apps.py=utf-8 encoding//src/ldt/ldt/indexation/backends/elasticsearch_backend.py=utf-8 encoding//src/ldt/ldt/indexation/highlighter.py=utf-8 encoding//src/ldt/ldt/indexation/models.py=utf-8 diff -r 3880aba1b2b1 -r 0637048db5d4 src/ldt/ldt/__init__.py --- a/src/ldt/ldt/__init__.py Fri Aug 28 18:04:30 2015 +0200 +++ b/src/ldt/ldt/__init__.py Tue Sep 01 18:27:47 2015 +0200 @@ -1,6 +1,6 @@ -__all__ = ["VERSION", "get_version", "__version__"] +__all__ = ["VERSION", "get_version", "__version__", "default_app_config"] -VERSION = (1, 58, 0, "final", 0) +VERSION = (1, 58, 1, "final", 0) def get_version(): @@ -26,3 +26,5 @@ # TODO: remove this by reworking ldt dependencies #from django.db.models.loading import get_models #_ = get_models() + +default_app_config = 'ldt.apps.LdtAppConfig' diff -r 3880aba1b2b1 -r 0637048db5d4 src/ldt/ldt/apps.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/apps.py Tue Sep 01 18:27:47 2015 +0200 @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +''' +Created on Sep 1, 2015 + +@author: ymh +''' + +from django.apps import AppConfig +from django.core.files.base import File +from django.db.models.fields.files import FieldFile +from django.db.models.fields.files import FileDescriptor +import six + + +def ldt_get(self, instance=None, owner=None): + if instance is None: + raise AttributeError( + "The '%s' attribute can only be accessed from %s instances." + % (self.field.name, owner.__name__)) + + # This is slightly complicated, so worth an explanation. + # instance.file`needs to ultimately return some instance of `File`, + # probably a subclass. Additionally, this returned object needs to have + # the FieldFile API so that users can easily do things like + # instance.file.path and have that delegated to the file storage engine. + # Easy enough if we're strict about assignment in __set__, but if you + # peek below you can see that we're not. So depending on the current + # value of the field we have to dynamically construct some sort of + # "thing" to return. + + # The instance dict contains whatever was originally assigned + # in __set__. + file = instance.__dict__[self.field.name] # @ReservedAssignment + + # If this value is callable (certainly because the field was defined + # with a callable default), we execute the function and assign the + # result to the value + if six.callable(file): + file = file() # @ReservedAssignment + if isinstance(file, FieldFile) and not hasattr(file, 'field'): + instance.__dict__[self.field.name] = file + + # If this value is a string (instance.file = "path/to/file") or None + # then we simply wrap it with the appropriate attribute class according + # to the file field. [This is FieldFile for FileFields and + # ImageFieldFile for ImageFields; it's also conceivable that user + # subclasses might also want to subclass the attribute class]. This + # object understands how to convert a path to a file, and also how to + # handle None. + if isinstance(file, six.string_types) or file is None: + attr = self.field.attr_class(instance, self.field, file) + instance.__dict__[self.field.name] = attr + + # Other types of files may be assigned as well, but they need to have + # the FieldFile interface added to them. Thus, we wrap any other type of + # File inside a FieldFile (well, the field's attr_class, which is + # usually FieldFile). + elif isinstance(file, File) and not isinstance(file, FieldFile): + file_copy = self.field.attr_class(instance, self.field, file.name) + file_copy.file = file + file_copy._committed = False + instance.__dict__[self.field.name] = file_copy + + # Finally, because of the (some would say boneheaded) way pickle works, + # the underlying FieldFile might not actually itself have an associated + # file. So we need to reset the details of the FieldFile in those cases. + elif isinstance(file, FieldFile) and not hasattr(file, 'field'): + file.instance = instance + file.field = self.field + file.storage = self.field.storage + + # That was fun, wasn't it? + return instance.__dict__[self.field.name] + +class LdtAppConfig(AppConfig): + ''' + App config to monkey patch django.db.models.fields.files.FileDescriptor.__get__ (cf django bug #24823 https://code.djangoproject.com/ticket/24823) + ''' + + name = 'ldt' + verbose_name = 'LDT Platform' + + def ready(self): + FileDescriptor.__get__ = ldt_get