Django 1.6 is Coming!

How hard will it be to upgrade?

Karen Tracey, ShipIt day 4Q2013

CCSR "SAM" Project

  • SAM is Survey Admin Module
  • Good-sized project (8 internal apps)
  • Caktus-built, so no "baggage"
  • Recently upgraded Django 1.3 -> 1.5
  • 861 tests (all pass), ~half hour to run
  • 94% statement test coverage

Hoped to Learn

  • transaction.atomic
  • New test discovery runner
  • Python 3?

Process

  1. Upgrade JUST Django
  2. manage.py check
  3. manage.py shell
  4. manage.py test
  5. python -Wall manage.py test
  6. Figure out how to get coverage with new runner
  7. Ultimately only got to #5
  8. Boom! on #2

Snag #1

  • Cannot import UNUSABLE_PASSWORD
  • Internal bit of Django we used
  • Django now pads this to a longer size
  • More secure (can't tell who has unusable pw)
  • Small changes to adjust our use
  • Lesson learned: internals change

Snag #2

  • Cannot import MAXIMUM_PASSWORD_LENGTH
  • Very short-lived constant from Django
  • Get rid of it & 2 tests that used it
  • Lesson learned: don't be so quick to upgrade
  • (Kidding! That was a security release...)

Snag #3

  • Now on step 4 (test)
  • All tests fail
  • BooleanField no longer has False default
  • Easy fix (but kinda annoying)
  • Lesson learned: be explicit

Snag #4

  • Debug toolbar using url defaults
  • Likely needs upgrade
  • Quicker fix just to remove it
  • Lesson learned: DDT should be in core
  • (Kidding!)

Some tests pass!

  • 859 tests, 20% faster
  • No idea if that 20% faster is repeatable
  • 1 failure, 19 errors
  • 4 underlying issues

Issue #1

JSON session serializer (7)

  • Default used to be pickle
  • Now it's JSON
  • Can't store model instances with JSON
  • Setting change to fix
  • After convincind self "safe"
  • Lesson learned: Django pushing security

Issue #2

urlparse.urlsplit no longer works (6)

  • We did: from django.http.utils import urlparse
  • Used to be equivalent to: import urlparse
  • Is not any more (Py3, six related)
  • Fix is to import urlparse
  • Lesson learned: don't use internals when unnecessary

Issue #3

WSGIRequest object has no attribute raw_post_data (3)

  • This was renamed to body
  • Easy fix
  • Lesson learned: run with -Wall more often!

Issue #4

Password reset tests failing (3)

  • Worked if you did it manually!
  • Tests claimed bad token
  • Really user wasn't being found
  • Django changed user pk encoding in token
  • Tests used Django for generating token
  • ...but SAM code to decode
  • Site mostly uses SAM code for both
  • Fix to upgrade SAM code to new encoding
  • Lesson learned: Hmmm...

Issue tests did not find

  • BoundField.label_tag now includes the form’s label_suffix
  • Sigh, at least it's documented
  • Lesson learned: read ALL the release notes
  • Lesson learned: keep in mind Django warts, they may get "fixed"