Opened 2 years ago

Closed 2 years ago

#27081 closed Bug (fixed)

Allow migrations to serialize methods on pypy

Reported by: Sergey Kurdakov Owned by: nobody
Component: Migrations Version: 1.9
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Sergey Kurdakov)

if model contains DateField and it is initialized with current date

example:

from datetime import date

class TestClass(models.Model):

    start_date = models.DateField(
        verbose_name=u'start date',
        default=date.today,
        )

pypy migrations will fail

django/db/migrations/writer.py", line 540, in serialize "topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <bound method type.today of <class 'datetime.date'>>

reason:
code for serialising methods in Django checks
if isinstance(value, (types.FunctionType, types.BuiltinFunctionType))
which succeeds on cpython because datetime.date.today is a
BuiltinFunctionType, wheras it's a types.MethodType on pypy and this check is missing in django
( link https://github.com/django/django/blob/3b383085fb89a48e756383e7cd5d3bd867353ba1/django/db/migrations/serializer.py#L379 )

a solution for client code is to declare local function

def today():
    return date.today()


class TestClass(models.Model):

    start_date = models.DateField(
        verbose_name=u'start date',
        default=today,
        )

but would be better to add types.MethodType check for pypy compatibility

Change History (3)

comment:1 Changed 2 years ago by Sergey Kurdakov

Description: modified (diff)

comment:2 Changed 2 years ago by Tim Graham

Component: UncategorizedMigrations
Has patch: set
Summary: DateField with current date intitialisation pypy migration issueAllow migrations to serialize methods on pypy
Triage Stage: UnreviewedAccepted
Type: UncategorizedBug

Seems okay. That proposed change fixes these existing test failures on pypy, so I guess no new tests are needed:

======================================================================
ERROR: test_serialize_datetime (migrations.test_writer.WriterTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/tests/migrations/test_writer.py", line 330, in test_serialize_datetime
    self.assertSerializedEqual(datetime.datetime.utcnow)
  File "/home/tim/code/django/tests/migrations/test_writer.py", line 194, in assertSerializedEqual
    self.assertEqual(self.serialize_round_trip(value), value)
  File "/home/tim/code/django/tests/migrations/test_writer.py", line 190, in serialize_round_trip
    string, imports = MigrationWriter.serialize(value)
  File "/home/tim/code/django/django/db/migrations/writer.py", line 293, in serialize
    return serializer_factory(value).serialize()
  File "/home/tim/code/django/django/db/migrations/serializer.py", line 388, in serializer_factory
    "topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <bound method type.utcnow of <class 'datetime.datetime'>>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/dev/topics/migrations/#migration-serializing

======================================================================
ERROR: test_simple_migration (migrations.test_writer.WriterTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/tests/migrations/test_writer.py", line 542, in test_simple_migration
    output = writer.as_string()
  File "/home/tim/code/django/django/db/migrations/writer.py", line 163, in as_string
    operation_string, operation_imports = OperationWriter(operation).serialize()
  File "/home/tim/code/django/django/db/migrations/writer.py", line 120, in serialize
    _write(arg_name, arg_value)
  File "/home/tim/code/django/django/db/migrations/writer.py", line 72, in _write
    arg_string, arg_imports = MigrationWriter.serialize(item)
  File "/home/tim/code/django/django/db/migrations/writer.py", line 293, in serialize
    return serializer_factory(value).serialize()
  File "/home/tim/code/django/django/db/migrations/serializer.py", line 43, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
  File "/home/tim/code/django/django/db/migrations/serializer.py", line 228, in serialize
    return self.serialize_deconstructed(path, args, kwargs)
  File "/home/tim/code/django/django/db/migrations/serializer.py", line 100, in serialize_deconstructed
    arg_string, arg_imports = serializer_factory(arg).serialize()
  File "/home/tim/code/django/django/db/migrations/serializer.py", line 388, in serializer_factory
    "topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <bound method type.utcnow of <class 'datetime.datetime'>>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/dev/topics/migrations/#migration-serializing

PR

comment:3 Changed 2 years ago by GitHub <noreply@…>

Resolution: fixed
Status: newclosed

In 96ee486e:

Fixed #27081 -- Allowed migrations to serialize methods on pypy.

Note: See TracTickets for help on using tickets.
Back to Top