-1

So I have a page that is expected to return content or return a 403 page in django

response = self.client.get(...)
print response.status_code
print type(response.status_code)
assert response.status_code is 200
print "WHAT IS GOING ON!?!?!?!"
response = self.client.get(...)
code = response.status_code
print code
print type(code)
assert code is 403
print "hmm"

Which returns the output:

200
<type 'int'>
WHAT IS GOING ON!?!?!?!
403
<type 'int'>

Clearly the code is failing at assert code is 403 but I can't imagine why. I even sanity checked myself by changing the line to assert 403 is 403 and the test passed. I'm new to Python and Django so I might be missing something obvious.

Syed Farjad Zia Zaidi
  • 3,302
  • 4
  • 27
  • 50
user833970
  • 2,729
  • 3
  • 26
  • 41
  • thanks for the nija edits, you just beat me to it – user833970 May 27 '14 at 22:09
  • 1
    try `==` instead of `is` because the 200 value is not necessarily the same object that what you are comparing – daouzli May 27 '14 at 22:11
  • the 200 assert works the 403 does not. and == is a good work around but It would be good to know why. – user833970 May 27 '14 at 22:12
  • 1
    [see](http://stackoverflow.com/questions/2988017/string-comparison-in-python-is-vs) – daouzli May 27 '14 at 22:14
  • 2
    If `==` works and `is` does not, then you're using `is` incorrectly anyway. Testing for equality should be done using `==`. Is should _only_ be for verifying an object is the _exact same_ object. – g.d.d.c May 27 '14 at 22:15
  • Not sure why the downvotes, it's actually a pretty interesting issue to run into if you're not experienced yet with the language. – Botond Béres May 27 '14 at 22:25
  • @Béres Botond The down votes were for some cursing I had forgot to edit out of the code snip-it before posting. They are entirely deserved. – user833970 May 28 '14 at 02:45

2 Answers2

5
In [15]: id(code)
Out[15]: 29536080

In [16]: id(403)
Out[16]: 29535960

Using is, you are asking if code and 403 are the same object.

As you can see from the ids, they are not. You need 403 == code to compare values.

Python caches values for small integers from -5 to 256, that is why your is comparison worked for 200.

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

from the docs here

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
2

The is keyword in Python tests identity, not equality.

To put it another way, it tests that two objects are the exact same object. The object you're comparing, response.status_code, is a different object than 403, likely because the 403 object is a temporary object created on the stack (for lack of a better description). The two objects will have different memory addresses.

I suppose it's by chance that the test against 200 earlier on worked, but I would expect it to be able to fail for the same reason.

Community
  • 1
  • 1
kevintodisco
  • 5,061
  • 1
  • 22
  • 28