Search code examples
pythondjangopython-2.7optparse

Custom Django management commands broken on Windows


I am currently working to upgrade from django 1.3 to 1.8. I have my app working on Ubuntu (Ubuntu 16.04) now however am having problems with the Windows version.

When I run my custom management commands on Windows the following errors are generated:

Traceback (most recent call last):
  File "D:\src\proj\grp\tests\test_list_members.py", line 29, in setUp
call_command('syncgroups')
  File "D:\src\env\lib\site-packages\django\core\management\__init__.py", line 103, in call_command
parser = command.create_parser('', name)
  File "D:\src\env\lib\site-packages\django\core\management\base.py", line 316, in create_parser
help='Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output')
  File "C:\Python27\Lib\optparse.py", line 1018, in add_option
raise TypeError, "invalid arguments"
TypeError: invalid arguments

I have managed to locate the source of the issue, it appears that the handling of __future__.unicode_literals is different on Windows than on Ubuntu. For example the following works on Ubuntu but not on Windows (the same TypeError error as above is seen)

from __future__ import unicode_literals
from optparse import OptionParser

OptionParser().add_option('-v', '--verbose')

Does this mean that Django 1.8 no longer supports custom management commands on Windows?

Any workarounds would be greatly appreciated!


Solution

  • The problem was the version of OptionParser installed on my Windows machine had not been updated to support Unicode properly. Updating my python installation was the best solution however a temporary workaround was also possible.

    Making the following change to %PYTHONHOME%\Lib\optparse.py resolved this issue...

    1006    ...
    1007    def add_option(self, *args, **kwargs):
    1008        """add_option(Option)
    1009           add_option(opt_str, ..., kwarg=val, ...)
    1010        """
        +-      if type(args[0]) in types.StringTypes:
    1012            option = self.option_class(*args, **kwargs)
    1013        elif len(args) == 1 and not kwargs:
    1014            option = args[0]
    1015    ...