#36750: dumpdata's output of m2m values is not deterministic
-------------------------------------+-------------------------------------
     Reporter:  Jacob Walls          |                     Type:  Bug
       Status:  new                  |                Component:  Core
                                     |  (Serialization)
      Version:  dev                  |                 Severity:  Normal
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 Recent failure of `main-random` CI job reveals that dumpdata's output of
 m2m values is not deterministic:

 {{{
 ./runtests.py fixtures --shuffle 7825542710 --settings=test_postgres -k
 forward -v2
 }}}

 {{{
 test_forward_reference_fk
 (fixtures.tests.ForwardReferenceTests.test_forward_reference_fk) ... ok
 test_forward_reference_m2m
 (fixtures.tests.ForwardReferenceTests.test_forward_reference_m2m) ... ok
 test_forward_reference_fk_natural_key
 (fixtures.tests.ForwardReferenceTests.test_forward_reference_fk_natural_key)
 ... ok
 test_forward_reference_m2m_natural_key
 (fixtures.tests.ForwardReferenceTests.test_forward_reference_m2m_natural_key)
 ... FAIL

 ======================================================================
 FAIL: test_forward_reference_m2m_natural_key
 (fixtures.tests.ForwardReferenceTests.test_forward_reference_m2m_natural_key)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "/Users/jwalls/django/tests/fixtures/tests.py", line 1308, in
 test_forward_reference_m2m_natural_key
     self._dumpdata_assert(
     ~~~~~~~~~~~~~~~~~~~~~^
         ["fixtures"],
         ^^^^^^^^^^^^^
     ...<8 lines>...
         natural_foreign_keys=True,
         ^^^^^^^^^^^^^^^^^^^^^^^^^^
     )
     ^
   File "/Users/jwalls/django/tests/fixtures/tests.py", line 127, in
 _dumpdata_assert
     self.assertJSONEqual(command_output, output)
     ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
 AssertionError: Lists differ: [{'mo[94 chars] [['t3'], ['t2']]}},
 {'model': 'fixtures.natur[179 chars][]}}] != [{'mo[94 chars] [['t2'],
 ['t3']]}}, {'model': 'fixtures.natur[179 chars][]}}]

 First differing element 0:
 {'mod[49 chars]: 't1', 'other_thing': None, 'other_things': [['t3'],
 ['t2']]}}
 {'mod[49 chars]: 't1', 'other_thing': None, 'other_things': [['t2'],
 ['t3']]}}

   [{'fields': {'key': 't1',
                'other_thing': None,
 -              'other_things': [['t3'], ['t2']]},
 ?                                     --------

 +              'other_things': [['t2'], ['t3']]},
 ?                               ++++++++

     'model': 'fixtures.naturalkeything'},
    {'fields': {'key': 't2', 'other_thing': None, 'other_things': []},
     'model': 'fixtures.naturalkeything'},
    {'fields': {'key': 't3', 'other_thing': None, 'other_things': []},
     'model': 'fixtures.naturalkeything'}]

 ----------------------------------------------------------------------
 Ran 4 tests in 0.071s

 FAILED (failures=1)
 Used shuffle seed: 7825542710 (given)
 }}}

 ----
 In the spirit of #24558 and #10381, I'm suggesting to make this
 deterministic instead of fiddling with the test.

 A naive diff just adding ordering by "pk" fixes the failure ...:

 {{{#!py
 diff --git a/django/core/serializers/python.py
 b/django/core/serializers/python.py
 index 2929874b01..496d3a5ba6 100644
 --- a/django/core/serializers/python.py
 +++ b/django/core/serializers/python.py
 @@ -74,7 +74,7 @@ class Serializer(base.Serializer):
                      return value.natural_key()

                  def queryset_iterator(obj, field):
 -                    attr = getattr(obj, field.name)
 +                    attr = getattr(obj, field.name).order_by("pk")  # !!!
 not right
                      chunk_size = (
                          2000 if getattr(attr, "prefetch_cache_name",
 None) else None
                      )
 }}}

 ... but to be mergeable, the patch would need to:
 - get the default ordering from somewhere better (through model? target
 model?), instead of hardcoding "pk"
 - check for all locations in the python and xml serializers that might
 need this change
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36750>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019aa791b520-69f7f007-490e-4b99-9645-a347b0fad512-000000%40eu-central-1.amazonses.com.

Reply via email to