Merge lp:~james-w/django-configglue/fix-argv into lp:django-configglue

Proposed by James Westby
Status: Merged
Approved by: Ricardo Kirkner
Approved revision: 70
Merged at revision: 68
Proposed branch: lp:~james-w/django-configglue/fix-argv
Merge into: lp:django-configglue
Diff against target: 109 lines (+62/-2)
2 files modified
django_configglue/management/__init__.py (+51/-1)
django_configglue/tests/test_configglue.py (+11/-1)
To merge this branch: bzr merge lp:~james-w/django-configglue/fix-argv
Reviewer Review Type Date Requested Status
Ricardo Kirkner Approve
Review via email: mp+88446@code.launchpad.net

Commit message

Stop 'value' being added to argv when '--unknown-option=value' is passed.

Description of the change

Hi,

As discussed this fixes a problem with Django's LaxOptionParser.

I added the test as you suggested and it fails before as expected, and succeeds
after.

I ended up writing my own init script that avoided the issues I was having, so
this isn't blocking our deployment, but it would still be good to have a solution.

Thanks,

James

To post a comment you must log in.
Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

A few remarks:

1. l.23-24: please leave only one blank line here
2. l.71: there is now explanation (nor test) of why this monkeypatch is needed
3. l.72-74: please remove the trailing blank lines

When done, please also add a commit message for tarmac to be able to merge this branch.

review: Needs Fixing
Revision history for this message
James Westby (james-w) wrote :

Hi,

I made those changes as requested (dropping the monkeypatch.)

Thanks,

James

70. By James Westby

Tweaks from review, thanks Ricardo.

Revision history for this message
Ricardo Kirkner (ricardokirkner) wrote :

LGTM. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'django_configglue/management/__init__.py'
2--- django_configglue/management/__init__.py 2011-07-27 00:14:34 +0000
3+++ django_configglue/management/__init__.py 2012-01-13 15:14:23 +0000
4@@ -5,17 +5,67 @@
5 # except where third-party/django/LICENSE applies.
6
7
8+from optparse import BadOptionError
9 import sys
10
11 import django
12 import django.core.management
13 from configglue.glue import schemaconfigglue
14-from django.core.management import ManagementUtility, LaxOptionParser
15+from django.core.management import ManagementUtility, LaxOptionParser as _LaxOptionParser
16 from django.core.management.base import BaseCommand, handle_default_options
17 from django.conf import settings
18 from django_configglue import utils
19
20
21+class LaxOptionParser(_LaxOptionParser):
22+ # Subclasses django's to avoid a bug
23+
24+ def _process_long_opt(self, rargs, values):
25+ arg = rargs.pop(0)
26+
27+ # Value explicitly attached to arg? Pretend it's the next
28+ # argument.
29+ if "=" in arg:
30+ (opt, next_arg) = arg.split("=", 1)
31+ rargs.insert(0, next_arg)
32+ had_explicit_value = True
33+ else:
34+ opt = arg
35+ had_explicit_value = False
36+
37+ try:
38+ opt = self._match_long_opt(opt)
39+ except BadOptionError:
40+ # Here's the addition in our subclass, we take care to take
41+ # the value back out of rargs so that it isn't duplicated if
42+ # this code path is hit.
43+ if had_explicit_value:
44+ rargs.pop(0)
45+ raise
46+ option = self._long_opt[opt]
47+ if option.takes_value():
48+ nargs = option.nargs
49+ if len(rargs) < nargs:
50+ if nargs == 1:
51+ self.error(_("%s option requires an argument") % opt)
52+ else:
53+ self.error(_("%s option requires %d arguments")
54+ % (opt, nargs))
55+ elif nargs == 1:
56+ value = rargs.pop(0)
57+ else:
58+ value = tuple(rargs[0:nargs])
59+ del rargs[0:nargs]
60+
61+ elif had_explicit_value:
62+ self.error(_("%s option does not take a value") % opt)
63+
64+ else:
65+ value = None
66+
67+ option.process(opt, value, values, self)
68+
69+
70 class GlueManagementUtility(ManagementUtility):
71 # This function was mostly taken from the django project.
72 # Please see the license file in the third-party/django directory.
73
74=== modified file 'django_configglue/tests/test_configglue.py'
75--- django_configglue/tests/test_configglue.py 2011-09-16 23:11:02 +0000
76+++ django_configglue/tests/test_configglue.py 2012-01-13 15:14:23 +0000
77@@ -5,6 +5,7 @@
78 import inspect
79 import textwrap
80 from cStringIO import StringIO
81+from optparse import BadOptionError
82 from unittest import TestCase
83
84 import django
85@@ -27,7 +28,7 @@
86 from django.conf.project_template import settings as project_settings
87 from mock import patch
88
89-from django_configglue.management import GlueManagementUtility
90+from django_configglue.management import GlueManagementUtility, LaxOptionParser
91 from django_configglue.utils import (
92 SETTINGS_ENCODING,
93 configglue,
94@@ -408,6 +409,15 @@
95 self.assertTrue('Show settings attributes' in self.capture['stdout'])
96
97
98+class LaxOptionParserTestCase(TestCase):
99+
100+ def test_explicit_value_for_unknown_option(self):
101+ parser = LaxOptionParser()
102+ rargs = ["--foo=bar"]
103+ self.assertRaises(BadOptionError, parser._process_long_opt, rargs, [])
104+ self.assertEqual([], rargs)
105+
106+
107 class UpperCaseDictOptionTestCase(TestCase):
108 def test_parse(self):
109 class MySchema(Schema):

Subscribers

People subscribed via source and target branches

to all changes: