Skip to content

Commit

Permalink
Fix config tests, add tests for (and relocate) fact proxy and have it…
Browse files Browse the repository at this point in the history
… support case-insensitivity
  • Loading branch information
batterseapower committed Sep 22, 2009
1 parent ebb09a5 commit 25f3dd8
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 73 deletions.
5 changes: 3 additions & 2 deletions pinyin/anki/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import anki.utils

import pinyin.anki.keys
import pinyin.factproxy
from pinyin.logger import log
import pinyin.media
import pinyin.transformations
Expand All @@ -30,7 +31,7 @@ def onFocusLost(self, fact, field):
return

# Need a fact proxy because the updater works on dictionary-like objects
factproxy = utils.AnkiFactProxy(self.config.candidateFieldNamesByKey, fact)
factproxy = pinyin.factproxy.FactProxy(self.config.candidateFieldNamesByKey, fact)

# Find which kind of field we have just moved off
updater = None
Expand Down Expand Up @@ -186,7 +187,7 @@ def triggered(self):

for fact in utils.suitableFacts(self.config.modelTag, self.mw.deck):
# Need a fact proxy because the updater works on dictionary-like objects
factproxy = utils.AnkiFactProxy(self.config.candidateFieldNamesByKey, fact)
factproxy = pinyin.factproxy.FactProxy(self.config.candidateFieldNamesByKey, fact)
if field not in factproxy:
continue

Expand Down
67 changes: 0 additions & 67 deletions pinyin/anki/utils.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import anki.utils

from pinyin.logger import log

"""
The fact proxy is responsible for making an Anki fact look like a dictionary with known keys.
It is responsible for choosing which of the available fields on a fact we map to each purpose.
"""
class AnkiFactProxy(object):
def __init__(self, candidateFieldNamesByKey, fact):
self.fact = fact

# NB: the fieldnames dictionary IS part of the interface of this class
self.fieldnames = {}
for key, candidateFieldNames in candidateFieldNamesByKey.items():
# Don't add a key into the dictionary if we can't find a field, or we end
# up reporting that we the contain the field but die during access
fieldname = chooseField(candidateFieldNames, fact)
if fieldname is not None:
self.fieldnames[key] = fieldname

def __contains__(self, key):
return key in self.fieldnames

def __getitem__(self, key):
return self.fact[self.fieldnames[key]]

def __setitem__(self, key, value):
self.fact[self.fieldnames[key]] = value

def chooseField(candidateFieldNames, fact):
# Find the first field that is present in the fact
for candidateField in candidateFieldNames:
if candidateField in fact.keys():
log.info("Choose %s as a field name from the fact", candidateField)
return candidateField

# No suitable field found!
log.warn("No field matching %s in the fact", candidateFieldNames)
return None

def persistconfig(mw, config):
# NB: MUST store a dict into settings, not a Config object. The
# reason is that the pickler needs to see the class definition
Expand All @@ -57,30 +17,3 @@ def suitableFacts(modelTag, deck):
if anki.utils.findTag(modelTag, model.tags):
for fact in deck.s.query(anki.facts.Fact).filter('modelId = %s' % model.id):
yield fact

if __name__ == "__main__":
import unittest

class AnkiFactProxyTest(unittest.TestCase):
def testDontContainMissingFields(self):
self.assertFalse("key" in AnkiFactProxy({"key" : ["Foo", "Bar"]}, { "Baz" : "Hi" }))

def testContainsPresentFields(self):
self.assertFalse("key" in AnkiFactProxy({"key" : ["Foo", "Bar"]}, { "Bar" : "Hi" }))

def testSet(self):
fact = { "Baz" : "Hi" }
AnkiFactProxy({"key" : ["Foo", "Bar"]}, fact)["key"] = "Bye"
self.assertEquals(fact["Baz"], "Bye")

def testGet(self):
fact = { "Baz" : "Hi" }
self.assertEquals(AnkiFactProxy({"key" : ["Foo", "Bar"]}, fact)["key"], "Hi")

def testPriority(self):
fact = { "Baz" : "Hi", "Foo" : "Meh" }
AnkiFactProxy({"key" : ["Foo", "Bar"]}, fact)["key"] = "Bye"
self.assertEquals(fact["Foo"], "Bye")
self.assertEquals(fact["Bar"], "Hi")

unittest.main()
40 changes: 40 additions & 0 deletions pinyin/factproxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-

from pinyin.logger import log

"""
The fact proxy is responsible for making an Anki fact look like a dictionary with known keys.
It is responsible for choosing which of the available fields on a fact we map to each purpose.
"""
class FactProxy(object):
def __init__(self, candidateFieldNamesByKey, fact):
self.fact = fact

# NB: the fieldnames dictionary IS part of the interface of this class
self.fieldnames = {}
for key, candidateFieldNames in candidateFieldNamesByKey.items():
# Don't add a key into the dictionary if we can't find a field, or we end
# up reporting that we the contain the field but die during access
fieldname = chooseField(candidateFieldNames, fact)
if fieldname is not None:
self.fieldnames[key] = fieldname

def __contains__(self, key):
return key in self.fieldnames

def __getitem__(self, key):
return self.fact[self.fieldnames[key]]

def __setitem__(self, key, value):
self.fact[self.fieldnames[key]] = value

def chooseField(candidateFieldNames, fact):
# Find the first field that is present in the fact
for candidateField in candidateFieldNames:
for factfieldname in [factfieldname for factfieldname in fact.keys() if factfieldname.lower() == candidateField.lower()]:
log.info("Choose %s as a field name from the fact for %s", factfieldname, candidateField)
return factfieldname

# No suitable field found!
log.warn("No field matching %s in the fact", candidateFieldNames)
return None
1 change: 1 addition & 0 deletions pinyin/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import config
import dictionary
import dictionaryonline
import factproxy
import meanings
import media
import model
Expand Down
15 changes: 11 additions & 4 deletions pinyin/tests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,17 @@ def testTonified(self):
self.assertFalse(Config({ "tonedisplay" : "numeric" }).shouldtonify)

def testNeedMeanings(self):
self.assertTrue(Config({ "meaninggeneration" : True, "detectmeasurewords" : True }).needmeanings)
self.assertTrue(Config({ "meaninggeneration" : True, "detectmeasurewords" : False }).needmeanings)
self.assertTrue(Config({ "meaninggeneration" : False, "detectmeasurewords" : True }).needmeanings)
self.assertFalse(Config({ "meaninggeneration" : False, "detectmeasurewords" : False }).needmeanings)
def row(mg, dmw, mwag, res):
self.assertEquals(Config({ "meaninggeneration" : mg, "detectmeasurewords" : dmw, "mwaudiogeneration" : mwag }).needmeanings, res)

row(True, True, True, True)
row(True, True, False, True)
row(True, False, True, True)
row(True, False, False, True)
row(False, True, True, True)
row(False, True, False, True)
row(False, False, True, True)
row(False, False, False, False)

def testMeaningNumber(self):
self.assertEquals(map(lambda n: Config({ "meaningnumbering" : "arabicParens", "colormeaningnumbers" : False, "emphasisemainmeaning" : False }).meaningnumber(n), [2, 10, 21]),
Expand Down
36 changes: 36 additions & 0 deletions pinyin/tests/factproxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-

import unittest

from pinyin.factproxy import *


class FactProxyTest(unittest.TestCase):
def testDontContainMissingFields(self):
self.assertFalse("key" in FactProxy({"key" : ["Foo", "Bar"]}, { "Baz" : "Hi" }))

def testContainsPresentFields(self):
self.assertTrue("key" in FactProxy({"key" : ["Foo", "Bar"]}, { "Bar" : "Hi" }))

def testSet(self):
fact = { "Baz" : "Hi" }
FactProxy({"key" : ["Foo", "Baz"]}, fact)["key"] = "Bye"
self.assertEquals(fact["Baz"], "Bye")

def testGet(self):
fact = { "Baz" : "Hi" }
self.assertEquals(FactProxy({"key" : ["Foo", "Baz"]}, fact)["key"], "Hi")

def testPriority(self):
fact = { "Baz" : "Hi", "Foo" : "Meh" }
FactProxy({"key" : ["Foo", "Baz"]}, fact)["key"] = "Bye"
self.assertEquals(fact, { "Baz" : "Hi", "Foo" : "Bye" })

fact = { "Baz" : "Hi", "Foo" : "Meh" }
FactProxy({"key" : ["Baz", "Foo"]}, fact)["key"] = "Bye"
self.assertEquals(fact, { "Baz" : "Bye", "Foo" : "Meh" })

def testCase(self):
fact = { "Foo" : "Meh" }
FactProxy({"key" : ["foo"]}, fact)["key"] = "Bye"
self.assertEquals(fact, { "Foo" : "Bye" })

0 comments on commit 25f3dd8

Please sign in to comment.