import requests from ua_parser import user_agent_parser _SUPPORT_DATA = requests.get('https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json').json()['data'] SUPPORT = 'y' PARTIAL_SUPPORT = 'a' UNSUPPORTED = 'n' POLYFILL = 'p' UNKNOWN = 'u' PREFIX = 'x' DISABLED = 'd' def safe_int(string): try: return int(string) except (ValueError, TypeError): return 0 class BrowserFamily(object): def __init__(self, data): self._data = data self._ranges = ranges = [] self._versions = versions = {} max_version = () max_support = UNKNOWN for version, support in data.items(): if version == 'all': self.max_support = support elif '-' in version: start, end = version.split('-') start = tuple(map(int, start.split('.'))) end = tuple(map(int, end.split('.'))) + (1e3000,) ranges.append((start, end, support)) if end > max_version: max_version = end max_support = support else: try: version = tuple(map(int, version.split('.'))) except ValueError: pass else: if version > max_version: max_version = version max_support = support versions[version] = support self.max_version = max_version self.max_support = max_support def check(self, major, minor, patch): int_major, int_minor, int_patch = map(safe_int, (major, minor, patch)) version = (int_major, int_minor, int_patch) if version > self.max_version: return self.max_support for key in ((int_major, int_minor, int_patch), (int_major, int_minor), (int_major,), major): try: return self._versions[key] except KeyError: pass for start, end, support in self._ranges: if start <= version < end: return support return UNKNOWN class Feat(object): def __init__(self, data): self._data = data self._family = {name: BrowserFamily(data) for name, data in data['stats'].items()} def __getitem__(self, item): return self._family[item] class Database(object): def __init__(self, data): self._data = data self._feats = {feat: Feat(data) for feat, data in data.items()} def __getitem__(self, item): return self._feats[item] database = Database(_SUPPORT_DATA) class CanIUse(object): def __init__(self, ua): self._agent = user_agent_parser.Parse(ua) os_family = self._agent['os']['family'] browser_family = self._agent['user_agent']['family'] family = None if os_family == 'Android': if 'Firefox' in browser_family: family = 'and_ff' elif 'Chrome' in browser_family: family = 'and_chr' elif 'Android' in browser_family: family = 'android' else: if 'Edge' in browser_family: family = 'edge' elif 'Firefox' in browser_family: family = 'firefox' elif 'Chrome' in browser_family: family = 'chrome' elif 'IE' in browser_family: family = 'ie' elif 'Opera' in browser_family: family = 'opera' elif 'Safari' in browser_family: family = 'safari' self._family = family def _check_feat(self, feat): if not self._family: return UNKNOWN try: stats = feat[self._family] except KeyError: return UNKNOWN else: ua = self._agent['user_agent'] return stats.check(ua['major'], ua['minor'], ua['patch'])[0] def __getattr__(self, attr): try: feat = database[attr.replace('_', '-')] except KeyError: raise AttributeError(attr) else: result = self._check_feat(feat) setattr(self, attr, result) return result