NDOJ/judge/utils/caniuse.py

149 lines
4.2 KiB
Python
Raw Normal View History

2020-01-21 06:35:58 +00:00
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