Opened 10 years ago
Closed 9 years ago
#25192 closed Bug (fixed)
Can't Squash Migration that uses migrations.RunPython.noop in Python 2
| Reported by: | James Pulec | Owned by: | Shai Berger |
|---|---|---|---|
| Component: | Migrations | Version: | 1.8 |
| Severity: | Normal | Keywords: | py2 |
| Cc: | Shai Berger | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When trying to squash a set of migrations, if one of them uses migrations.RunPython.noop for a backwards or forward operation, a ValueError is raised due to an attempt to serialize an unbound method. Not sure if there should be a special check for that operation when attempting to run squashmigrations with Python2.
Traceback:
Traceback (most recent call last):
File "manage.py", line 17, in <module>
execute_from_command_line(sys.argv)
File "/var/venv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
utility.execute()
File "/var/venv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/venv/local/lib/python2.7/site-packages/django/core/management/base.py", line 393, in run_from_argv
self.execute(*args, **cmd_options)
File "/var/venv/local/lib/python2.7/site-packages/django/core/management/base.py", line 444, in execute
output = self.handle(*args, **options)
File "/var/venv/local/lib/python2.7/site-packages/django/core/management/commands/squashmigrations.py", line 141, in handle
fh.write(writer.as_string())
File "/var/venv/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 166, in as_string
operation_string, operation_imports = OperationWriter(operation).serialize()
File "/var/venv/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 124, in serialize
_write(arg_name, arg_value)
File "/var/venv/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 87, in _write
arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
File "/var/venv/local/lib/python2.7/site-packages/django/db/migrations/writer.py", line 435, in serialize
% (value.__name__, module_name, get_docs_version()))
ValueError: Could not find function noop in django.db.migrations.operations.special.
Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared and used in the same class body). Please move the function into the main module body to use migrations.
Change History (9)
comment:1 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 9 years ago
| Keywords: | py2 added |
|---|---|
| Summary: | Can't Squash Migration that uses migrations.RunPython.noop in Python2 → Can't Squash Migration that uses migrations.RunPython.noop in Python 2 |
comment:3 by , 9 years ago
comment:4 by , 9 years ago
| Cc: | added |
|---|
I found a funny workaround: In my project, I added this squashmigrations command (that is, a file management/commands/squashmigrations.py in one of my projects' apps):
"""
A squashmigrations command which does some monkeypatching on the RunPython operation
to allow squashing migrations which use RunPython.noop, even on Python 2
"""
from django.core.management.commands.squashmigrations import Command as DjangoCommand
from django.db.migrations import RunPython
# A staticmethod decorator is needed (out of a class!) because we are going to
# monkeypatch this function into a class and it will be introspected by code that
# will think it is an unbound instance method without the decorator.
@staticmethod
def noop(apps, schema_editor):
return None
class Command(DjangoCommand):
def handle(self, **options):
# Monkeypatch
RunPython.noop = noop
# Invoke original
return super(Command, self).handle(**options)
Note the oddity of the @staticmethod decorator on a function that isn't in a class.
I suppose we could use the same idea in fixing the bug in Django as well...
comment:5 by , 9 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
Closing due to the end of Python 2 support in master in a couple weeks.
comment:6 by , 9 years ago
| Resolution: | wontfix |
|---|---|
| Status: | closed → new |
comment:8 by , 9 years ago
| Has patch: | set |
|---|
I was hitting the same issue (when squashing migrations) and learned that you can simply add a global function to the migration script that does nothing (or copy from the existing noop) and refer to that from the RunPython function.
Paul