Source code for werkzeug.useragents

# -*- coding: utf-8 -*-

    This module provides a helper to inspect user agent strings.  This module
    is far from complete but should work for most of the currently available

    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
import re

class UserAgentParser(object):

    """A simple user agent parser.  Used by the `UserAgent`."""

    platforms = (
        ('cros', 'chromeos'),
        ('iphone|ios', 'iphone'),
        ('ipad', 'ipad'),
        (r'darwin|mac|os\s*x', 'macos'),
        ('win', 'windows'),
        (r'android', 'android'),
        (r'x11|lin(\b|ux)?', 'linux'),
        ('(sun|i86)os', 'solaris'),
        (r'nintendo\s+wii', 'wii'),
        ('irix', 'irix'),
        ('hp-?ux', 'hpux'),
        ('aix', 'aix'),
        ('sco|unix_sv', 'sco'),
        ('bsd', 'bsd'),
        ('amiga', 'amiga'),
        ('blackberry|playbook', 'blackberry'),
        ('symbian', 'symbian')
    browsers = (
        ('googlebot', 'google'),
        ('msnbot', 'msn'),
        ('yahoo', 'yahoo'),
        ('ask jeeves', 'ask'),
        (r'aol|america\s+online\s+browser', 'aol'),
        ('opera', 'opera'),
        ('chrome', 'chrome'),
        ('firefox|firebird|phoenix|iceweasel', 'firefox'),
        ('galeon', 'galeon'),
        ('safari|version', 'safari'),
        ('webkit', 'webkit'),
        ('camino', 'camino'),
        ('konqueror', 'konqueror'),
        ('k-meleon', 'kmeleon'),
        ('netscape', 'netscape'),
        (r'msie|microsoft\s+internet\s+explorer|trident/.+? rv:', 'msie'),
        ('lynx', 'lynx'),
        ('links', 'links'),
        ('seamonkey|mozilla', 'seamonkey')

    _browser_version_re = r'(?:%s)[/\sa-z(]*(\d+[.\da-z]+)?(?i)'
    _language_re = re.compile(

    def __init__(self):
        self.platforms = [(b, re.compile(a, re.I)) for a, b in self.platforms]
        self.browsers = [(b, re.compile(self._browser_version_re % a))
                         for a, b in self.browsers]

    def __call__(self, user_agent):
        for platform, regex in self.platforms:
            match =
            if match is not None:
            platform = None
        for browser, regex in self.browsers:
            match =
            if match is not None:
                version =
            browser = version = None
        match =
        if match is not None:
            language = or
            language = None
        return platform, browser, version, language

[docs]class UserAgent(object): """Represents a user agent. Pass it a WSGI environment or a user agent string and you can inspect some of the details from the user agent string via the attributes. The following attributes exist: .. attribute:: string the raw user agent string .. attribute:: platform the browser platform. The following platforms are currently recognized: - `aix` - `amiga` - `android` - `bsd` - `chromeos` - `hpux` - `iphone` - `ipad` - `irix` - `linux` - `macos` - `sco` - `solaris` - `wii` - `windows` .. attribute:: browser the name of the browser. The following browsers are currently recognized: - `aol` * - `ask` * - `camino` - `chrome` - `firefox` - `galeon` - `google` * - `kmeleon` - `konqueror` - `links` - `lynx` - `msie` - `msn` - `netscape` - `opera` - `safari` - `seamonkey` - `webkit` - `yahoo` * (Browsers maked with a star (``*``) are crawlers.) .. attribute:: version the version of the browser .. attribute:: language the language of the browser """ _parser = UserAgentParser()
[docs] def __init__(self, environ_or_string): if isinstance(environ_or_string, dict): environ_or_string = environ_or_string.get('HTTP_USER_AGENT', '') self.string = environ_or_string self.platform, self.browser, self.version, self.language = \ self._parser(environ_or_string)
[docs] def to_header(self): return self.string
def __str__(self): return self.string def __nonzero__(self): return bool(self.browser) __bool__ = __nonzero__ def __repr__(self): return '<%s %r/%s>' % ( self.__class__.__name__, self.browser, self.version )
# conceptionally this belongs in this module but because we want to lazily # load the user agent module (which happens in we have to import # it afterwards. The class itself has the module set to this module so # pickle, inspect and similar modules treat the object as if it was really # implemented here. from werkzeug.wrappers import UserAgentMixin # noqa