Doctests for the List class
List and ListRef element classes
Basic usage
Setup test tooling:
>>> from dragonfly import *
>>> from dragonfly.test import ElementTester
>>> list_fruit = List("list_fruit")
>>> element = Sequence([Literal("item"), ListRef("list_fruit_ref", list_fruit)])
>>> tester_fruit = ElementTester(element)
>>> # Explicitly load tester grammar because lists can only be updated
>>> # for loaded grammars.
>>> tester_fruit.load()
Empty lists cannot be recognized:
>>> tester_fruit.recognize("item")
RecognitionFailure
>>> tester_fruit.recognize("item apple")
RecognitionFailure
A list update is automatically available for recognition without reloading the grammar:
>>> tester_fruit.recognize("item apple")
RecognitionFailure
>>> list_fruit.append("apple")
>>> list_fruit
['apple']
>>> tester_fruit.recognize("item apple")
[u'item', u'apple']
>>> tester_fruit.recognize("item banana")
RecognitionFailure
>>> list_fruit.append("banana")
>>> list_fruit
['apple', 'banana']
>>> tester_fruit.recognize("item apple")
[u'item', u'apple']
>>> tester_fruit.recognize("item banana")
[u'item', u'banana']
>>> tester_fruit.recognize("item apple banana")
RecognitionFailure
>>> list_fruit.remove("apple")
>>> list_fruit
['banana']
>>> tester_fruit.recognize("item apple")
RecognitionFailure
>>> tester_fruit.recognize("item banana")
[u'item', u'banana']
Lists can contain the same value multiple times, although that does not affect recognition:
>>> list_fruit.append("banana")
>>> list_fruit
['banana', 'banana']
>>> tester_fruit.recognize("item banana")
[u'item', u'banana']
>>> tester_fruit.recognize("item banana banana")
RecognitionFailure
Tear down test tooling:
>>> # Explicitly unload tester grammar.
>>> tester_fruit.unload()
Multiple lists
Setup test tooling:
>>> list_meat = List("list_meat")
>>> list_veg = List("list_veg")
>>> element = Sequence([Literal("food"),
... ListRef("list_meat_ref", list_meat),
... ListRef("list_veg_ref", list_veg)])
>>> tester_meat_veg = ElementTester(element)
>>> # Explicitly load tester grammar because lists can only be updated
>>> # for loaded grammars.
>>> tester_meat_veg.load()
Multiple lists can be combined within a single rule:
>>> list_meat.append("steak")
>>> tester_meat_veg.recognize("food steak")
RecognitionFailure
>>> list_veg.append("carrot")
>>> tester_meat_veg.recognize("food steak carrot")
[u'food', u'steak', u'carrot']
>>> list_meat.append("hamburger")
>>> tester_meat_veg.recognize("food hamburger carrot")
[u'food', u'hamburger', u'carrot']
Tear down test tooling:
>>> # Explicitly unload tester grammar.
>>> tester_meat_veg.unload()
A single list can be present multiple times within a rule:
>>> element = Sequence([Literal("carnivore"),
... ListRef("list_meat_ref1", list_meat),
... ListRef("list_meat_ref2", list_meat)])
>>> tester_carnivore = ElementTester(element)
>>> # Explicitly load tester grammar because lists can only be updated
>>> # for loaded grammars.
>>> tester_carnivore.load()
>>> tester_carnivore.recognize("carnivore steak")
RecognitionFailure
>>> tester_carnivore.recognize("carnivore hamburger steak")
[u'carnivore', u'hamburger', u'steak']
>>> tester_carnivore.recognize("carnivore steak hamburger")
[u'carnivore', u'steak', u'hamburger']
>>> tester_carnivore.recognize("carnivore steak steak")
[u'carnivore', u'steak', u'steak']
>>> list_meat.remove("steak")
>>> tester_carnivore.recognize("carnivore steak hamburger")
RecognitionFailure
>>> tester_carnivore.recognize("carnivore hamburger hamburger")
[u'carnivore', u'hamburger', u'hamburger']
Tear down test tooling:
>>> # Explicitly unload tester grammar.
>>> tester_carnivore.unload()
Unique list names
The names of lists must be unique within a grammar:
>>> list_fruit1 = List("list_fruit")
>>> list_fruit2 = List("list_fruit")
>>> element = Sequence([Literal("fruit"),
... ListRef("list_fruit1_ref", list_fruit1),
... ListRef("list_fruit2_ref", list_fruit2)])
>>> tester_fruit = ElementTester(element)
>>> # Explicitly load tester grammar because lists can only be updated
>>> # for loaded grammars.
>>> tester_fruit.load()
Traceback (most recent call last):
...
GrammarError: Two lists with the same name 'list_fruit' not allowed.
List add/remove restrictions
Setup test tooling:
>>> list_fruit = List("list_fruit", ["apple", "banana"])
>>> element = Sequence([Literal("item"), ListRef("list_fruit_ref", list_fruit)])
>>> tester_fruit = ElementTester(element)
>>> # Explicitly load tester grammar because lists can only be updated
>>> # for loaded grammars.
>>> tester_fruit.load()
Lists cannot be added while the grammar is loaded:
>>> list_other = List("list_other", ["other"])
>>> tester_fruit.add_list(list_other) # Fails.
Traceback (most recent call last):
...
GrammarError: Cannot add list while loaded.
Lists cannot be removed while the grammar is loaded:
>>> tester_fruit.remove_list(list_fruit) # Fails.
Traceback (most recent call last):
...
GrammarError: Cannot remove list while loaded.
Tear down test tooling:
>>> # Explicitly unload tester grammar.
>>> tester_fruit.unload()
ListRef construction
ListRef objects must be created referencing the correct type of list object:
>>> print(ListRef("list_fruit_ref", [])) # Fails.
Traceback (most recent call last):
...
TypeError: List argument to ListRef constructor must be a Dragonfly list.
>>> print(ListRef("list_fruit_ref", List("list_fruit"))) # Succeeds.
ListRef('list_fruit')
List context manager
List operations can be performed optimally via Python’s with
statement:
>>> list_fruit = List("list_fruit")
>>> element = Sequence([Literal("item"), ListRef("list_fruit_ref", list_fruit)])
>>> tester_fruit = ElementTester(element)
>>> tester_fruit.load()
>>> with list_fruit:
... list_fruit.append("apple")
... list_fruit.append("banana")
...
>>> list_fruit
['apple', 'banana']
>>> tester_fruit.recognize("item apple")
[u'item', u'apple']
>>> tester_fruit.recognize("item banana")
[u'item', u'banana']
Tear down test tooling:
>>> # Explicitly unload tester grammar.
>>> tester_fruit.unload()