Skip to content

Commit f0fc3f4

Browse files
committed
Use ua hash for smaller cache keys
1 parent af33b18 commit f0fc3f4

File tree

3 files changed

+25
-11
lines changed

3 files changed

+25
-11
lines changed

device_detector/device_detector.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
NameVersionExtractor,
3131
WholeNameExtractor,
3232
)
33-
from .settings import DDCache, WORTHLESS_UA_TYPES
33+
from .settings import DDCache, WORTHLESS_UA_TYPES, ua_hash
3434
from .yaml_loader import RegexLoader
3535

3636
MAC_iOS = {
@@ -73,7 +73,7 @@ def __init__(self, user_agent, skip_bot_detection=False):
7373

7474
# Holds the useragent that should be parsed
7575
self.user_agent = user_agent
76-
76+
self.ua_hash = ua_hash(self.user_agent)
7777
self.os = None
7878
self.client = None
7979
self.device = None
@@ -98,14 +98,15 @@ def class_name(self) -> str:
9898
return self.__class__.__name__
9999

100100
def get_parse_cache(self):
101-
if self.user_agent not in DDCache['user_agents']:
101+
if self.ua_hash not in DDCache['user_agents']:
102102
return None
103-
return DDCache['user_agents'][self.user_agent].get('parsed', None)
103+
return DDCache['user_agents'][self.ua_hash].get('parsed', None)
104104

105105
def set_parse_cache(self):
106-
if self.user_agent not in DDCache['user_agents']:
107-
DDCache['user_agents'][self.user_agent] = {}
108-
DDCache['user_agents'][self.user_agent]['parsed'] = self
106+
try:
107+
DDCache['user_agents'][self.ua_hash]['parsed'] = self
108+
except KeyError:
109+
DDCache['user_agents'][self.ua_hash] = {'parsed': self}
109110
return self
110111

111112
# -----------------------------------------------------------------------------

device_detector/parser/parser.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from ..settings import (
77
DDCache,
8+
ua_hash,
89
)
910
from .extractors import (
1011
NameExtractor,
@@ -30,13 +31,14 @@ def __init__(self, ua):
3031
else:
3132
self.user_agent = ua
3233

34+
self.ua_hash = ua_hash(self.user_agent)
3335
self.ua_data = {}
3436
self.app_name = ''
3537
self.app_name_no_punctuation = ''
3638
self.matched_regex = None
3739
self.known = False
38-
if self.user_agent not in DDCache['user_agents']:
39-
DDCache['user_agents'][self.user_agent] = {}
40+
if self.ua_hash not in DDCache['user_agents']:
41+
DDCache['user_agents'][self.ua_hash] = {}
4042

4143
@property
4244
def cache_name(self) -> str:
@@ -50,10 +52,10 @@ def dtype(self) -> str:
5052
return self.cache_name.lower()
5153

5254
def get_from_cache(self) -> dict:
53-
return DDCache['user_agents'][self.user_agent].get(self.cache_name, None)
55+
return DDCache['user_agents'][self.ua_hash].get(self.cache_name, None)
5456

5557
def add_to_cache(self) -> dict:
56-
DDCache['user_agents'][self.user_agent][self.cache_name] = self.ua_data
58+
DDCache['user_agents'][self.ua_hash][self.cache_name] = self.ua_data
5759
return self.ua_data
5860

5961
def _check_regex(self, regex):

device_detector/settings.py

+11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
from collections import OrderedDict
22
from copy import deepcopy
3+
from hashlib import md5
34
import os
45

56

7+
def ua_hash(user_agent):
8+
"""
9+
Return short hash of User Agent string for
10+
memory-efficient cache key.
11+
"""
12+
return md5(user_agent.encode('utf-8')).hexdigest()[:9]
13+
14+
615
# interpolate regex with anchors so
716
# iPhone / Tiphone are matched correctly
817
BOUNDED_REGEX = r'(?:^|[^A-Z0-9_\-])(?:{})'
@@ -85,4 +94,6 @@ def clear(self):
8594
'LRUDict',
8695
'ROOT',
8796
'WORTHLESS_UA_TYPES',
97+
'ua_hash',
8898
)
99+

0 commit comments

Comments
 (0)