pax_global_header00006660000000000000000000000064134523524750014524gustar00rootroot0000000000000052 comment=a4c59e1dd6230e7c6fcd4e3ff21a71cbc25dc604 python-user-agents-2.0/000077500000000000000000000000001345235247500151415ustar00rootroot00000000000000python-user-agents-2.0/.gitignore000066400000000000000000000000771345235247500171350ustar00rootroot00000000000000node_modules/ .DS* TAGS dist cabal-dev *.pyc build/ *.egg-info python-user-agents-2.0/.travis.yml000066400000000000000000000003571345235247500172570ustar00rootroot00000000000000sudo: false language: python dist: xenial python: - "2.7" - "3.4" - "3.5" - "3.6" - "3.7" install: - "python setup.py install" - "pip install -U pip" - "pip install pyyaml ua-parser" script: - python -m unittest discover python-user-agents-2.0/AUTHORS.txt000066400000000000000000000001521345235247500170250ustar00rootroot00000000000000Author: * Selwin Ong (https://github.com/selwin) * Loisaida Sam Sandberg (https://github.com/loisaidasam)python-user-agents-2.0/LICENSE.txt000066400000000000000000000020351345235247500167640ustar00rootroot00000000000000Copyright (c) 2013 Selwin Ong Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.python-user-agents-2.0/MANIFEST000066400000000000000000000002451345235247500162730ustar00rootroot00000000000000# file GENERATED by distutils, do NOT edit LICENSE.txt README.rst setup.py user_agents/__init__.py user_agents/compat.py user_agents/parsers.py user_agents/tests.py python-user-agents-2.0/MANIFEST.in000066400000000000000000000000461345235247500166770ustar00rootroot00000000000000include LICENSE.txt include README.rstpython-user-agents-2.0/README.rst000066400000000000000000000152301345235247500166310ustar00rootroot00000000000000Python User Agents ================== ``user_agents`` is a Python library that provides an easy way to identify/detect devices like mobile phones, tablets and their capabilities by parsing (browser/HTTP) user agent strings. The goal is to reliably detect whether: - User agent is a mobile, tablet or PC based device - User agent has touch capabilities (has touch screen) ``user_agents`` relies on the excellent `ua-parser `_ to do the actual parsing of the raw user agent string. Installation ------------ .. figure:: https://secure.travis-ci.org/selwin/python-user-agents.png :alt: Build status Build status ``user-agents`` is hosted on `PyPI `__ and can be installed as such: :: pip install pyyaml ua-parser user-agents Alternatively, you can also get the latest source code from Github_ and install it manually. .. _Github: https://github.com/selwin/python-user-agents Usage ----- Various basic information that can help you identify visitors can be accessed ``browser``, ``device`` and ``os`` attributes. For example: .. code:: python from user_agents import parse # iPhone's user agent string ua_string = 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3' user_agent = parse(ua_string) # Accessing user agent's browser attributes user_agent.browser # returns Browser(family=u'Mobile Safari', version=(5, 1), version_string='5.1') user_agent.browser.family # returns 'Mobile Safari' user_agent.browser.version # returns (5, 1) user_agent.browser.version_string # returns '5.1' # Accessing user agent's operating system properties user_agent.os # returns OperatingSystem(family=u'iOS', version=(5, 1), version_string='5.1') user_agent.os.family # returns 'iOS' user_agent.os.version # returns (5, 1) user_agent.os.version_string # returns '5.1' # Accessing user agent's device properties user_agent.device # returns Device(family=u'iPhone', brand=u'Apple', model=u'iPhone') user_agent.device.family # returns 'iPhone' user_agent.device.brand # returns 'Apple' user_agent.device.model # returns 'iPhone' # Viewing a pretty string version str(user_agent) # returns "iPhone / iOS 5.1 / Mobile Safari 5.1" ``user_agents`` also expose a few other more "sophisticated" attributes that are derived from one or more basic attributes defined above. As for now, these attributes should correctly identify popular platforms/devices, pull requests to support smaller ones are always welcome. Currently these attributes are supported: - ``is_mobile``: whether user agent is identified as a mobile phone (iPhone, Android phones, Blackberry, Windows Phone devices etc) - ``is_tablet``: whether user agent is identified as a tablet device (iPad, Kindle Fire, Nexus 7 etc) - ``is_pc``: whether user agent is identified to be running a traditional "desktop" OS (Windows, OS X, Linux) - ``is_touch_capable``: whether user agent has touch capabilities - ``is_bot``: whether user agent is a search engine crawler/spider For example: .. code:: python from user_agents import parse # Let's start from an old, non touch Blackberry device ua_string = 'BlackBerry9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/331 UNTRUSTED/1.0 3gpp-gba' user_agent = parse(ua_string) user_agent.is_mobile # returns True user_agent.is_tablet # returns False user_agent.is_touch_capable # returns False user_agent.is_pc # returns False user_agent.is_bot # returns False str(user_agent) # returns "BlackBerry 9700 / BlackBerry OS 5 / BlackBerry 9700" # Now a Samsung Galaxy S3 ua_string = 'Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' user_agent = parse(ua_string) user_agent.is_mobile # returns True user_agent.is_tablet # returns False user_agent.is_touch_capable # returns True user_agent.is_pc # returns False user_agent.is_bot # returns False str(user_agent) # returns "Samsung GT-I9300 / Android 4.0.4 / Android 4.0.4" # iPad's user agent string ua_string = 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10' user_agent = parse(ua_string) user_agent.is_mobile # returns False user_agent.is_tablet # returns True user_agent.is_touch_capable # returns True user_agent.is_pc # returns False user_agent.is_bot # returns False str(user_agent) # returns "iPad / iOS 3.2 / Mobile Safari 4.0.4" # Kindle Fire's user agent string ua_string = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true' user_agent = parse(ua_string) user_agent.is_mobile # returns False user_agent.is_tablet # returns True user_agent.is_touch_capable # returns True user_agent.is_pc # returns False user_agent.is_bot # returns False str(user_agent) # returns "Kindle / Android / Amazon Silk 1.1.0-80" # Touch capable Windows 8 device ua_string = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)' user_agent = parse(ua_string) user_agent.is_mobile # returns False user_agent.is_tablet # returns False user_agent.is_touch_capable # returns True user_agent.is_pc # returns True user_agent.is_bot # returns False str(user_agent) # returns "PC / Windows 8 / IE 10" Running Tests ------------- :: python -m unittest discover Changelog --------- Version 2.0 (2019-04-07) ~~~~~~~~~~~~~~~~~~~~~~~~ - ``python-user-agents`` now require ``ua-parser>=0.8.0``. Thanks @IMDagger! Version 1.1 ~~~~~~~~~~~~~ - Fixes packaging issue Version 1.0 ~~~~~~~~~~~ - Adds compatibility with ``ua-parser`` 0.4.0 - Access to more device information in ``user_agent.device.brand`` and ``user_agent.device.model`` Version 0.3.2 ~~~~~~~~~~~~~ - Better mobile detection - Better PC detection Version 0.3.1 ~~~~~~~~~~~~~ - user\_agent.is\_mobile returns True when mobile spider is detected Version 0.3.0 ~~~~~~~~~~~~~ - Added **str**/**unicode** methods for convenience of pretty string Version 0.2.0 ~~~~~~~~~~~~~ - Fixed errors when running against newer versions if ua-parser - Support for Python 3 Version 0.1.1 ~~~~~~~~~~~~~ - Added ``is_bot`` property - Symbian OS devices are now detected as a mobile device Version 0.1 ~~~~~~~~~~~ - Initial release Developed by the cool guys at `Stamps `__. python-user-agents-2.0/setup.py000066400000000000000000000023411345235247500166530ustar00rootroot00000000000000# -*- coding: utf-8 -*- from setuptools import setup setup( name='user-agents', version='2.0', author='Selwin Ong', author_email='selwin.ong@gmail.com', packages=['user_agents'], url='https://github.com/selwin/python-user-agents', license='MIT', description='A library to identify devices (phones, tablets) and their capabilities by parsing (browser/HTTP) user agent strings', long_description=open('README.rst').read(), zip_safe=False, include_package_data=True, package_data={'': ['README.rst']}, install_requires=['ua-parser>=0.8.0'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development :: Libraries :: Python Modules', ] ) python-user-agents-2.0/user_agents/000077500000000000000000000000001345235247500174605ustar00rootroot00000000000000python-user-agents-2.0/user_agents/__init__.py000066400000000000000000000000601345235247500215650ustar00rootroot00000000000000VERSION = (2, 0, 0) from .parsers import parse python-user-agents-2.0/user_agents/compat.py000066400000000000000000000003631345235247500213170ustar00rootroot00000000000000import sys PY3 = sys.version_info[0] == 3 if PY3: string_types = str def iteritems(d, **kw): return iter(d.items(**kw)) else: string_types = basestring def iteritems(d, **kw): return iter(d.iteritems(**kw)) python-user-agents-2.0/user_agents/devices.json000066400000000000000000000341161345235247500220020ustar00rootroot00000000000000{ "android_firefox_aurora": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Android; Mobile; rv:27.0) Gecko/27.0 Firefox/27.0", "str": "Other / Android / Firefox Mobile 27" }, "blackberry_bold": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "BlackBerry9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/331 UNTRUSTED/1.0 3gpp-gba", "str": "BlackBerry 9700 / BlackBerry OS 5 / BlackBerry 9700" }, "blackberry_bold_touch": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.241 Mobile Safari/534.11+", "str": "BlackBerry 9930 / BlackBerry OS 7 / BlackBerry WebKit 7" }, "blackberry_torch": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; zh-TW) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.448 Mobile Safari/534.8+", "str": "BlackBerry 9800 / BlackBerry OS 6 / BlackBerry WebKit 6" }, "galaxy_s3": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", "str": "GT-I9300 / Android 4.0.4 / Android 4.0.4" }, "galaxy_tab": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "str": "SCH-I800 / Android 2.2 / Android 2.2" }, "google_bot": { "is_bot": true, "is_mobile": false, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "str": "Spider / Other / Googlebot 2.1" }, "ie": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)", "str": "PC / Windows 8 / IE 10" }, "ie_touch": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)", "str": "PC / Windows 8 / IE 10" }, "ipad": { "is_bot": false, "is_mobile": false, "is_pc": false, "is_tablet": true, "is_touch_capable": true, "ua_string": "Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10", "str": "iPad / iOS 3.2 / Mobile Safari 4.0.4" }, "iphone": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3", "str": "iPhone / iOS 5.1 / Mobile Safari 5.1" }, "j2me_opera": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (J2ME/22.478; U; en) Presto/2.5.25 Version/10.54", "str": "Other / Other / Opera Mini 9.80" }, "kindle_fire": { "is_bot": false, "is_mobile": false, "is_pc": false, "is_tablet": true, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true", "str": "Kindle Fire / Android / Amazon Silk 1.1.0-80" }, "mac_safari": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2", "str": "PC / Mac OS X 10.6.8 / WebKit Nightly 537.13" }, "nexus_5": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; Android 4.4.4; Nexus 5 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Mobile Safari/537.36", "str": "Nexus 5 / Android 4.4.4 / Chrome Mobile 37.0.2062" }, "nexus_7": { "is_bot": false, "is_mobile": false, "is_pc": false, "is_tablet": true, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19", "str": "Nexus 7 / Android 4.1.1 / Chrome 18.0.1025" }, "nokia_n9": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", "str": "Nokia N9 / MeeGo / Nokia Browser 8.5.0" }, "nokia_n97": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/12.0.024; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.12344", "str": "Nokia N97 / Symbian OS 9.4 / Nokia Browser 7.1.12344" }, "nokia_n900": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (X11; U; Linux armv7l; no-NO; rv:1.9.2.3pre) Gecko/20100723 Firefox/3.5 Maemo Browser 1.7.4.8 RX-51 N900", "str": "Nokia N900 / Maemo / Maemo Browser 1.7.4" }, "playbook": { "is_bot": false, "is_mobile": false, "is_pc": false, "is_tablet": true, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.0.1; en-US) AppleWebKit/535.8+ (KHTML, like Gecko) Version/7.2.0.1 Safari/535.8+", "str": "BlackBerry Playbook / BlackBerry Tablet OS 2.0.1 / BlackBerry WebKit 2.0.1" }, "playstation": { "is_bot": false, "is_mobile": false, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (PLAYSTATION 3 4.60) AppleWebKit/531.22.8 (KHTML, like Gecko)", "str": "PlayStation 3 / Other / NetFront NX" }, "playstation_vita": {"is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (PlayStation Vita 3.12) AppleWebKit/536.26 (KHTML, like Gecko) Silk/3.2", "str": "PlayStation Vita / Other / NetFront NX" }, "samsung_galaxy_s": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; Android 4.4.2; en-us; SAMSUNG SCH-I545 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36", "str": "SAMSUNG SCH-I545 / Android 4.4.2 / Chrome Mobile 28.0.1500" }, "samsung_galaxy_s_iii_mini": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; Android 4.1.2; GT-I8190 Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.117 Mobile Safari/537.36", "str": "GT-I8190 / Android 4.1.2 / Chrome Mobile 37.0.2062" }, "samsung_sm_galaxy_s5": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (Linux; Android 4.4.2; en-gb; SAMSUNG SM-G900F Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.6 Chrome/28.0.1500.94 Mobile Safari/537.36", "str": "SAMSUNG SM-G900F / Android 4.4.2 / Chrome Mobile 28.0.1500" }, "samsung_wave_ii": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8530/S8530DDLC2; U; Bada/2.0; en-us) AppleWebKit/534.20 (KHTML, like Gecko) Dolfin/3.0 Mobile WVGA SMM-MMS/1.2.0 OPN-B", "str": "Samsung GT-S8530 / Bada 2 / Dolfin 3" }, "ubuntu_firefox": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1", "str": "PC / Ubuntu / Firefox 15.0.1" }, "windows_ie": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", "str": "PC / Windows 7 / IE 9" }, "windows_phone": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; SGH-i917)", "str": "Samsung SGH-i917 / Windows Phone 7.5 / IE Mobile 9" }, "windows_rt": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": true, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)", "str": "PC / Windows RT / IE 10" }, "googlebot_mobile": { "is_bot": true, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (iPhone; U; CPU iPhone OS) (compatible; Googlebot-Mobile/2.1; http://www.google.com/bot.html)", "str": "Spider / Other / Mobile Safari" }, "googlebot_mobile_2": { "is_bot": true, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", "str": "Spider / Other / Mobile Safari" }, "googlebot_mobile_3": { "is_bot": true, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)", "str": "Spider / Other / Other" }, "windows_ce": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "SAMSUNG-SGH-I617/UCHJ1 Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)", "str": "Samsung SGH-I617 / Windows CE / IE Mobile 7.11" }, "windows_mobile": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": true, "ua_string": "Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 8.12; MSIEMobile 6.0) 320x240; VZW; UTStar-XV6175.1; Windows Mobile 6.5 Standard;", "str": "Other / Windows Mobile / IE Mobile 8.12" }, "opera_mobile": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": true, "is_touch_capable": true, "ua_string": "Opera/9.80 (Android 2.3.3; Linux; Opera Mobi/ADR-1202011015; U; en) Presto/2.9.201 Version/11.50", "str": "Opera / Android 2.3.3 / Opera Mobile 11.50" }, "opera_mini": { "is_bot": false, "is_mobile": true, "is_pc": false, "is_tablet": false, "is_touch_capable": false, "ua_string": "Opera/9.80 (BREW; Opera Mini/5.0/27.2370; U; en) Presto/2.8.119 240X320 Samsung SCH-U380", "str": "Opera / Android 2.3.3 / Opera Mobile 11.50" }, "windows_95": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (Windows; U; Win 9x 4.90; en-GB; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1", "str": "Other / Windows ME / Firefox 2" }, "solaris": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.6) Gecko/20040503", "str": "Other / Solaris / Other" }, "chrome_os": { "is_bot": false, "is_mobile": false, "is_pc": true, "is_tablet": false, "is_touch_capable": false, "ua_string": "Mozilla/5.0 (X11; CrOS i686 0.12.433) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.77 Safari/534.30", "str": "CrOS" } } python-user-agents-2.0/user_agents/parsers.py000066400000000000000000000175011345235247500215150ustar00rootroot00000000000000from collections import namedtuple from ua_parser import user_agent_parser from .compat import string_types MOBILE_DEVICE_FAMILIES = ( 'iPhone', 'iPod', 'Generic Smartphone', 'Generic Feature Phone', 'PlayStation Vita', 'iOS-Device' ) PC_OS_FAMILIES = ( 'Windows 95', 'Windows 98', 'Solaris', ) MOBILE_OS_FAMILIES = ( 'Windows Phone', 'Windows Phone OS', # Earlier versions of ua-parser returns Windows Phone OS 'Symbian OS', 'Bada', 'Windows CE', 'Windows Mobile', 'Maemo', ) MOBILE_BROWSER_FAMILIES = ( 'Opera Mobile', 'Opera Mini', ) TABLET_DEVICE_FAMILIES = ( 'iPad', 'BlackBerry Playbook', 'Blackberry Playbook', # Earlier versions of ua-parser returns "Blackberry" instead of "BlackBerry" 'Kindle', 'Kindle Fire', 'Kindle Fire HD', 'Galaxy Tab', 'Xoom', 'Dell Streak', ) TOUCH_CAPABLE_OS_FAMILIES = ( 'iOS', 'Android', 'Windows Phone', 'Windows CE', 'Windows Mobile', 'Firefox OS', 'MeeGo', ) TOUCH_CAPABLE_DEVICE_FAMILIES = ( 'BlackBerry Playbook', 'Blackberry Playbook', 'Kindle Fire', ) EMAIL_PROGRAM_FAMILIES = set(( 'Outlook', 'Windows Live Mail', 'AirMail', 'Apple Mail', 'Outlook', 'Thunderbird', 'Lightning', 'ThunderBrowse', 'Windows Live Mail', 'The Bat!', 'Lotus Notes', 'IBM Notes', 'Barca', 'MailBar', 'kmail2', 'YahooMobileMail' )) def verify_attribute(attribute): if isinstance(attribute, string_types) and attribute.isdigit(): return int(attribute) return attribute def parse_version(major=None, minor=None, patch=None, patch_minor=None): # Returns version number tuple, attributes will be integer if they're numbers major = verify_attribute(major) minor = verify_attribute(minor) patch = verify_attribute(patch) patch_minor = verify_attribute(patch_minor) return tuple( filter(lambda x: x is not None, (major, minor, patch, patch_minor)) ) Browser = namedtuple('Browser', ['family', 'version', 'version_string']) def parse_browser(family, major=None, minor=None, patch=None, patch_minor=None): # Returns a browser object version = parse_version(major, minor, patch) version_string = '.'.join([str(v) for v in version]) return Browser(family, version, version_string) OperatingSystem = namedtuple('OperatingSystem', ['family', 'version', 'version_string']) def parse_operating_system(family, major=None, minor=None, patch=None, patch_minor=None): version = parse_version(major, minor, patch) version_string = '.'.join([str(v) for v in version]) return OperatingSystem(family, version, version_string) Device = namedtuple('Device', ['family', 'brand', 'model']) def parse_device(family, brand, model): return Device(family, brand, model) class UserAgent(object): def __init__(self, user_agent_string): ua_dict = user_agent_parser.Parse(user_agent_string) self.ua_string = user_agent_string self.os = parse_operating_system(**ua_dict['os']) self.browser = parse_browser(**ua_dict['user_agent']) self.device = parse_device(**ua_dict['device']) def __str__(self): device = self.is_pc and "PC" or self.device.family os = ("%s %s" % (self.os.family, self.os.version_string)).strip() browser = ("%s %s" % (self.browser.family, self.browser.version_string)).strip() return " / ".join([device, os, browser]) def __unicode__(self): return unicode(str(self)) def _is_android_tablet(self): # Newer Android tablets don't have "Mobile" in their user agent string, # older ones like Galaxy Tab still have "Mobile" though they're not if ('Mobile Safari' not in self.ua_string and self.browser.family != "Firefox Mobile"): return True return False def _is_blackberry_touch_capable_device(self): # A helper to determine whether a BB phone has touch capabilities # Blackberry Bold Touch series begins with 99XX if 'Blackberry 99' in self.device.family: return True if 'Blackberry 95' in self.device.family: # BB Storm devices return True if 'Blackberry 95' in self.device.family: # BB Torch devices return True return False @property def is_tablet(self): if self.device.family in TABLET_DEVICE_FAMILIES: return True if (self.os.family == 'Android' and self._is_android_tablet()): return True if self.os.family == 'Windows' and self.os.version_string.startswith('RT'): return True if self.os.family == 'Firefox OS' and 'Mobile' not in self.browser.family: return True return False @property def is_mobile(self): # First check for mobile device and mobile browser families if self.device.family in MOBILE_DEVICE_FAMILIES: return True if self.browser.family in MOBILE_BROWSER_FAMILIES: return True # Device is considered Mobile OS is Android and not tablet # This is not fool proof but would have to suffice for now if ((self.os.family == 'Android' or self.os.family == 'Firefox OS') and not self.is_tablet): return True if self.os.family == 'BlackBerry OS' and self.device.family != 'Blackberry Playbook': return True if self.os.family in MOBILE_OS_FAMILIES: return True # TODO: remove after https://github.com/tobie/ua-parser/issues/126 is closed if 'J2ME' in self.ua_string or 'MIDP' in self.ua_string: return True # This is here mainly to detect Google's Mobile Spider if 'iPhone;' in self.ua_string: return True if 'Googlebot-Mobile' in self.ua_string: return True # Mobile Spiders should be identified as mobile if self.device.family == 'Spider' and 'Mobile' in self.browser.family: return True # Nokia mobile if 'NokiaBrowser' in self.ua_string and 'Mobile' in self.ua_string: return True return False @property def is_touch_capable(self): # TODO: detect touch capable Nokia devices if self.os.family in TOUCH_CAPABLE_OS_FAMILIES: return True if self.device.family in TOUCH_CAPABLE_DEVICE_FAMILIES: return True if self.os.family == 'Windows': if self.os.version_string.startswith('RT'): return True if self.os.version_string.startswith('8') and 'Touch' in self.ua_string: return True if 'BlackBerry' in self.os.family and self._is_blackberry_touch_capable_device(): return True return False @property def is_pc(self): # Returns True for "PC" devices (Windows, Mac and Linux) if 'Windows NT' in self.ua_string or self.os.family in PC_OS_FAMILIES or \ self.os.family == 'Windows' and self.os.version_string == 'ME': return True # TODO: remove after https://github.com/tobie/ua-parser/issues/127 is closed if self.os.family == 'Mac OS X' and 'Silk' not in self.ua_string: return True # Maemo has 'Linux' and 'X11' in UA, but it is not for PC if 'Maemo' in self.ua_string: return False if 'Chrome OS' in self.os.family: return True if 'Linux' in self.ua_string and 'X11' in self.ua_string: return True return False @property def is_bot(self): return True if self.device.family == 'Spider' else False @property def is_email_client(self): if self.browser.family in EMAIL_PROGRAM_FAMILIES: return True return False def parse(user_agent_string): return UserAgent(user_agent_string) python-user-agents-2.0/user_agents/tests.py000066400000000000000000000345441345235247500212060ustar00rootroot00000000000000import json import os import unittest from ua_parser import user_agent_parser from . import compat from .parsers import parse iphone_ua_string = 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3' ipad_ua_string = 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10' galaxy_tab_ua_string = 'Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' galaxy_s3_ua_string = 'Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' kindle_fire_ua_string = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true' playbook_ua_string = 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.0.1; en-US) AppleWebKit/535.8+ (KHTML, like Gecko) Version/7.2.0.1 Safari/535.8+' nexus_7_ua_string = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19' windows_phone_ua_string = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; SGH-i917)' blackberry_torch_ua_string = 'Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; zh-TW) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.448 Mobile Safari/534.8+' blackberry_bold_ua_string = 'BlackBerry9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/331 UNTRUSTED/1.0 3gpp-gba' blackberry_bold_touch_ua_string = 'Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.241 Mobile Safari/534.11+' windows_rt_ua_string = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0)' j2me_opera_ua_string = 'Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (J2ME/22.478; U; en) Presto/2.5.25 Version/10.54' ie_ua_string = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)' ie_touch_ua_string = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Touch)' mac_safari_ua_string = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2' windows_ie_ua_string = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' ubuntu_firefox_ua_string = 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:15.0) Gecko/20100101 Firefox/15.0.1' google_bot_ua_string = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' nokia_n97_ua_string = 'Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/12.0.024; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.12344' android_firefox_aurora_ua_string = 'Mozilla/5.0 (Android; Mobile; rv:27.0) Gecko/27.0 Firefox/27.0' thunderbird_ua_string = 'Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 Lightning/4.0.2' outlook_usa_string = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; Microsoft Outlook 15.0.4420)' chromebook_ua_string = 'Mozilla/5.0 (X11; CrOS i686 0.12.433) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.77 Safari/534.30' iphone_ua = parse(iphone_ua_string) ipad_ua = parse(ipad_ua_string) galaxy_tab = parse(galaxy_tab_ua_string) galaxy_s3_ua = parse(galaxy_s3_ua_string) kindle_fire_ua = parse(kindle_fire_ua_string) playbook_ua = parse(playbook_ua_string) nexus_7_ua = parse(nexus_7_ua_string) windows_phone_ua = parse(windows_phone_ua_string) windows_rt_ua = parse(windows_rt_ua_string) blackberry_torch_ua = parse(blackberry_torch_ua_string) blackberry_bold_ua = parse(blackberry_bold_ua_string) blackberry_bold_touch_ua = parse(blackberry_bold_touch_ua_string) j2me_opera_ua = parse(j2me_opera_ua_string) ie_ua = parse(ie_ua_string) ie_touch_ua = parse(ie_touch_ua_string) mac_safari_ua = parse(mac_safari_ua_string) windows_ie_ua = parse(windows_ie_ua_string) ubuntu_firefox_ua = parse(ubuntu_firefox_ua_string) google_bot_ua = parse(google_bot_ua_string) nokia_n97_ua = parse(nokia_n97_ua_string) android_firefox_aurora_ua = parse(android_firefox_aurora_ua_string) thunderbird_ua = parse(thunderbird_ua_string) outlook_ua = parse(outlook_usa_string) chromebook_ua = parse(chromebook_ua_string) class UserAgentsTest(unittest.TestCase): def test_user_agent_object_assignments(self): ua_dict = user_agent_parser.Parse(devices['iphone']['ua_string']) iphone_ua = devices['iphone']['user_agent'] # Ensure browser attributes are assigned correctly self.assertEqual(iphone_ua.browser.family, ua_dict['user_agent']['family']) self.assertEqual( iphone_ua.browser.version, (int(ua_dict['user_agent']['major']), int(ua_dict['user_agent']['minor'])) ) # Ensure os attributes are assigned correctly self.assertEqual(iphone_ua.os.family, ua_dict['os']['family']) self.assertEqual( iphone_ua.os.version, (int(ua_dict['os']['major']), int(ua_dict['os']['minor'])) ) # Ensure device attributes are assigned correctly self.assertEqual(iphone_ua.device.family, ua_dict['device']['family']) def test_is_tablet_property(self): self.assertFalse(iphone_ua.is_tablet) self.assertFalse(galaxy_s3_ua.is_tablet) self.assertFalse(blackberry_torch_ua.is_tablet) self.assertFalse(blackberry_bold_ua.is_tablet) self.assertFalse(windows_phone_ua.is_tablet) self.assertFalse(ie_ua.is_tablet) self.assertFalse(ie_touch_ua.is_tablet) self.assertFalse(mac_safari_ua.is_tablet) self.assertFalse(windows_ie_ua.is_tablet) self.assertFalse(ubuntu_firefox_ua.is_tablet) self.assertFalse(j2me_opera_ua.is_tablet) self.assertFalse(google_bot_ua.is_tablet) self.assertFalse(nokia_n97_ua.is_tablet) self.assertTrue(windows_rt_ua.is_tablet) self.assertTrue(ipad_ua.is_tablet) self.assertTrue(playbook_ua.is_tablet) self.assertTrue(kindle_fire_ua.is_tablet) self.assertTrue(nexus_7_ua.is_tablet) self.assertFalse(android_firefox_aurora_ua.is_tablet) def test_is_mobile_property(self): self.assertTrue(iphone_ua.is_mobile) self.assertTrue(galaxy_s3_ua.is_mobile) self.assertTrue(blackberry_torch_ua.is_mobile) self.assertTrue(blackberry_bold_ua.is_mobile) self.assertTrue(windows_phone_ua.is_mobile) self.assertTrue(j2me_opera_ua.is_mobile) self.assertTrue(nokia_n97_ua.is_mobile) self.assertFalse(windows_rt_ua.is_mobile) self.assertFalse(ipad_ua.is_mobile) self.assertFalse(playbook_ua.is_mobile) self.assertFalse(kindle_fire_ua.is_mobile) self.assertFalse(nexus_7_ua.is_mobile) self.assertFalse(ie_ua.is_mobile) self.assertFalse(ie_touch_ua.is_mobile) self.assertFalse(mac_safari_ua.is_mobile) self.assertFalse(windows_ie_ua.is_mobile) self.assertFalse(ubuntu_firefox_ua.is_mobile) self.assertFalse(google_bot_ua.is_mobile) self.assertTrue(android_firefox_aurora_ua.is_mobile) def test_is_touch_property(self): self.assertTrue(iphone_ua.is_touch_capable) self.assertTrue(galaxy_s3_ua.is_touch_capable) self.assertTrue(ipad_ua.is_touch_capable) self.assertTrue(playbook_ua.is_touch_capable) self.assertTrue(kindle_fire_ua.is_touch_capable) self.assertTrue(nexus_7_ua.is_touch_capable) self.assertTrue(windows_phone_ua.is_touch_capable) self.assertTrue(ie_touch_ua.is_touch_capable) self.assertTrue(blackberry_bold_touch_ua.is_mobile) self.assertTrue(blackberry_torch_ua.is_mobile) self.assertFalse(j2me_opera_ua.is_touch_capable) self.assertFalse(ie_ua.is_touch_capable) self.assertFalse(blackberry_bold_ua.is_touch_capable) self.assertFalse(mac_safari_ua.is_touch_capable) self.assertFalse(windows_ie_ua.is_touch_capable) self.assertFalse(ubuntu_firefox_ua.is_touch_capable) self.assertFalse(google_bot_ua.is_touch_capable) self.assertFalse(nokia_n97_ua.is_touch_capable) self.assertTrue(android_firefox_aurora_ua.is_touch_capable) def test_is_pc(self): self.assertFalse(iphone_ua.is_pc) self.assertFalse(galaxy_s3_ua.is_pc) self.assertFalse(ipad_ua.is_pc) self.assertFalse(playbook_ua.is_pc) self.assertFalse(kindle_fire_ua.is_pc) self.assertFalse(nexus_7_ua.is_pc) self.assertFalse(windows_phone_ua.is_pc) self.assertFalse(blackberry_bold_touch_ua.is_pc) self.assertFalse(blackberry_torch_ua.is_pc) self.assertFalse(blackberry_bold_ua.is_pc) self.assertFalse(j2me_opera_ua.is_pc) self.assertFalse(google_bot_ua.is_pc) self.assertFalse(nokia_n97_ua.is_pc) self.assertTrue(mac_safari_ua.is_pc) self.assertTrue(windows_ie_ua.is_pc) self.assertTrue(ubuntu_firefox_ua.is_pc) self.assertTrue(ie_touch_ua.is_pc) self.assertTrue(ie_ua.is_pc) self.assertFalse(android_firefox_aurora_ua.is_pc) self.assertTrue(chromebook_ua.is_pc) def test_is_bot(self): self.assertTrue(google_bot_ua.is_bot) self.assertFalse(iphone_ua.is_bot) self.assertFalse(galaxy_s3_ua.is_bot) self.assertFalse(ipad_ua.is_bot) self.assertFalse(playbook_ua.is_bot) self.assertFalse(kindle_fire_ua.is_bot) self.assertFalse(nexus_7_ua.is_bot) self.assertFalse(windows_phone_ua.is_bot) self.assertFalse(blackberry_bold_touch_ua.is_bot) self.assertFalse(blackberry_torch_ua.is_bot) self.assertFalse(blackberry_bold_ua.is_bot) self.assertFalse(j2me_opera_ua.is_bot) self.assertFalse(mac_safari_ua.is_bot) self.assertFalse(windows_ie_ua.is_bot) self.assertFalse(ubuntu_firefox_ua.is_bot) self.assertFalse(ie_touch_ua.is_bot) self.assertFalse(ie_ua.is_bot) self.assertFalse(nokia_n97_ua.is_bot) self.assertFalse(android_firefox_aurora_ua.is_bot) def test_is_email_client(self): self.assertTrue(thunderbird_ua.is_email_client) self.assertTrue(outlook_ua.is_email_client) self.assertFalse(playbook_ua.is_email_client) self.assertFalse(kindle_fire_ua.is_email_client) self.assertFalse(nexus_7_ua.is_email_client) self.assertFalse(windows_phone_ua.is_email_client) self.assertFalse(blackberry_bold_touch_ua.is_email_client) self.assertFalse(blackberry_torch_ua.is_email_client) self.assertFalse(blackberry_bold_ua.is_email_client) self.assertFalse(j2me_opera_ua.is_email_client) self.assertFalse(mac_safari_ua.is_email_client) self.assertFalse(windows_ie_ua.is_email_client) self.assertFalse(ubuntu_firefox_ua.is_email_client) self.assertFalse(ie_touch_ua.is_email_client) self.assertFalse(ie_ua.is_email_client) self.assertFalse(nokia_n97_ua.is_email_client) self.assertFalse(android_firefox_aurora_ua.is_email_client) def test_strings(self): self.assertEqual(str(iphone_ua), "iPhone / iOS 5.1 / Mobile Safari 5.1") self.assertEqual(str(ipad_ua), "iPad / iOS 3.2 / Mobile Safari 4.0.4") self.assertEqual(str(galaxy_tab), "Samsung SCH-I800 / Android 2.2 / Android 2.2") self.assertEqual(str(galaxy_s3_ua), "Samsung GT-I9300 / Android 4.0.4 / Android 4.0.4") self.assertEqual(str(kindle_fire_ua), "Kindle / Android / Amazon Silk 1.1.0-80") self.assertEqual(str(playbook_ua), "BlackBerry Playbook / BlackBerry Tablet OS 2.0.1 / BlackBerry WebKit 2.0.1") self.assertEqual(str(nexus_7_ua), "Asus Nexus 7 / Android 4.1.1 / Chrome 18.0.1025") self.assertEqual(str(windows_phone_ua), "Samsung SGH-i917 / Windows Phone 7.5 / IE Mobile 9.0") self.assertEqual(str(windows_rt_ua), "PC / Windows RT / IE 10.0") self.assertEqual(str(blackberry_torch_ua), "BlackBerry 9800 / BlackBerry OS 6.0.0 / BlackBerry WebKit 6.0.0") self.assertEqual(str(blackberry_bold_ua), "BlackBerry 9700 / BlackBerry OS 5.0.0 / BlackBerry 9700") self.assertEqual(str(blackberry_bold_touch_ua), "BlackBerry 9930 / BlackBerry OS 7.0.0 / BlackBerry WebKit 7.0.0") self.assertEqual(str(j2me_opera_ua), "Generic Feature Phone / Other / Opera Mini 9.80") self.assertEqual(str(ie_ua), "PC / Windows 8 / IE 10.0") self.assertEqual(str(ie_touch_ua), "PC / Windows 8 / IE 10.0") self.assertEqual(str(mac_safari_ua), "PC / Mac OS X 10.6.8 / WebKit Nightly 537.13") self.assertEqual(str(windows_ie_ua), "PC / Windows 7 / IE 9.0") self.assertEqual(str(ubuntu_firefox_ua), "PC / Ubuntu / Firefox 15.0.1") self.assertEqual(str(google_bot_ua), "Spider / Other / Googlebot 2.1") self.assertEqual(str(nokia_n97_ua), "Nokia N97 / Symbian OS 9.4 / Nokia Browser 7.1.12344") self.assertEqual(str(android_firefox_aurora_ua), "Generic Smartphone / Android / Firefox Mobile 27.0") def test_unicode_strings(self): try: # Python 2 unicode_ua_str = unicode(devices['iphone']['user_agent']) self.assertEqual(unicode_ua_str, u"iPhone / iOS 5.1 / Mobile Safari 5.1") self.assertTrue(isinstance(unicode_ua_str, unicode)) except NameError: # Python 3 unicode_ua_str = str(devices['iphone']['user_agent']) self.assertEqual(unicode_ua_str, "iPhone / iOS 5.1 / Mobile Safari 5.1") with open(os.path.join(os.path.dirname(__file__), 'devices.json')) as f: devices = json.load(f) def test_wrapper(items): def test_func(self): attrs = ('is_bot', 'is_mobile', 'is_pc', 'is_tablet', 'is_touch_capable') for attr in attrs: self.assertEqual( getattr(items['user_agent'], attr), items[attr], msg=attr) # Temporarily commenting this out since UserAgent.device # may return different string depending ua-parser version # self.assertEqual(str(items['user_agent']), items['str']) return test_func for device, items in compat.iteritems(devices): items['user_agent'] = parse(items['ua_string']) setattr(UserAgentsTest, 'test_' + device, test_wrapper(items))