class BotifyTestCase(unittest.TestCase): def setUp(self): self.flag = 0 self.bot = Botify(self.is_data_callback, self.clean_data_callback) def is_data_callback(self, value): return False def clean_data_callback(self, value): return value def task1(self): self.flag = 1 def add_task(self): context = Context(self.task1, 0) rule = (-1, ) keywords = ('keyword1', 'keyword2') self.bot.add_task(keywords, context, rule) def add_modifier(self): modifier = 'hello' keywords = ('keyword1', 'keyword2') relative_pos = 1 action = Botify.ACTION_UPDATE_RULE parameter = () self.bot.add_modifier(modifier, keywords, relative_pos, action, parameter) def test_add_task(self): self.add_task() for keyword in ('keyword1', 'keyword2'): self.assertEqual(self.bot._tasks[keyword]['context'], Context(self.task1, 0)) self.assertEqual(self.bot._tasks[keyword]['rule'], (-1, )) def test_add_modifier(self): self.add_modifier() self.assertTrue('hello' in self.bot._modifiers) for keyword in ('keyword1', 'keyword2'): self.assertTrue(keyword in self.bot._modifiers['hello']) value = (Botify.ACTION_UPDATE_RULE, (), 1) self.assertTrue(value in self.bot._modifiers['hello'][keyword]) def test_parse(self): self.add_task() #self.add_modifier() result = self.bot.parse("hello keyword1") self.assertEqual(len(result), 0) self.assertEqual(self.flag, 1)
def test_special_characters(self): user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" botify = Botify( { "HTTP_HOST": "http://example.test", "PATH_INFO": "/Français", "HTTP_USER_AGENT": user_agent, "REMOTE_ADDR": "127.0.0.1", } ) bot = "<ip>%s</ip><ua>%s</ua>" % (botify.ip, botify.user_agent) with nested(patch.object(Botify, "send_data"), patch.object(time, "time")) as (send_data_method, time_method): send_data_method.return_value = True current_time = 1319812537 time_method.return_value = current_time botify.set_code(200) data = botify.record()
def setUp(self): self.flag = 0 self.bot = Botify(self.is_data_callback, self.clean_data_callback)
def test_format_data(self): user_agent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" botify = Botify( { "HTTP_HOST": "http://example.test", "PATH_INFO": "/example", "HTTP_USER_AGENT": user_agent, "REMOTE_ADDR": "127.0.0.1", } ) bot = "<ip>%s</ip><ua>%s</ua>" % (botify.ip, botify.user_agent) with nested(patch.object(Botify, "send_data"), patch.object(time, "time")) as (send_data_method, time_method): send_data_method.return_value = True current_time = 1319812537 time_method.return_value = current_time botify.set_code(200) data = botify.record() self.assertEquals( data, '<?xml version="2.0"?><crawl><load>0</load><code>200</code><time>%(time)s</time><url>%(url)s</url><api_key>%(api_key)s</api_key><bot>%(bot_id)s</bot><id>%(client_id)s</id></crawl>' % { "time": current_time, "url": urllib.quote(botify.get_url()), "api_key": settings.BOTIFY_API_KEY, "client_id": settings.BOTIFY_CLIENT_ID, "bot_id": bot, }, ) botify.add_tracker("example") self.assertRaises(ValueError, botify.add_tracker, ({"test": "test"})) data = botify.record() self.assertEquals( data, '<?xml version="2.0"?><crawl><load>0</load><code>200</code><time>%(time)s</time><url>%(url)s</url><api_key>%(api_key)s</api_key><bot>%(bot_id)s</bot><id>%(client_id)s</id><trackers><t>example</t></trackers></crawl>' % { "time": current_time, "url": urllib.quote(botify.get_url()), "api_key": settings.BOTIFY_API_KEY, "client_id": settings.BOTIFY_CLIENT_ID, "bot_id": bot, }, ) botify.canonical = "http://example.test/home" data = botify.record() self.assertEquals( data, '<?xml version="2.0"?><crawl><load>0</load><code>200</code><time>%(time)s</time><url>%(url)s</url><api_key>%(api_key)s</api_key><bot>%(bot_id)s</bot><id>%(client_id)s</id><trackers><t>example</t></trackers><canonical>http%%3A//example.test/home</canonical></crawl>' % { "time": current_time, "url": urllib.quote(botify.get_url()), "api_key": settings.BOTIFY_API_KEY, "client_id": settings.BOTIFY_CLIENT_ID, "bot_id": bot, }, )
def test_is_crawlable(self): for user_agent in USER_AGENTS: is_crawlable = Botify.is_crawlable(None, user_agent) self.assertTrue(bool(is_crawlable)) self.assertFalse(Botify.is_crawlable("http://example.test", USER_AGENTS[0][0]))
class NLCalculator: """Natural Language Mathematical Calculator. This class can be used to parse mathematical statements in natural language. Attributes ---------- strict_mode_enabled """ def __init__(self): self._parser = Botify(is_token_data_callback=is_numeric, clean_data_callback=convert_to_numeric) self._init_tasks() self._init_modifiers() @property def strict_mode_enabled(self): """Whether strict mode is enabled for the calculator instance.""" return self._parser.strict_mode_enabled @strict_mode_enabled.setter def strict_mode_enabled(self, value): self._parser.strict_mode_enabled = value def _init_tasks(self): # Addition self._parser.add_task(keywords=('sum', 'summation', 'add', 'addition', 'total'), context=CONTEXT_SUM, rule=(1, 2)) self._parser.add_task(keywords=('added',), context=CONTEXT_SUM, rule=(-2, -1)) self._parser.add_task(keywords=('plus', '+'), context=CONTEXT_SUM, rule=(-1, 1)) # Subtraction self._parser.add_task(keywords=('difference', 'subtract', 'subtraction'), context=CONTEXT_DIFF, rule=(1, 2)) self._parser.add_task(keywords=('subtracted',), context=CONTEXT_DIFF, rule=(-2, -1)) self._parser.add_task(keywords=('minus', '-'), context=CONTEXT_DIFF, rule=(-1, 1)) # Multiplication self._parser.add_task(keywords=('product', 'multiply', 'multiplication'), context=CONTEXT_MUL, rule=(1, 2)) self._parser.add_task(keywords=('into', 'times', '*'), context=CONTEXT_MUL, rule=(-1, 1)) self._parser.add_task(keywords=('multiplied',), context=CONTEXT_MUL, rule=(-2, -1)) # Division self._parser.add_task(keywords=('divide', 'division'), context=CONTEXT_DIV, rule=(1, 2)) self._parser.add_task(keywords=('divided', 'over', '/'), context=CONTEXT_DIV, rule=(-1, 1)) # Factorial self._parser.add_task(keywords=('factorial',), context=CONTEXT_FACT, rule=(-1,)) # Exponent self._parser.add_task(keywords=('power', '^', '**'), context=CONTEXT_POW, rule=(-1, 1)) # Square self._parser.add_task(keywords=('square', 'squared'), context=CONTEXT_SQR, rule=(-1,)) # Cube self._parser.add_task(keywords=('cube', 'cubed'), context=CONTEXT_CUBE, rule=(-1,)) # Root self._parser.add_task(keywords=('root',), context=CONTEXT_SQRT, rule=(1,)) # Special Constants self._parser.add_task(keywords=('pi',), # pi context=CONTEXT_PI, rule=()) self._parser.add_task(keywords=('e',), # e context=CONTEXT_E, rule=()) def _init_modifiers(self): self._parser.add_modifier(modifier='to', keywords=('added', 'multiplied'), relative_pos=-1, action=Botify.ACTION_UPDATE_RULE, parameter=(-1, 1)) self._parser.add_modifier(modifier='with', keywords=('added', 'multiplied'), relative_pos=-1, action=Botify.ACTION_UPDATE_RULE, parameter=(-1, 1)) self._parser.add_modifier(modifier='of', keywords=('factorial', 'square', 'cube'), relative_pos=-1, action=Botify.ACTION_UPDATE_RULE, parameter=(1,)) self._parser.add_modifier(modifier='by', keywords=('divide', 'divided', 'multiply', 'multiplied'), relative_pos=-1, action=Botify.ACTION_UPDATE_RULE, parameter=(-1, 1)) self._parser.add_modifier(modifier='from', keywords=('subtract',), relative_pos=-2, action=Botify.ACTION_UPDATE_RULE, parameter=(2, 1)) self._parser.add_modifier(modifier='from', keywords=('subtracted',), relative_pos=-1, action=Botify.ACTION_UPDATE_RULE, parameter=(1, -1)) self._parser.add_modifier(modifier='root', keywords=('square', 'cube'), relative_pos=-2, action=Botify.ACTION_UPDATE_RULE, parameter=(1,)) self._parser.add_modifier(modifier='root', keywords=('square',), relative_pos=-2, action=Botify.ACTION_UPDATE_CONTEXT, parameter=CONTEXT_SQRT) self._parser.add_modifier(modifier='root', keywords=('cube',), relative_pos=-2, action=Botify.ACTION_UPDATE_CONTEXT, parameter=CONTEXT_CUBE_ROOT) self._parser.add_modifier(modifier='root', keywords=('square', 'cube'), relative_pos=-2, action=Botify.ACTION_DELETE, parameter=1) def calculate(self, text): """Calculate the output after parsing input. Parameters ---------- text : str A string value which should be parsed Returns ------- int or float: The final result Raises ------ ValueError If the text cannot be succesfully parsed and evaluated to get a result. """ res = self._parser.parse(text2int(text)) if len(res) == 1: return res[0] else: raise ValueError("Unable to Parse")
def __init__(self): self._parser = Botify(is_token_data_callback=is_numeric, clean_data_callback=convert_to_numeric) self._init_tasks() self._init_modifiers()