def virtual(cls, **options):
def wrapped(func):<EOL><INDENT>param_name = inflection.underscore(func.__name__)<EOL>options.setdefault('<STR_LIT:name>', param_name)<EOL>if '<STR_LIT>' in options:<EOL><INDENT>if isinstance(options['<STR_LIT>'], set):<EOL><INDENT>options['<STR_LIT>'].add('<STR_LIT>')<EOL>options['<STR_LIT>'].add('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>options['<STR_LIT>'] |= (cls.Flags.Virtual | cls.Flags.ReadOnly)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>options['<STR_LIT>'] = {'<STR_LIT>', '<STR_LIT>'}<EOL><DEDENT>def define_setter():<EOL><INDENT>def setter_wrapped(setter_func):<EOL><INDENT>func.__orb__.setFlags(func.__orb__.flags() & ~cls.Flags.ReadOnly)<EOL>func.__orb__.setter()(setter_func)<EOL>return setter_func<EOL><DEDENT>return setter_wrapped<EOL><DEDENT>def define_query_filter():<EOL><INDENT>def shortcut_wrapped(shortcut_func):<EOL><INDENT>func.__orb__.queryFilter(shortcut_func)<EOL>return shortcut_func<EOL><DEDENT>return shortcut_wrapped<EOL><DEDENT>func.__orb__ = cls(**options)<EOL>func.__orb__.getter()(func)<EOL>func.setter = define_setter<EOL>func.queryFilter = define_query_filter<EOL>return func<EOL><DEDENT>return wrapped<EOL>
Allows for defining virtual columns and collectors on models -- these
are objects that are defined in code and not directly in a data store.

:param cls:
:param options:
:return: