Merge lp:~allenap/maas/urlencode-is-duckist into lp:~maas-committers/maas/trunk

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 1083
Proposed branch: lp:~allenap/maas/urlencode-is-duckist
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 56 lines (+28/-1)
2 files modified
src/maascli/api.py (+1/-1)
src/maascli/tests/test_api.py (+27/-0)
To merge this branch: bzr merge lp:~allenap/maas/urlencode-is-duckist
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+126584@code.launchpad.net

Commit message

Always return a 2-tuple from name_value_pair.

urllib.urlencode has some fairly duckist code. It doesn't let the data it consumes walk and quack like a duck. It insists that the first item in a non-dict sequence is a tuple. Of any size. It does this in the name of avoiding *string* input.

Description of the change

urllib.urlencode has some fairly duckist code. It doesn't let the data
it consumes walk and quack like a duck. It insists that the first item
in a non-dict sequence is a tuple. Of any size. It does this in the
name of avoiding *string* input.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Looks ok.

34 + # The tuple is important because this is used as input to urlencode,
35 + # which refuses to let ducks quack.

I'd expand this to include this explanation you've got in the commit msg about urlencode's requirement for a tuple. It just reads as a rant otherwise :)

review: Approve
Revision history for this message
Gavin Panella (allenap) wrote :

> I'd expand this to include this explanation you've got in the commit msg about
> urlencode's requirement for a tuple. It just reads as a rant otherwise :)

Okay, but it *is* a rant. It's late/early here :)

Thanks for the review.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maascli/api.py'
2--- src/maascli/api.py 2012-09-26 13:07:08 +0000
3+++ src/maascli/api.py 2012-09-27 03:05:23 +0000
4@@ -241,7 +241,7 @@
5 def name_value_pair(string):
6 parts = string.split("=", 1)
7 if len(parts) == 2:
8- return parts
9+ return tuple(parts)
10 else:
11 raise CommandError(
12 "%r is not a name=value pair" % string)
13
14=== modified file 'src/maascli/tests/test_api.py'
15--- src/maascli/tests/test_api.py 2012-09-26 13:17:05 +0000
16+++ src/maascli/tests/test_api.py 2012-09-27 03:05:23 +0000
17@@ -28,6 +28,8 @@
18 from testtools.matchers import (
19 Equals,
20 Is,
21+ IsInstance,
22+ MatchesAll,
23 MatchesListwise,
24 )
25
26@@ -127,6 +129,31 @@
27 "%s" % error)
28
29
30+class TestAction(TestCase):
31+ """Tests for :class:`maascli.api.Action`."""
32+
33+ def test_name_value_pair_returns_2_tuple(self):
34+ # The tuple is important because this is used as input to
35+ # urllib.urlencode, which doesn't let the data it consumes walk and
36+ # quack like a duck. It insists that the first item in a non-dict
37+ # sequence is a tuple. Of any size. It does this in the name of
38+ # avoiding *string* input.
39+ result = api.Action.name_value_pair("foo=bar")
40+ self.assertThat(
41+ result, MatchesAll(
42+ Equals(("foo", "bar")),
43+ IsInstance(tuple)))
44+
45+ def test_name_value_pair_demands_two_parts(self):
46+ self.assertRaises(
47+ CommandError, api.Action.name_value_pair, "foo bar")
48+
49+ def test_name_value_pair_does_not_strip_whitespace(self):
50+ self.assertEqual(
51+ (" foo ", " bar "),
52+ api.Action.name_value_pair(" foo = bar "))
53+
54+
55 class TestActionReSTful(TestCase):
56 """Tests for ReSTful operations in `maascli.api.Action`."""
57