in src/composer/composer.py [0:0]
def declare(combinators, prefix=None):
'''
derive combinator methods from combinator table
check argument count and map argument positions to argument names
delegate to Composition constructor for the rest of the validation
'''
if not isinstance(combinators, dict):
raise ComposerError('Invalid argument "combinators" in "declare"', combinators)
if prefix is not None and not isinstance(prefix, str):
raise ComposerError('Invalid argument "prefix" in "declare"', prefix)
composer = types.SimpleNamespace()
for key in combinators:
type_ = prefix + '.' + key if prefix is not None else key
combinator = combinators[key]
if not isinstance(combinator, dict) or ('args' in combinator and not isinstance(combinator['args'], list)):
raise ComposerError('Invalid "'+type_+'" combinator specification in "declare"', combinator)
if 'args' in combinator:
for arg in combinator['args']:
if not isinstance(arg['name'], str):
raise ComposerError('Invalid "'+type_+'" combinator specification in "declare"', combinator)
# Javascript capturing rules differ from python3 ones.
def capture(combinator=combinator, type_=type_):
def combine(*arguments):
composition = { 'type': type_, '.combinator': lambda : combinator }
skip = len(combinator.get('args', []))
if 'components' not in combinator and len(arguments) > skip:
raise ComposerError('Too many arguments in "'+type_+'" combinator')
for i in range(skip):
composition[combinator['args'][i]['name']] = arguments[i]
if 'components' in combinator:
composition['components'] = arguments[skip:]
return Composition(composition)
return combine
setattr(composer, key, capture())
return composer