def register_semantic_type_to_format(self, semantic_type, artifact_format): if not issubclass(artifact_format, DirectoryFormat): raise TypeError("%r is not a directory format." % artifact_format) if not is_semantic_type(semantic_type): raise TypeError("%r is not a semantic type." % semantic_type) if not isinstance(semantic_type, grammar.TypeExpression): raise ValueError("%r is not a semantic type expression." % semantic_type) if semantic_type.predicate is not None: raise ValueError("%r has a predicate, differentiating format on" " predicate is not supported.") self.type_formats.append(TypeFormatRecord( type_expression=semantic_type, format=artifact_format, plugin=self))
def register_semantic_types(self, *semantic_types): for semantic_type in semantic_types: if not is_semantic_type(semantic_type): raise TypeError("%r is not a semantic type." % semantic_type) if not (isinstance(semantic_type, grammar.CompositeType) or (semantic_type.is_concrete() and not semantic_type.fields)): raise ValueError("%r is not a semantic type symbol." % semantic_type) if semantic_type.name in self.types: raise ValueError("Duplicate semantic type symbol %r." % semantic_type) self.types[semantic_type.name] = SemanticTypeRecord( semantic_type=semantic_type, plugin=self)
def parse_type(string, expect=None): """Convert a string into a TypeExpression Parameters ---------- string : str The string type expression to convert into a TypeExpression expect : {'semantic', 'primitive', 'visualization'}, optional Will raise a TypeError if the resulting TypeExpression is not a member of `expect`. Returns ------- TypeExpression Raises ------ ValueError Raised when `expect` has an invalid value TypeError Raised when the expression contains invalid characters TypeError Raised when the expression does not result in a member of `expect` UnknownTypeError Raised when unkown types are present in the expression. """ if expect is not None and expect not in {'semantic', 'primitive', 'visualization'}: raise ValueError("`expect` got %r, must be 'semantic', 'primitive'," " 'visualization', or None." % (expect,)) if '\n' in string or '\r' in string or ';' in string: raise TypeError("Found multiple statements in type expression %r. Will" " not evaluate to avoid arbitrary code execution." % string) pm = qiime2.sdk.PluginManager() locals_ = {n: getattr(qtype, n) for n in qtype.__all__ if '_' not in n} locals_.update({k: v.semantic_type for k, v in pm.semantic_types.items()}) try: type_expr = eval(string, {'__builtins__': {}}, locals_) if expect is None: pass elif expect == 'semantic' and qtype.is_semantic_type(type_expr): pass # TODO optimize codepath for `expect=primitive` and # `expect=visualization` since `PluginManager` is slow and isn't # necessary for these types. elif expect == 'primitive' and qtype.is_primitive_type(type_expr): pass elif expect == 'visualization' and type_expr == qtype.Visualization: pass else: raise TypeError("Type expression %r is not a %s type." % (type_expr, expect)) return type_expr except NameError as e: # http://stackoverflow.com/a/2270822/579416 name, = re.findall("name '(\w+)' is not defined", str(e)) raise UnknownTypeError("Name %r is not a defined QIIME type, a plugin" " may be needed to define it." % name)
def test_set_primitive_type(self): self.assertTrue(is_collection_type(Set[Int % Range(5)])) self.assertTrue(is_primitive_type(Set[Int % Range(5)])) self.assertFalse(is_semantic_type(Set[Int % Range(5)]))
def test_set_semantic_type(self): Foo = SemanticType('Foo') self.assertTrue(is_collection_type(Set[Foo])) self.assertTrue(is_semantic_type(Set[Foo])) self.assertFalse(is_primitive_type(Set[Foo]))
def action_patch(self, action: 'UsageAction', inputs: 'UsageInputs', outputs: 'UsageOutputNames', ) -> 'UsageOutputs': """ A monkeypatch for Usage.action that deals generously with archive versions that don't track output-name. If there are no output-names to search the signature with, it will attempt to search the signature.outputs for a parameter spec with the same QIIME type. Because our goal in the patched snippet is to assign a usage example type, a type-expression match should always return a correct usage example type. """ if not isinstance(action, UsageAction): # pragma: no cover raise ValueError('Invalid value for `action`: expected %r, ' 'received %r.' % (UsageAction, type(action))) if not isinstance(inputs, UsageInputs): # pragma: no cover raise ValueError('Invalid value for `inputs`: expected %r, ' 'received %r.' % (UsageInputs, type(inputs))) if not isinstance(outputs, UsageOutputNames): # pragma: no cover raise ValueError('Invalid value for `outputs`: expected %r, ' 'received %r.' % (UsageOutputNames, type(outputs))) action_f = _get_action_if_plugin_present(action) @functools.lru_cache(maxsize=None) def memoized_action(): # pragma: no cover execed_inputs = inputs.map_variables(lambda v: v.execute()) if self.asynchronous: return action_f.asynchronous(**execed_inputs).result() return action_f(**execed_inputs) usage_results = [] # outputs will be ordered by the `UsageOutputNames` order, not the # signature order - this makes it so that the example writer doesn't # need to be explicitly aware of the signature order for param_name, var_name in outputs.items(): # param name is not output-name in archive versions without output-name try: qiime_type = action_f.signature.outputs[param_name].qiime_type except KeyError: # param_name is often a snake-case qiime2 type, so we can check # if the same type still exists in the param spec. If so, use it. for (p_name, p_spec) in action_f.signature.outputs.items(): searchable_type_name = camel_to_snake(str(p_spec.qiime_type)) if param_name == searchable_type_name: qiime_type = action_f.signature.outputs[p_name].qiime_type break if is_visualization_type(qiime_type): var_type = 'visualization' elif is_semantic_type(qiime_type): var_type = 'artifact' else: # pragma: no cover raise ValueError('unknown output type: %r' % (qiime_type,)) def factory(name=param_name): # pragma: no cover results = memoized_action() result = getattr(results, name) return result variable = self._usage_variable(var_name, factory, var_type) usage_results.append(variable) results = UsageOutputs(outputs.keys(), usage_results) cache_info = memoized_action.cache_info cache_clear = memoized_action.cache_clear # manually graft on cache operations object.__setattr__(results, '_cache_info', cache_info) object.__setattr__(results, '_cache_reset', cache_clear) return results
def parse_type(string, expect=None): """Convert a string into a TypeExpression Parameters ---------- string : str The string type expression to convert into a TypeExpression expect : {'semantic', 'primitive', 'visualization'}, optional Will raise a TypeError if the resulting TypeExpression is not a member of `expect`. Returns ------- TypeExpression Raises ------ ValueError Raised when `expect` has an invalid value TypeError Raised when the expression contains invalid characters TypeError Raised when the expression does not result in a member of `expect` UnknownTypeError Raised when unkown types are present in the expression. """ if expect is not None and expect not in {'semantic', 'primitive', 'visualization'}: raise ValueError("`expect` got %r, must be 'semantic', 'primitive'," " 'visualization', or None." % (expect,)) if '\n' in string or '\r' in string or ';' in string: raise TypeError("Found multiple statements in type expression %r. Will" " not evaluate to avoid arbitrary code execution." % string) pm = qiime2.sdk.PluginManager() locals_ = {n: getattr(qtype, n) for n in qtype.__all__ if '_' not in n} locals_.update({k: v.semantic_type for k, v in pm.semantic_types.items()}) try: type_expr = eval(string, {'__builtins__': {}}, locals_) if expect is None: pass elif expect == 'semantic' and qtype.is_semantic_type(type_expr): pass # TODO optimize codepath for `expect=primitive` and # `expect=visualization` since `PluginManager` is slow and isn't # necessary for these types. elif expect == 'primitive' and qtype.is_primitive_type(type_expr): pass elif expect == 'visualization' and type_expr == qtype.Visualization: pass else: raise TypeError("Type expression %r is not a %s type." % (type_expr, expect)) return type_expr except NameError as e: # http://stackoverflow.com/a/2270822/579416 name, = re.findall(r"name '(\w+)' is not defined", str(e)) raise UnknownTypeError("Name %r is not a defined QIIME type, a plugin" " may be needed to define it." % name)