############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test of the Vocabulary and related support APIs. """ import unittest class SimpleTermTests(unittest.TestCase): def _getTargetClass(self): from zope.schema.vocabulary import SimpleTerm return SimpleTerm def _makeOne(self, *args, **kw): return self._getTargetClass()(*args, **kw) def test_class_conforms_to_ITokenizedTerm(self): from zope.interface.verify import verifyClass from zope.schema.interfaces import ITokenizedTerm verifyClass(ITokenizedTerm, self._getTargetClass()) def test_instance_conforms_to_ITokenizedTerm(self): from zope.interface.verify import verifyObject from zope.schema.interfaces import ITokenizedTerm verifyObject(ITokenizedTerm, self._makeOne('VALUE')) def test_ctor_defaults(self): from zope.schema.interfaces import ITitledTokenizedTerm term = self._makeOne('VALUE') self.assertEqual(term.value, 'VALUE') self.assertEqual(term.token, 'VALUE') self.assertEqual(term.title, None) self.assertFalse(ITitledTokenizedTerm.providedBy(term)) def test_ctor_explicit(self): from zope.schema.interfaces import ITitledTokenizedTerm term = self._makeOne('TERM', 'TOKEN', 'TITLE') self.assertEqual(term.value, 'TERM') self.assertEqual(term.token, 'TOKEN') self.assertEqual(term.title, 'TITLE') self.assertTrue(ITitledTokenizedTerm.providedBy(term)) def test_bytes_value(self): from zope.schema.interfaces import ITitledTokenizedTerm term = self._makeOne(b'term') self.assertEqual(term.value, b'term') self.assertEqual(term.token, 'term') self.assertFalse(ITitledTokenizedTerm.providedBy(term)) class SimpleVocabularyTests(unittest.TestCase): def _getTargetClass(self): from zope.schema.vocabulary import SimpleVocabulary return SimpleVocabulary def _makeOne(self, *args, **kw): return self._getTargetClass()(*args, **kw) def test_class_conforms_to_IVocabularyTokenized(self): from zope.interface.verify import verifyClass from zope.schema.interfaces import IVocabularyTokenized verifyClass(IVocabularyTokenized, self._getTargetClass()) def test_instance_conforms_to_IVocabularyTokenized(self): from zope.interface.verify import verifyObject from zope.schema.interfaces import IVocabularyTokenized verifyObject(IVocabularyTokenized, self._makeOne(())) def test_ctor_additional_interfaces(self): from zope.interface import Interface from zope.schema.vocabulary import SimpleTerm class IStupid(Interface): pass VALUES = [1, 4, 2, 9] vocabulary = self._makeOne([SimpleTerm(x) for x in VALUES], IStupid) self.assertTrue(IStupid.providedBy(vocabulary)) self.assertEqual(len(vocabulary), len(VALUES)) for value, term in zip(VALUES, vocabulary): self.assertEqual(term.value, value) for value in VALUES: self.assertTrue(value in vocabulary) self.assertFalse('ABC' in vocabulary) for term in vocabulary: self.assertTrue(vocabulary.getTerm(term.value) is term) self.assertTrue(vocabulary.getTermByToken(term.token) is term) def test_fromValues(self): from zope.interface import Interface from zope.schema.interfaces import ITokenizedTerm class IStupid(Interface): pass VALUES = [1, 4, 2, 9] vocabulary = self._getTargetClass().fromValues(VALUES) self.assertEqual(len(vocabulary), len(VALUES)) for value, term in zip(VALUES, vocabulary): self.assertTrue(ITokenizedTerm.providedBy(term)) self.assertEqual(term.value, value) for value in VALUES: self.assertTrue(value in vocabulary) def test_fromItems(self): from zope.interface import Interface from zope.schema.interfaces import ITokenizedTerm class IStupid(Interface): pass ITEMS = [('one', 1), ('two', 2), ('three', 3), ('fore!', 4)] vocabulary = self._getTargetClass().fromItems(ITEMS) self.assertEqual(len(vocabulary), len(ITEMS)) for item, term in zip(ITEMS, vocabulary): self.assertTrue(ITokenizedTerm.providedBy(term)) self.assertEqual(term.token, item[0]) self.assertEqual(term.value, item[1]) for item in ITEMS: self.assertTrue(item[1] in vocabulary) def test_createTerm(self): from zope.schema.vocabulary import SimpleTerm VALUES = [1, 4, 2, 9] for value in VALUES: term = self._getTargetClass().createTerm(value) self.assertTrue(isinstance(term, SimpleTerm)) self.assertEqual(term.value, value) self.assertEqual(term.token, str(value)) def test_getTerm_miss(self): vocabulary = self._makeOne(()) self.assertRaises(LookupError, vocabulary.getTerm, 'nonesuch') def test_getTermByToken_miss(self): vocabulary = self._makeOne(()) self.assertRaises(LookupError, vocabulary.getTermByToken, 'nonesuch') def test_nonunique_tokens(self): klass = self._getTargetClass() self.assertRaises(ValueError, klass.fromValues, [2, '2']) self.assertRaises( ValueError, klass.fromItems, [(1, 'one'), ('1', 'another one')] ) self.assertRaises( ValueError, klass.fromItems, [(0, 'one'), (1, 'one')] ) def test_nonunique_tokens_swallow(self): klass = self._getTargetClass() items = [(0, 'one'), (1, 'one')] terms = [klass.createTerm(value, token) for (token, value) in items] vocab = self._getTargetClass()(terms, swallow_duplicates=True) self.assertEqual(vocab.getTerm('one').token, '1') def test_nonunique_token_message(self): try: self._getTargetClass().fromValues([2, '2']) except ValueError as e: self.assertEqual(str(e), "term tokens must be unique: '2'") def test_nonunique_token_messages(self): try: self._getTargetClass().fromItems([(0, 'one'), (1, 'one')]) except ValueError as e: self.assertEqual(str(e), "term values must be unique: 'one'") def test_overriding_createTerm(self): class MyTerm(object): def __init__(self, value): self.value = value self.token = repr(value) self.nextvalue = value + 1 class MyVocabulary(self._getTargetClass()): def createTerm(cls, value): return MyTerm(value) createTerm = classmethod(createTerm) vocab = MyVocabulary.fromValues([1, 2, 3]) for term in vocab: self.assertEqual(term.value + 1, term.nextvalue) # Test _createTermTree via TreeVocabulary.fromDict class TreeVocabularyTests(unittest.TestCase): def _getTargetClass(self): from zope.schema.vocabulary import TreeVocabulary return TreeVocabulary def tree_vocab_2(self): region_tree = { ('regions', 'Regions'): { ('aut', 'Austria'): { ('tyr', 'Tyrol'): { ('auss', 'Ausserfern'): {}, } }, ('ger', 'Germany'): { ('bav', 'Bavaria'): {} }, } } return self._getTargetClass().fromDict(region_tree) def business_tree(self): return { ('services', 'services', 'Services'): { ('reservations', 'reservations', 'Reservations'): { ('res_host', 'res_host', 'Res Host'): {}, ('res_gui', 'res_gui', 'Res GUI'): {}, }, ('check_in', 'check_in', 'Check-in'): { ('dcs_host', 'dcs_host', 'DCS Host'): {}, }, }, ('infrastructure', 'infrastructure', 'Infrastructure'): { ('communication_network', 'communication_network', 'Communication/Network'): { ('messaging', 'messaging', 'Messaging'): {}, }, ('data_transaction', 'data_transaction', 'Data/Transaction'): { ('database', 'database', 'Database'): {}, }, ('security', 'security', 'Security'): {}, }, } def tree_vocab_3(self): return self._getTargetClass().fromDict(self.business_tree()) def test_implementation(self): from zope.interface.verify import verifyObject from zope.interface.common.mapping import IEnumerableMapping from zope.schema.interfaces import ITreeVocabulary from zope.schema.interfaces import IVocabulary from zope.schema.interfaces import IVocabularyTokenized for v in [self.tree_vocab_2(), self.tree_vocab_3()]: self.assertTrue(verifyObject(IEnumerableMapping, v)) self.assertTrue(verifyObject(IVocabulary, v)) self.assertTrue(verifyObject(IVocabularyTokenized, v)) self.assertTrue(verifyObject(ITreeVocabulary, v)) def test_additional_interfaces(self): from zope.interface import Interface class IStupid(Interface): pass v = self._getTargetClass().fromDict({('one', '1'): {}}, IStupid) self.assertTrue(IStupid.providedBy(v)) def test_ordering(self): #The TreeVocabulary makes use of an OrderedDict to store it's #internal tree representation. # #Check that they keys are indeed oredered. from zope.schema._compat import OrderedDict d = { (1, 'new_york', 'New York'): { (2, 'ny_albany', 'Albany'): {}, (3, 'ny_new_york', 'New York'): {}, }, (4, 'california', 'California'): { (5, 'ca_los_angeles', 'Los Angeles'): {}, (6, 'ca_san_francisco', 'San Francisco'): {}, }, (7, 'texas', 'Texas'): {}, (8, 'florida', 'Florida'): {}, (9, 'utah', 'Utah'): {}, } dict_ = OrderedDict(sorted(d.items(), key=lambda t: t[0])) vocab = self._getTargetClass().fromDict(dict_) # Test keys self.assertEqual( [k.token for k in vocab.keys()], ['1', '4', '7', '8', '9'] ) # Test __iter__ self.assertEqual( [k.token for k in vocab], ['1', '4', '7', '8', '9'] ) self.assertEqual( [k.token for k in vocab[[k for k in vocab.keys()][0]].keys()], ['2', '3'] ) self.assertEqual( [k.token for k in vocab[[k for k in vocab.keys()][1]].keys()], ['5', '6'] ) def test_indexes(self): # TreeVocabulary creates three indexes for quick lookups, # term_by_value, term_by_value and path_by_value. tv2 = self.tree_vocab_2() self.assertEqual( [k for k in sorted(tv2.term_by_value.keys())], ['Ausserfern', 'Austria', 'Bavaria', 'Germany', 'Regions', 'Tyrol'] ) self.assertEqual( [k for k in sorted(tv2.term_by_token.keys())], ['auss', 'aut', 'bav', 'ger', 'regions', 'tyr'] ) self.assertEqual( [k for k in sorted(tv2.path_by_value.keys())], ['Ausserfern', 'Austria', 'Bavaria', 'Germany', 'Regions', 'Tyrol'] ) self.assertEqual( [k for k in sorted(tv2.path_by_value.values())], [ ['Regions'], ['Regions', 'Austria'], ['Regions', 'Austria', 'Tyrol'], ['Regions', 'Austria', 'Tyrol', 'Ausserfern'], ['Regions', 'Germany'], ['Regions', 'Germany', 'Bavaria'], ] ) self.assertEqual( [k for k in sorted(self.tree_vocab_3().term_by_value.keys())], [ 'check_in', 'communication_network', 'data_transaction', 'database', 'dcs_host', 'infrastructure', 'messaging', 'res_gui', 'res_host', 'reservations', 'security', 'services', ] ) self.assertEqual( [k for k in sorted(self.tree_vocab_3().term_by_token.keys())], [ 'check_in', 'communication_network', 'data_transaction', 'database', 'dcs_host', 'infrastructure', 'messaging', 'res_gui', 'res_host', 'reservations', 'security', 'services', ] ) self.assertEqual( [k for k in sorted(self.tree_vocab_3().path_by_value.values())], [ ['infrastructure'], ['infrastructure', 'communication_network'], ['infrastructure', 'communication_network', 'messaging'], ['infrastructure', 'data_transaction'], ['infrastructure', 'data_transaction', 'database'], ['infrastructure', 'security'], ['services'], ['services', 'check_in'], ['services', 'check_in', 'dcs_host'], ['services', 'reservations'], ['services', 'reservations', 'res_gui'], ['services', 'reservations', 'res_host'], ] ) def test_termpath(self): tv2 = self.tree_vocab_2() tv3 = self.tree_vocab_3() self.assertEqual( tv2.getTermPath('Bavaria'), ['Regions', 'Germany', 'Bavaria'] ) self.assertEqual( tv2.getTermPath('Austria'), ['Regions', 'Austria'] ) self.assertEqual( tv2.getTermPath('Ausserfern'), ['Regions', 'Austria', 'Tyrol', 'Ausserfern'] ) self.assertEqual( tv2.getTermPath('Non-existent'), [] ) self.assertEqual( tv3.getTermPath('database'), ["infrastructure", "data_transaction", "database"] ) def test_len(self): # len returns the number of all nodes in the dict self.assertEqual(len(self.tree_vocab_2()), 1) self.assertEqual(len(self.tree_vocab_3()), 2) def test_contains(self): tv2 = self.tree_vocab_2() self.assertTrue('Regions' in tv2 and 'Austria' in tv2 and 'Bavaria' in tv2) self.assertTrue('bav' not in tv2) self.assertTrue('foo' not in tv2) self.assertTrue({} not in tv2) # not hashable tv3 = self.tree_vocab_3() self.assertTrue('database' in tv3 and 'security' in tv3 and 'services' in tv3) self.assertTrue('Services' not in tv3) self.assertTrue('Database' not in tv3) self.assertTrue({} not in tv3) # not hashable def test_values_and_items(self): for v in (self.tree_vocab_2(), self.tree_vocab_3()): for term in v: self.assertEqual([i for i in v.values()], [i for i in v._terms.values()]) self.assertEqual([i for i in v.items()], [i for i in v._terms.items()]) def test_get(self): for v in [self.tree_vocab_2(), self.tree_vocab_3()]: for key, value in v.items(): self.assertEqual(v.get(key), value) self.assertEqual(v[key], value) def test_get_term(self): for v in (self.tree_vocab_2(), self.tree_vocab_3()): for term in v: self.assertTrue(v.getTerm(term.value) is term) self.assertTrue(v.getTermByToken(term.token) is term) self.assertRaises(LookupError, v.getTerm, 'non-present-value') self.assertRaises(LookupError, v.getTermByToken, 'non-present-token') def test_nonunique_values_and_tokens(self): # Since we do term and value lookups, all terms' values and tokens # must be unique. This rule applies recursively. self.assertRaises( ValueError, self._getTargetClass().fromDict, { ('one', '1'): {}, ('two', '1'): {}, }) self.assertRaises( ValueError, self._getTargetClass().fromDict, { ('one', '1'): {}, ('one', '2'): {}, }) # Even nested tokens must be unique. self.assertRaises( ValueError, self._getTargetClass().fromDict, { ('new_york', 'New York'): { ('albany', 'Albany'): {}, ('new_york', 'New York'): {}, }, }) # The same applies to nested values. self.assertRaises( ValueError, self._getTargetClass().fromDict, { ('1', 'new_york'): { ('2', 'albany'): {}, ('3', 'new_york'): {}, }, }) # The title attribute does however not have to be unique. self._getTargetClass().fromDict({ ('1', 'new_york', 'New York'): { ('2', 'ny_albany', 'Albany'): {}, ('3', 'ny_new_york', 'New York'): {}, }, }) self._getTargetClass().fromDict({ ('one', '1', 'One'): {}, ('two', '2', 'One'): {}, }) def test_nonunique_value_message(self): try: self._getTargetClass().fromDict({ ('one', '1'): {}, ('two', '1'): {}, }) except ValueError as e: self.assertEqual(str(e), "Term values must be unique: '1'") def test_nonunique_token_message(self): try: self._getTargetClass().fromDict({ ('one', '1'): {}, ('one', '2'): {}, }) except ValueError as e: self.assertEqual(str(e), "Term tokens must be unique: 'one'") def test_recursive_methods(self): #Test the _createTermTree and _getPathToTreeNode methods from zope.schema.vocabulary import _createTermTree tree = _createTermTree({}, self.business_tree()) vocab = self._getTargetClass().fromDict(self.business_tree()) term_path = vocab._getPathToTreeNode(tree, "infrastructure") vocab_path = vocab._getPathToTreeNode(vocab, "infrastructure") self.assertEqual(term_path, vocab_path) self.assertEqual(term_path, ["infrastructure"]) term_path = vocab._getPathToTreeNode(tree, "security") vocab_path = vocab._getPathToTreeNode(vocab, "security") self.assertEqual(term_path, vocab_path) self.assertEqual(term_path, ["infrastructure", "security"]) term_path = vocab._getPathToTreeNode(tree, "database") vocab_path = vocab._getPathToTreeNode(vocab, "database") self.assertEqual(term_path, vocab_path) self.assertEqual(term_path, ["infrastructure", "data_transaction", "database"]) term_path = vocab._getPathToTreeNode(tree, "dcs_host") vocab_path = vocab._getPathToTreeNode(vocab, "dcs_host") self.assertEqual(term_path, vocab_path) self.assertEqual(term_path, ["services", "check_in", "dcs_host"]) term_path = vocab._getPathToTreeNode(tree, "dummy") vocab_path = vocab._getPathToTreeNode(vocab, "dummy") self.assertEqual(term_path, vocab_path) self.assertEqual(term_path, []) class RegistryTests(unittest.TestCase): #Tests of the simple vocabulary and presentation registries. def setUp(self): from zope.schema.vocabulary import _clear _clear() def tearDown(self): from zope.schema.vocabulary import _clear _clear() def test_setVocabularyRegistry(self): from zope.schema.vocabulary import setVocabularyRegistry from zope.schema.vocabulary import getVocabularyRegistry r = _makeDummyRegistry() setVocabularyRegistry(r) self.assertTrue(getVocabularyRegistry() is r) def test_getVocabularyRegistry(self): from zope.schema.interfaces import IVocabularyRegistry from zope.schema.vocabulary import getVocabularyRegistry r = getVocabularyRegistry() self.assertTrue(IVocabularyRegistry.providedBy(r)) # TODO: still need to test the default implementation def _makeSampleVocabulary(): from zope.interface import implementer from zope.schema.interfaces import IVocabulary class SampleTerm(object): pass @implementer(IVocabulary) class SampleVocabulary(object): def __iter__(self): return iter([self.getTerm(x) for x in range(0, 10)]) def __contains__(self, value): return 0 <= value < 10 def __len__(self): return 10 def getTerm(self, value): if value in self: t = SampleTerm() t.value = value t.double = 2 * value return t raise LookupError("no such value: %r" % value) return SampleVocabulary() def _makeDummyRegistry(): from zope.schema.vocabulary import VocabularyRegistry class DummyRegistry(VocabularyRegistry): def get(self, object, name): v = _makeSampleVocabulary() v.object = object v.name = name return v return DummyRegistry() def test_suite(): return unittest.TestSuite(( unittest.makeSuite(SimpleTermTests), unittest.makeSuite(SimpleVocabularyTests), unittest.makeSuite(TreeVocabularyTests), unittest.makeSuite(RegistryTests), ))