def wrapper(obj): try: return obj_processor(obj) except Exception as e: if isinstance(e, TextXError): raise else: if hasattr(obj, '_tx_position') and hasattr(obj, '_tx_filename'): raise_from(TextXError(str(e), **get_location(obj)), e) else: raise_from(TextXError(str(e)), e)
def model_from_str(self, model_str, file_name=None, debug=None, pre_ref_resolution_callback=None, encoding='utf-8'): """ Instantiates model from the given string. :param pre_ref_resolution_callback: called before references are resolved. This can be useful to manage models distributed across files (scoping) """ if type(model_str) is not text: raise TextXError("textX accepts only unicode strings.") if file_name is None: model = self._parser_blueprint.clone().get_model_from_str( model_str, debug=debug, pre_ref_resolution_callback=pre_ref_resolution_callback) for p in self._model_processors: p(model, self) else: model = self.internal_model_from_file(file_name, encoding, debug, model_str=model_str) return model
def get_reference_propositions(self, obj, attr, name_part): """ retrieve a list of reference propositions. Args: obj: parent attr: attribute name_part: The name is used to build the list (e.g. using a substring-like logic). Returns: the list of objects representing the proposed references """ from textx.scoping.tools import resolve_model_path from textx import textx_isinstance obj_list = resolve_model_path(obj, self.path_to_container_object) if type(obj_list) is Postponed: self.postponed_counter += 1 return obj_list # the referenced element must be a list # (else it is a design error in the path passed to # the RelativeName object). if not isinstance(obj_list, list): from textx.exceptions import TextXError raise TextXError( "expected path to list in the model ({})".format( self.path_to_container_object)) obj_list = filter( lambda x: textx_isinstance(x, attr.cls) and x.name.find(name_part) >= 0, obj_list) return list(obj_list)
def get_language(language_name): """ Returns a callable that instantiates meta-model for the given language. """ langs = list(pkg_resources.iter_entry_points(group=LANG_EP, name=language_name)) if not langs: raise TextXError('Language "{}" is not registered.' .format(language_name)) if len(langs) > 1: # Multiple languages defined with the same name raise TextXError('Language "{}" registered multiple times:\n{}' .format(language_name, "\n".join([l.dist for l in langs]))) return langs[0].load()()
def check_testcase(testcase): """ checks that the config used by the testcase fulfills its needs """ for need in testcase.needs: if need not in testcase.config.haves: raise (TextXError( "{}: {} not found in {}.{}".format(testcase.name, need.name, testcase.scenario.name, testcase.config.name), **get_location(testcase) # unpack location info ))
def model_from_str(self, model_str, file_name=None, debug=None, pre_ref_resolution_callback=None, encoding='utf-8', **kwargs): """ Instantiates model from the given string. :param pre_ref_resolution_callback: called before references are resolved. This can be useful to manage models distributed across files (scoping) :param **kwargs additional arguments available through _tx_model_params after initiating the model. The attribute is set while executing pre_ref_resolution_callback (see scoping.md) """ self._tx_model_param_definitions.check_params('from_str', **kwargs) if type(model_str) is not text: raise TextXError("textX accepts only unicode strings.") if file_name is None: def kwargs_callback(other_model): if hasattr(other_model, '_tx_metamodel'): other_model._tx_model_params = ModelParams(kwargs) if pre_ref_resolution_callback: pre_ref_resolution_callback(other_model) model = self._parser_blueprint.clone().get_model_from_str( model_str, debug=debug, pre_ref_resolution_callback=kwargs_callback) for p in self._model_processors: p(model, self) else: model = self.internal_model_from_file( file_name, encoding, debug, model_str=model_str, pre_ref_resolution_callback=pre_ref_resolution_callback, model_params=ModelParams(kwargs)) return model
def get_reference_propositions(self, obj, attr, name_part): """ retrieve a list of reference propositions. Args: obj: parent attr: attribute name_part: The name is used to build the list (e.g. using a substring-like logic). Returns: the list of objects representing the proposed references """ from textx.scoping.tools import resolve_model_path from textx import textx_isinstance # find all all "connected" objects # (e.g. find all classes: the most derived # class, its base, the base of its base, etc.) from textx.scoping.tools import get_list_of_concatenated_objects def_obj = resolve_model_path(obj, self.path_to_definition_object) def_objs = get_list_of_concatenated_objects(def_obj, self.path_to_extension) # for all containing classes, collect all # objects to be looked up (e.g. methods) obj_list = [] for def_obj in def_objs: if type(def_obj) is Postponed: self.postponed_counter += 1 return def_obj tmp_list = resolve_model_path(def_obj, self.path_to_target) assert tmp_list is not None # expected to point to alist if not isinstance(tmp_list, list): from textx.exceptions import TextXError raise TextXError( "expected path to list in the model ({})".format( self.path_to_target)) tmp_list = list( filter( lambda x: textx_isinstance(x, attr.cls) and x.name.find( name_part) >= 0, tmp_list)) obj_list = obj_list + tmp_list return list(obj_list)
def resolve_model_path(obj, dot_separated_name, follow_named_element_in_lists=False): """ Get a model object based on a model-path starting from some model object. It can be used in the same way you would navigate through a normal instance of a model object, except: - "parent(TYPE)" can be used to navigate to the parent of an element repeatedly, until a certain type is reached (see unittest). - lists of named objects (e.g. lists of named packages) can be traversed, as if the named objects were part of the model grammar (see unittest: Syntax, "name_of_model_list.name_of_named_obj_in_list"). - None/Postponed values are intercepted and lead to an overall return value None/Postponed. A use case for this function is, when a model path needs to be stored and executed on a previously unknown object and/or the Postpone/None-logic is required. Args: obj: the current object dot_separated_name: the attribute name "a.b.c.d" starting from obj Note: the attribute "parent(TYPE)" is a shortcut to jump to the parent of type "TYPE" (exact match of type name). follow_named_element_in_lists: follow named elements in list if True override_unresolved_lists: try to follow unresolved lists, if True Returns: the object if found, or Postponed() if some postponed refs are found on the path / or obj is not found """ from textx.scoping import Postponed names = dot_separated_name.split(".") match = re.match(r'parent\((\w+)\)', names[0]) if obj is None or type(obj) is Postponed: return obj elif type(obj) is list: if follow_named_element_in_lists: next_obj = get_named_obj_in_list(obj, names[0]) else: from textx.exceptions import TextXError raise TextXError( "unexpected: got list in path for get_referenced_object") elif match: next_obj = obj desired_parent_typename = match.group(1) next_obj = get_recursive_parent_with_typename( next_obj, desired_parent_typename) if type(next_obj) is Postponed: return next_obj elif next_obj is not None: return resolve_model_path(next_obj, ".".join(names[1:]), follow_named_element_in_lists) else: return None else: next_obj = getattr(obj, names[0]) if needs_to_be_resolved(obj, names[0]): return Postponed() elif next_obj is None: return None if len(names) > 1: return resolve_model_path(next_obj, ".".join( names[1:]), follow_named_element_in_lists) return next_obj