diff options
| author | Andrew Godwin <andrew@aeracode.org> | 2014-06-07 17:04:58 -0700 |
|---|---|---|
| committer | Andrew Godwin <andrew@aeracode.org> | 2014-06-07 17:05:51 -0700 |
| commit | 6fd455adfcc85f6bd390bce784a1b5dfe5d610ea (patch) | |
| tree | bbde7ef48977f036461e15a68addc9a3dcdd261e /django/db | |
| parent | 250e2b422b4da93f38cd61319b9b3c9f422e6ede (diff) | |
Fixed #22436: More careful checking on method ref'ce serialization
Diffstat (limited to 'django/db')
| -rw-r--r-- | django/db/migrations/writer.py | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/django/db/migrations/writer.py b/django/db/migrations/writer.py index f73c4b78a0..d709c91707 100644 --- a/django/db/migrations/writer.py +++ b/django/db/migrations/writer.py @@ -12,7 +12,7 @@ import types from django.apps import apps from django.db import models from django.db.migrations.loader import MigrationLoader -from django.utils import datetime_safe, six +from django.utils import datetime_safe, six, importlib from django.utils.encoding import force_text from django.utils.functional import Promise @@ -284,13 +284,29 @@ class MigrationWriter(object): klass = value.__self__ module = klass.__module__ return "%s.%s.%s" % (module, klass.__name__, value.__name__), set(["import %s" % module]) - elif value.__name__ == '<lambda>': + # Further error checking + if value.__name__ == '<lambda>': raise ValueError("Cannot serialize function: lambda") - elif value.__module__ is None: + if value.__module__ is None: raise ValueError("Cannot serialize function %r: No module" % value) - else: - module = value.__module__ - return "%s.%s" % (module, value.__name__), set(["import %s" % module]) + # Python 3 is a lot easier, and only uses this branch if it's not local. + if getattr(value, "__qualname__", None) and getattr(value, "__module__", None): + if "<" not in value.__qualname__: # Qualname can include <locals> + return "%s.%s" % (value.__module__, value.__qualname__), set(["import %s" % value.__module__]) + # Python 2/fallback version + module_name = value.__module__ + # Make sure it's actually there and not an unbound method + module = importlib.import_module(module_name) + if not hasattr(module, value.__name__): + raise ValueError( + "Could not find function %s in %s.\nPlease note that " + "due to Python 2 limitations, you cannot serialize " + "unbound method functions (e.g. a method declared\n" + "and used in the same class body). Please move the " + "function into the main module body to use migrations.\n" + "For more information, see https://docs.djangoproject.com/en/1.7/topics/migrations/#serializing-values" + ) + return "%s.%s" % (module_name, value.__name__), set(["import %s" % module_name]) # Classes elif isinstance(value, type): special_cases = [ |
