pythongoogle-app-enginetipfy

Why would Python give me a "TypeError: argument of type 'UserAgent' is not iterable" in a non-iteration type of operation?


I have a BaseHandler class that subclasses the Tipfy RequestHandler in my AppEngine site. In it, I have setup a "poor man's" browser sniffer for mobile devices with a class attribute (a tuple) containing device names.

In a subsequent method, I loop through the device names in the tuple and check them against the user agent string from the Request object. If I get a match, I set an instance attribute called "is_mobile" to True.

In that method, however, Python is giving me a "TypeError: argument of type 'UserAgent' is not iterable" error, and I can't understand why, since the line it is complaining about is not (as far as I understand) a loop.

Here is the code:

class BaseHandler(RequestHandler, AppEngineAuthMixin, AllSessionMixins):

    mobile_devices = ('Android', 'iPhone', 'iPod', 'Blackberry')

    ....

    def detect_mobile_devices(self):
        found_device = False

        for device in self.__class__.mobile_devices:
            if device in self.request.user_agent:
                found_device = True
                break

        self.is_mobile = found_device

Here is the line Python does not like:

File "/path/to/project/app/apps/remember_things/handlers.py", line 56, in detect_mobile_devices
if device in self.request.user_agent:

Solution

  • The expression

    device in self.request.user_agent
    

    will first try to call

    self.request.user_agent.__contains__(device)
    

    If this method does not exist, Python tries to iterate over self.request.user_agent and compares each item it encounters to device. Obviously, the type of self.request.user_agent neither allows .__contains__() nor iteration, hence the error message.

    Also see the documentation of membership test in Python.