[web2py] Re: Bug in user_agent_parser.py

2011-08-23 Thread Ross Peoples
I am looking in to this. Thank you for taking the time to provide the needed 
information. I'll let you know what I find.

[web2py] Re: Bug in user_agent_parser.py

2011-08-23 Thread Angelo Compagnucci
OK,

I think I found the problem.

It's located in these two functions.

def detect(self, agent, result):
if agent and self.checkWords(agent):
result[self.info_type] = Storage(name=self.name)
version = self.getVersion(agent)
if version:
result[self.info_type].version = version
return True
return False

def checkWords(self, agent):
for w in self.skip_if_found:
if w in agent:
return False
if self.look_for:
return True
return False


Detect should return true only if agent is not empty and
checkWords(agent) returns true.
The method checkWords(agent) shows a problem, the method return true
when the variable self.look_for exist, and not check if the words in
the useragent really match the ones into look_for variable.

It should be something like this:

 def checkWords(self, agent):
for w in self.skip_if_found:
if w in agent:
return False
if self.look_for in agent:   
  return True
return False

Whith this fix it works for me!

Bye!


2011/8/23 Angelo Compagnucci angelo.compagnu...@gmail.com:
 Hi list,

 I'm using user_agent_parser.py from the latest stable version.

 I have this user agent:

 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0

 I cannot understand why the code looks for the Opera user agent (I
 have not read carefully the code) but it fails with this error:

  File 
 C:\Users\Collaboratore\Documents\HotSpot\MANAGER\web2py\gluon\contrib\user_agent_parser.py,
 line 134, in getVersion
    return agent.split(self.look_for)[1][1:].split(' ')[0]
 IndexError: list index out of range

 Clearly the code has a problem:

 class Opera(Browser):
    look_for = Opera
    def getVersion(self, agent):
                return agent.split(self.look_for)[1][1:].split(' ')[0]

 This agent.split(self.look_for)[1] raise an exception when look_for
 returns nothing (as in my case).

 I think it should be a sort of checking prior calling getVersion, or
 call getVersion only when the useragent is really Opera!

 I'll look forward into the code and I'll try to look for a solution.

 Thank you!



[web2py] Re: Bug in user_agent_parser.py

2011-08-23 Thread Ross Peoples
I just submitted a patch for inclusion into the trunk. It includes the 
change you mention, and includes a few other fixes, including a fix to the 
simple_detect() method that would throw a different set of IndexErrors.

I have attached it here as well so that you can test while waiting for 
inclusion into the trunk. Let me know is this is working for you. Thanks.


Extract client information from http user agent
The module does not try to detect all capabilities of browser in current form (it can easily be extended though).
Aim is
* fast
* very easy to extend
* reliable enough for practical purposes
* and assist python web apps to detect clients.

Taken from http://pypi.python.org/pypi/httpagentparser (MIT license)
Modified my Ross Peoples for web2py to better support iPhone and iPad.

import sys
from storage import Storage

class DetectorsHub(dict):
_known_types = ['os', 'dist', 'flavor', 'browser']

def __init__(self, *args, **kw):
dict.__init__(self, *args, **kw)
for typ in self._known_types:
self.setdefault(typ, [])
self.registerDetectors()

def register(self, detector):
if detector.info_type not in self._known_types:
self[detector.info_type] = [detector]
self._known_types.insert(detector.order, detector.info_type)
else:
self[detector.info_type].append(detector)

def reorderByPrefs(self, detectors, prefs):
if prefs is None:
return []
elif prefs == []:
return detectors
else:
prefs.insert(0, '')
def key_name(d):
return d.name in prefs and prefs.index(d.name) or sys.maxint
return sorted(detectors, key=key_name)

def __iter__(self):
return iter(self._known_types)

def registerDetectors(self):
detectors = [v() for v in globals().values() \
 if DetectorBase in getattr(v, '__mro__', [])]
for d in detectors:
if d.can_register:
self.register(d)


class DetectorBase(object):
name =  # to perform match in DetectorsHub object
info_type = override me
result_key = override me
order = 10 # 0 is highest
look_for = string to look for
skip_if_found = [] # strings if present stop processin
can_register = False
prefs = Storage() # dict(info_type = [name1, name2], ..)
version_splitters = [/,  ]
_suggested_detectors = None

def __init__(self):
if not self.name:
self.name = self.__class__.__name__
self.can_register = (self.__class__.__dict__.get('can_register', True))

def detect(self, agent, result):
if agent and self.checkWords(agent):
result[self.info_type] = Storage(name=self.name)
version = self.getVersion(agent)
if version:
result[self.info_type].version = version
return True
return False

def checkWords(self, agent):
for w in self.skip_if_found:
if w in agent:
return False
if self.look_for in agent:
return True
return False

def getVersion(self, agent):
# - version string /None
vs = self.version_splitters
return agent.split(self.look_for + vs[0])[-1].split(vs[1])[0].strip()


class OS(DetectorBase):
info_type = os
can_register = False
version_splitters = [;,  ]


class Dist(DetectorBase):
info_type = dist
can_register = False


class Flavor(DetectorBase):
info_type = flavor
can_register = False


class Browser(DetectorBase):
info_type = browser
can_register = False


class Macintosh(OS):
look_for = 'Macintosh'
prefs = Storage(dist=None)
def getVersion(self, agent):
pass


class Firefox(Browser):
look_for = Firefox


class Konqueror(Browser):
look_for = Konqueror
version_splitters = [/, ;]


class Opera(Browser):
look_for = Opera
def getVersion(self, agent):
return agent.split(self.look_for)[1][1:].split(' ')[0]

class Netscape(Browser):
look_for = Netscape

class MSIE(Browser):
look_for = MSIE
skip_if_found = [Opera]
name = Microsoft Internet Explorer
version_splitters = [ , ;]


class Galeon(Browser):
look_for = Galeon


class Safari(Browser):
look_for = Safari

def checkWords(self, agent):
unless_list = [Chrome, OmniWeb]
if self.look_for in agent:
for word in unless_list:
if word in agent:
return False
return True

def getVersion(self, agent):
if Version/ in agent:
return agent.split('Version/')[-1].split(' ')[0].strip()
else:
# Mobile Safari
return agent.split('Safari ')[-1].split(' ')[0].strip()


class Linux(OS):
look_for = 'Linux'
prefs = Storage(browser=[Firefox],
dist=[Ubuntu, Android], 

Re: [web2py] Re: Bug in user_agent_parser.py

2011-08-23 Thread Angelo Compagnucci
Thank you!

It works like a charm!

I'll keep you informed if I find anything!

Thank you!

2011/8/23 Ross Peoples ross.peop...@gmail.com:
 I just submitted a patch for inclusion into the trunk. It includes the
 change you mention, and includes a few other fixes, including a fix to the
 simple_detect() method that would throw a different set of IndexErrors.
 I have attached it here as well so that you can test while waiting for
 inclusion into the trunk. Let me know is this is working for you. Thanks.