#24278 closed Bug (fixed)
squashmigrations throws ValueError: need more than 1 value to unpack
| Reported by: | Piotr Maliński | Owned by: | Marten Kenbeek | 
|---|---|---|---|
| Component: | Migrations | Version: | 1.8 | 
| Severity: | Normal | Keywords: | |
| Cc: | Markus Holtermann, michaelvantellingen@… | Triage Stage: | Ready for checkin | 
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
When squashing several migrations I got an exception during squashmigrations:
Traceback (most recent call last):
  File "/env/bin/django-admin.py", line 5, in <module>
    management.execute_from_command_line()
  File "/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "/env/lib/python3.4/site-packages/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/env/lib/python3.4/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/env/lib/python3.4/site-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "/env/lib/python3.4/site-packages/django/core/management/commands/squashmigrations.py", line 122, in handle
    fh.write(writer.as_string())
  File "/env/lib/python3.4/site-packages/django/db/migrations/writer.py", line 130, in as_string
    operation_string, operation_imports = OperationWriter(operation).serialize()
  File "/env/lib/python3.4/site-packages/django/db/migrations/writer.py", line 87, in serialize
    arg_string, arg_imports = MigrationWriter.serialize(arg_value)
  File "/env/lib/python3.4/site-packages/django/db/migrations/writer.py", line 260, in serialize
    item_string, item_imports = cls.serialize(item)
  File "/env/lib/python3.4/site-packages/django/db/migrations/writer.py", line 327, in serialize
    return cls.serialize_deconstructed(*value.deconstruct())
  File "/env/lib/python3.4/site-packages/django/db/migrations/writer.py", line 223, in serialize_deconstructed
    module, name = path.rsplit(".", 1)
ValueError: need more than 1 value to unpack
The "path" variable got a value of "RenameField" instead of django.something.someField. I found one "migrations.RenameField" in the migrations set and after removing it (and "migrations.AlterField" which also caused such exception) the squash passed.
The migration (operations) with those fields looks like so:
operations = [
        migrations.SeparateDatabaseAndState(state_operations=[
            migrations.RenameField(
                model_name='somemodel',
                old_name='some_old_name',
                new_name='new_name',
            ),
            migrations.AlterField(
                model_name='somemodel',
                name='new_name',
                field=models.BooleanField(db_column='some_old_name', default=False),
                preserve_default=True,
            ),
        ]),
    ]
      Change History (13)
comment:1 by , 11 years ago
| Owner: | changed from to | 
|---|---|
| Status: | new → assigned | 
| Triage Stage: | Unreviewed → Accepted | 
comment:2 by , 11 years ago
Failing test case: Operations don't implement __eq__, so this is kinda useless. 
diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py
index 38065fb..4130e32 100644
--- a/tests/migrations/test_writer.py
+++ b/tests/migrations/test_writer.py
@@ -346,6 +346,18 @@ class WriterTests(TestCase):
         self.assertSerializedEqual(FoodManager('a', 'b'))
         self.assertSerializedEqual(FoodManager('x', 'y', c=3, d=4))
 
+    def test_serialize_operation(self):
+        """
+        Tests serializing an operation with MigrationWriter serialize. This happens when
+        serializing an operation within an operation, e.g. with SeparateDatabaseAndState.
+        """
+        operation = migrations.RenameField(
+                model_name="SomeModel",
+                old_name="old_name",
+                new_name="new_name",
+            )
+        self.assertSerializedEqual(operation)
+
     def test_simple_migration(self):
         """
         Tests serializing a simple migration.
comment:3 by , 11 years ago
| Has patch: | set | 
|---|
PR: https://github.com/django/django/pull/4075
MigrationsWriter._serialize_path() now checks if there is a dot in the path, and if there isn't, assumes it is a class in django.db.migrations. As this module is always imported in generated migrations, I changed the imports to an empty dict and the name to migrations.<ClassName>. 
This bug was caused by the fact that Operation.deconstruct() returns the class name as the first value instead of the full import path. 
follow-up: 5 comment:4 by , 11 years ago
| Cc: | added | 
|---|---|
| Patch needs improvement: | set | 
I don't think this is the way to go. I'd prefer to find a way to use the django.db.migrations.writer.OperationWriter instead. This would also take care of indenting the respective output.
comment:5 by , 11 years ago
Replying to MarkusH:
I don't think this is the way to go. I'd prefer to find a way to use the
django.db.migrations.writer.OperationWriterinstead. This would also take care of indenting the respective output.
Yes, that indeed seems to be a better approach. I've pushed a new patch that uses the OperationWriter instead. (PR)
I think I'm gonna try to refactor this so that the isinstance(value, Operation) check is moved to MigrationWriter.serialize(). This would leave the _write function in OperationWriter.serialize() as a more general function, while MigrationWriter.serialize() handles the value-specific serialization. _write would still need to be able to handle multi-line values, but this also opens up the possibility for other objects to serialize into a multi-line string. 
comment:6 by , 11 years ago
| Patch needs improvement: | unset | 
|---|
comment:8 by , 11 years ago
| Cc: | added | 
|---|
comment:9 by , 11 years ago
| Patch needs improvement: | unset | 
|---|---|
| Triage Stage: | Accepted → Ready for checkin | 
| Version: | 1.7 → 1.8 | 
Confirmed, working on this now.