Skip to content

Commit

Permalink
New PrefixDict.
Browse files Browse the repository at this point in the history
  • Loading branch information
rec committed Jan 10, 2015
1 parent c89567d commit 0a7f73b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 28 deletions.
43 changes: 35 additions & 8 deletions code/python/echomesh/base/GetPrefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

from echomesh.base import Join

class PrefixException(Exception):
pass
class PrefixException(KeyError):
def __init__(self, key, *args, **kwds):
args = ' '.join(a for a in args if a)
super(PrefixException, self).__init__(key, args, **kwds)

def __str__(self):
return self.args[1]

_NONE = object()

def get_prefix(table, key, allow_prefixes=True):
def get_prefix(table, key, allow_prefixes=True, exception_prefix=''):
"""
Looks up an entry in a table where unique prefixes are allowed.
"""
Expand All @@ -25,22 +30,44 @@ def get_prefix(table, key, allow_prefixes=True):
elif len(results) > 1:
words = sorted(x[0] for x in results)
cmds = Join.join_words(words)
raise PrefixException('"%s" matches more than one: %s' %
(key, cmds))
raise PrefixException('"%s" is not valid' % (key))
raise PrefixException(key, exception_prefix,
'"%s" matches more than one:' % key, cmds)
raise PrefixException(key, exception_prefix, '"%s" is not valid' % key)

def set_assignment(address, value, master, slave, unmapped_keys=None):
def set_assignment(
address, value, master, slave, unmapped_keys=None, exception_prefix=''):
unmapped = False
keys = address.split('.')
for i, key in enumerate(keys):
if unmapped:
new_master = master.get(key, {})
else:
key, new_master = get_prefix(master, key)
key, new_master = get_prefix(master, key,
exception_prefix=exception_prefix)
if i == len(keys) - 1:
slave[key] = value
else:
master = new_master
slave = slave.setdefault(key, {})
if (not i) and unmapped_keys and key in unmapped_keys:
unmapped = True

class PrefixDict(dict):
allow_prefixes = True
name = ''

def get_prefix(self, key):
prefix = self.name and ('In table %s,' % self.name)
return get_prefix(self, key,
exception_prefix=prefix,
allow_prefixes=self.allow_prefixes)

def __getitem__(self, key):
return self.get_prefix(key)[1]

def __contains__(self, key):
try:
self[key]
return True
except:
return False
29 changes: 14 additions & 15 deletions code/python/echomesh/base/GetPrefix_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ class GetPrefixTest(TestCase):
def setUp(self):
self.slave = {}

def assertException(self, key, message, allow_prefixes=True):
with self.assertRaises(GetPrefix.PrefixException) as cm:
GetPrefix.get_prefix(TABLE, key, allow_prefixes=allow_prefixes)
self.assertEqual(str(cm.exception), message)

def test_simple(self):
self.assertEqual(GetPrefix.get_prefix(TABLE, 'one'), ('one', 1))

Expand All @@ -22,23 +27,10 @@ def test_no_prefix(self):
('one', 1))

def test_bad_prefix(self):
try:
GetPrefix.get_prefix(TABLE, 'o', allow_prefixes=False)
except Exception as e:
self.assertEqual(str(e), '"o" is not valid')

def test_no_prefix2(self):
try:
GetPrefix.get_prefix(TABLE, 'x', allow_prefixes=False)
except Exception as e:
self.assertEqual(str(e), '"x" is not valid')
self.assertException('o', '"o" is not valid', allow_prefixes=False)

def test_many_prefixes(self):
try:
GetPrefix.get_prefix(TABLE, 't')
except Exception as e:
self.assertEqual(str(e),
'"t" matches more than one: three and two')
self.assertException('t', '"t" matches more than one: three and two')

def test_assignment(self):
GetPrefix.set_assignment('foo.bar.baz', 32, MASTER, self.slave)
Expand All @@ -52,3 +44,10 @@ def test_assignment_unmapped(self):
GetPrefix.set_assignment('new.foo', 23, MASTER, self.slave,
unmapped_keys=set(['new']))
self.assertEqual(self.slave, {'new': {'foo': 23}})

def test_prefix_dict(self):
pdict = GetPrefix.PrefixDict(TABLE)
self.assertEqual(pdict['o'], 1)
with self.assertRaises(GetPrefix.PrefixException) as cm:
GetPrefix.get_prefix(TABLE, 'x')
self.assertEqual(str(cm.exception), '"x" is not valid')
3 changes: 2 additions & 1 deletion code/python/echomesh/base/MergeSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def save(self):

parent = os.path.dirname(f)
if not os.path.exists(parent):
print('Creating directory', parent)
from echomesh.util import Log
Log.logger(__name__).info('Creating directory %s.', parent)
os.makedirs(parent)

with open(f, 'wb') as fw:
Expand Down
5 changes: 2 additions & 3 deletions code/python/echomesh/command/Help.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

LOGGER = Log.logger(__name__)

HELP_TEXT = """
HELP = """
echomesh has the following help topics:
%s
Expand All @@ -17,8 +17,7 @@

def _help(_, *parts):
if not parts:
LOGGER.info(HELP_TEXT,
Registry.registry().join_keys(command_only=False))
LOGGER.info(HELP, Registry.registry().join_keys(command_only=False))
else:
cmd, parts = parts[0], parts[1:]
if not parts:
Expand Down
17 changes: 16 additions & 1 deletion code/python/echomesh/settings/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type: config
aliases:
save_with_project: false

# Configure audio input, output and processing.
audio:
# The audio section is the longest section in the whole config file.

Expand All @@ -35,10 +36,13 @@ audio:
# printed on the console - very spammy.
verbose: false

# This is a list of mapping from db levels to microphone levels.
# A list of mapping from db levels to microphone levels.
#
# BUG: For the moment, you can't use unit conversions in this area, so
# don't put "db" after these numbers:
# https://github.com/rec/echomesh/issues/195
#
# TODO: these should move into a plug-in specific setting.
levels:
silent: -37
quiet: -25
Expand All @@ -57,6 +61,17 @@ audio:
# Disabled, see https://github.com/rec/echomesh/issues/197.
route: audio

# Where do we look for commands, patterns, elements and outputs?
#
# Any entries from here come before the echomesh system defaults, so if you
# create a function of the same name as a system one, it'll override that value.

classpath:
command: ''
pattern: ''
element: ''
output: ''

# Turns on various debugging mechanisms and gives better diagnositics.
debug: false

Expand Down

0 comments on commit 0a7f73b

Please sign in to comment.