예제 #1
0
def test_get_model():

    metamodel = metamodel_from_str(grammar)
    model = metamodel.model_from_str(model_str)

    t = model.a[0].y
    assert get_model(t) is model
예제 #2
0
def get_parser(model_obj):
    """
    Args:
        model_obj: the model object of interest

    Returns:
        the parser associated with the element
    """
    the_model = get_model(model_obj)
    return the_model._tx_parser
예제 #3
0
 def check_raw_type_is_defined_for_language(rawtype):
     if "generate_cpp" in self.options.keys(
     ) and self.options["generate_cpp"]:
         if rawtype.genericType == "custom" and not rawtype.cpptype:
             raise Exception(
                 "C++ type is required to generate C++ code for {} in {}"
                 .format(rawtype.name,
                         get_model(rawtype)._tx_filename))
     if "generate_python" in self.options.keys(
     ) and self.options["generate_python"]:
         if rawtype.genericType == "custom" and not rawtype.pythontype:
             raise Exception(
                 "python type is required to generate python code for {} in {}"
                 .format(rawtype.name,
                         get_model(rawtype)._tx_filename))
     if "generate_python_construct" in self.options.keys(
     ) and self.options["generate_python_construct"]:
         if not rawtype.pythonconstructtype:
             raise Exception(
                 "python-construct type is required to generate python code for {} in {}"
                 .format(rawtype.name,
                         get_model(rawtype)._tx_filename))
예제 #4
0
def needs_to_be_resolved(parent_obj, attr_name):
    """
    This function determines, if a reference (CrossReference) needs to be
    resolved or not (while creating the model, while resolving references).

    Args:
        parent_obj: the object containing the attribute to be resolved.
        attr_name: the attribute identification object.

    Returns:
        True if the attribute needs to be resolved. Else False.
        In case of lists of references, this function return true if any of the
        references in the list needs to be resolved.
        Note: outside the model building process (from_file or from_str) this
        function always returns False.

    """
    if hasattr(get_model(parent_obj), "_tx_reference_resolver"):
        return get_model(parent_obj)._tx_reference_resolver. \
            has_unresolved_crossrefs(parent_obj, attr_name)
    else:
        return False
def person_definer_scope(knows, attr, attr_ref):
    m = get_model(knows)  # get the model of the currently processed element
    name = attr_ref.obj_name  # the name of currently looked up element
    found_persons = list(filter(lambda p: p.name == name, m.persons))
    if len(found_persons) > 0:
        return found_persons[0]  # if a person exists, return it
    else:
        mm = get_metamodel(m)  # else, create it and store it in the model
        person = mm['Person']()
        person.name = name
        person.parent = m
        m.persons.append(person)
        return person
예제 #6
0
    def apply(self, obj, lookup_list, matched_path, first_element):
        """
        Args:
            obj: model object
            lookup_list: non-empty name list

        Returns:
            The object indicated by the navigation object,
            Postponed, None, or a list (if a list has to be processed).
        """
        from textx.scoping.tools import needs_to_be_resolved
        from textx.scoping import Postponed
        if first_element:
            from textx import get_model
            obj = get_model(obj)
        if len(lookup_list) == 0 and self.consume_name:
            return None, lookup_list, matched_path
        if needs_to_be_resolved(obj, self.name):
            return Postponed(), lookup_list, matched_path
        if hasattr(obj, self.name):
            target = getattr(obj, self.name)
            if not self.consume_name and self.fixed_name is None:
                return target, lookup_list, matched_path  # return list
            else:
                if not isinstance(target, list):
                    target = [target]
                if self.fixed_name is not None:
                    lst = list(
                        filter(
                            lambda x: hasattr(x, "name") and getattr(
                                x, "name") == self.fixed_name, target))
                    if len(lst) > 0:
                        return lst[0], lookup_list, matched_path + [
                            lst[0]
                        ]  # return obj
                    else:
                        return None, lookup_list, matched_path  # return None
                else:
                    lst = list(
                        filter(
                            lambda x: hasattr(x, "name") and getattr(
                                x, "name") == lookup_list[0], target))
                    if len(lst) > 0:
                        return lst[0], lookup_list[1:], matched_path + [
                            lst[0]
                        ]  # return obj
                    else:
                        return None, lookup_list, matched_path  # return None
        else:
            return None, lookup_list, matched_path
예제 #7
0
파일: tools.py 프로젝트: nhamidn/textX
def get_location(model_obj):
    """
    Args:
        model_obj: the model object of interest

    Returns:
        the line, col and filename of the model element.
        The filename may be None.
        This function may be used to fill exceptions
    """
    the_model = get_model(model_obj)
    line, col = the_model._tx_parser.pos_to_linecol(
        model_obj._tx_position)
    return {"line": line, "col": col, "filename": the_model._tx_filename}
예제 #8
0
def get_location(model_obj):
    """
    Args:
        model_obj: the model object of interest

    Returns:
        the line, col and filename of the model element.
        The filename may be None.
        This function may be used to fill exceptions
    """
    the_model = get_model(model_obj)
    line, col = the_model._tx_parser.pos_to_linecol(
        model_obj._tx_position)
    return {"line": line, "col": col, "filename": the_model._tx_filename}
예제 #9
0
def test_issue89_get_obj_pos_in_text():
    mm = textx.metamodel_from_str('''
        Model: objs+=Obj;
        Obj: 'obj' name=ID;
    ''')
    m = mm.model_from_str('''obj A
obj B
 obj C
         obj D
    ''')
    assert (1, 1) == textx.get_model(m.objs[0])._tx_parser.pos_to_linecol(
        m.objs[0]._tx_position)

    assert (2, 1) == m._tx_parser.pos_to_linecol(m.objs[1]._tx_position)
    assert (3, 2) == m._tx_parser.pos_to_linecol(m.objs[2]._tx_position)
    assert (4, 10) == m._tx_parser.pos_to_linecol(m.objs[3]._tx_position)
 def json_scope_provider(obj, attr, attr_ref):
     if not obj.pyobj:
         from textx.scoping import Postponed
         return Postponed()
     if not hasattr(obj.pyobj, "data"):
         import json
         obj.pyobj.data = json.load(
             open(
                 os.path.join(
                     os.path.abspath(
                         os.path.dirname(get_model(obj)._tx_filename)),
                     obj.pyobj.filename)))
     if attr_ref.obj_name in obj.pyobj.data:
         return obj.pyobj.data[attr_ref.obj_name]
     else:
         raise TextXSemanticError("{} not found".format(attr_ref.obj_name))
예제 #11
0
 def __call__(self, obj, attr, obj_ref):
     from textx.scoping.tools import get_referenced_object
     from textx.scoping import Postponed
     from textx import get_model
     try:
         res = get_referenced_object(
             None, obj,
             self.path_to_container_object + "." + obj_ref.obj_name,
             obj_ref.cls)
         if type(res) is Postponed:
             self.postponed_counter += 1
         return res
     except TypeError as e:
         from textx.scoping.tools import get_parser
         line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
         raise TextXSemanticError('{}'.format(str(e)), line=line, col=col,
                                  filename=get_model(obj)._tx_filename)
예제 #12
0
def check_array_attribute(array_attribute):
    """
    check if array size depends only on attributes defined before it in the struct
    :param array_attribute:
    :return: None
    throws on error
    """
    from itemlang.itemc.metamodel_formula import ScalarRef
    dependencies = map(
        lambda x: x.ref0,
        reduce(
            lambda l1, l2: l1 + l2,
            map(lambda node: get_children_of_type(ScalarRef, node),
                array_attribute.array_dimensions), []))
    struct = array_attribute.parent
    index_of_array = struct.attributes.index(array_attribute)
    available_infos_until_this_array = struct.attributes[0:index_of_array]
    for d in dependencies:
        if not (d in available_infos_until_this_array):
            raise Exception(
                "array {}.{} depends on {}.{} not defined before it in {}.".
                format(struct.name, array_attribute.name, struct.name, d.name,
                       get_model(struct)._tx_filename))
예제 #13
0
    def __call__(self, obj, attr, obj_ref):
        from textx.model import ObjCrossRef, get_model
        assert type(obj_ref) is ObjCrossRef, type(obj_ref)
        # cls, obj_name = obj_ref.cls, obj_ref.obj_name

        # 1) lookup URIs... (first, before looking locally - to detect file
        #    not founds and distant model errors...)
        # TODO: raise error if lookup is not unique

        model = get_model(obj)
        model_repository = model._tx_model_repository

        # 1) try to find object locally
        ret = self.scope_provider(obj, attr, obj_ref)
        if ret:
            return ret

        # 2) do we have loaded models?
        for m in model_repository.local_models.filename_to_model.values():
            ret = self.scope_provider(m, attr, obj_ref)
            if ret:
                return ret
        return None
예제 #14
0
 def get_from_zero_or_more(obj, lookup_list, first_element=False):
     assert self.start_locally() or self.start_at_root()  # or, not xor
     if not allowed(obj, lookup_list, self):  # also adjusts visited objs
         return  # recursion stopper
     if first_element:
         if self.start_locally():
             yield obj, lookup_list
         if self.start_at_root():
             from textx import get_model
             yield get_model(obj), lookup_list
     else:
         yield obj, lookup_list
     assert isinstance(self.path_element.seq, RRELSequence)
     for iobj, ilookup_list in self.path_element.seq.get_next_matches(
             obj, lookup_list, allowed,
             first_element=first_element):
         if isinstance(iobj, Postponed):
             yield iobj, ilookup_list  # found postponed
             return
         # yield from
         for iiobj, iilookup_list in get_from_zero_or_more(
                 iobj, ilookup_list):
             yield iiobj, iilookup_list
예제 #15
0
    def __call__(self, obj, attr, obj_ref):
        from textx.model import ObjCrossRef, get_model
        assert type(obj_ref) is ObjCrossRef, type(obj_ref)
        # cls, obj_name = obj_ref.cls, obj_ref.obj_name

        # 1) lookup URIs... (first, before looking locally - to detect file
        #    not founds and distant model errors...)
        # TODO: raise error if lookup is not unique

        model = get_model(obj)
        model_repository = model._tx_model_repository

        # 1) try to find object locally
        ret = self.scope_provider(obj, attr, obj_ref)
        if ret:
            return ret

        # 2) do we have loaded models?
        for m in model_repository.local_models.filename_to_model.values():
            ret = self.scope_provider(m, attr, obj_ref)
            if ret:
                return ret
        return None
예제 #16
0
 def myassert(ref):
     if not ref.default_value:
         raise Exception("{}: {}.{} needs to have a default value".format(
             get_model(ref)._tx_filename, ref.parent.name, ref.name))
예제 #17
0
    def __call__(self, obj, attr, obj_ref):
        """
        the default scope provider

        Args:
            obj: unused (used for multi_metamodel_support)
            attr: unused
            obj_ref: the cross reference to be resolved

        Returns:
            the resolved reference or None
        """
        from textx.const import RULE_COMMON, RULE_ABSTRACT
        from textx.model import ObjCrossRef
        from textx.scoping.tools import get_parser

        if obj_ref is None:
            return None  # an error! (see model.py: resolve_refs (TODO check)

        assert type(obj_ref) is ObjCrossRef, type(obj_ref)

        if get_parser(obj).debug:
            get_parser(obj).dprint("Resolving obj crossref: {}:{}"
                                   .format(obj_ref.cls, obj_ref.obj_name))

        def _inner_resolve_link_rule_ref(cls, obj_name):
            """
            Depth-first resolving of link rule reference.
            """
            if cls._tx_type is RULE_ABSTRACT:
                for inherited in cls._tx_inh_by:
                    result = _inner_resolve_link_rule_ref(inherited,
                                                          obj_name)
                    if result:
                        return result
            elif cls._tx_type == RULE_COMMON:
                # TODO make this code exchangable
                # allow to know the current attribute (model location for
                # namespace) and to navigate through the whole model...
                # OR (with another scope provider) to make custom lookups in
                # the model
                #
                # Scopeprovider
                # - needs: .current reference (in the model)
                #          .the model (?)
                # - provides: the resolved object or None
                if id(cls) in get_parser(obj)._instances:
                    objs = get_parser(obj)._instances[id(cls)]
                    return objs.get(obj_name)

        if self.multi_metamodel_support:
            from textx import get_model, get_children
            from textx import textx_isinstance
            result_lst = get_children(
                lambda x:
                _hasattr(x, "name") and _getattr(x, "name") == obj_ref.obj_name
                and textx_isinstance(x, obj_ref.cls), get_model(obj))
            if len(result_lst) == 1:
                result = result_lst[0]
            elif len(result_lst) > 1:
                line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
                raise TextXSemanticError(
                    "name {} is not unique.".format(obj_ref.obj_name),
                    line=line, col=col, filename=get_model(obj)._tx_filename)
            else:
                result = None
        else:
            result = _inner_resolve_link_rule_ref(obj_ref.cls,
                                                  obj_ref.obj_name)
        if result:
            return result

        return None  # error handled outside
예제 #18
0
 def basename(self):
     exercise = self.parent
     fn = get_model(exercise)._tx_filename.\
         replace(sep, "_").\
         replace(".", "_")
     return "uml_{}_{}".format(fn, exercise.content.index(self))
예제 #19
0
    def __call__(self, obj, attr, obj_ref):
        """
        the default scope provider

        Args:
            obj: unused (used for multi_metamodel_support)
            attr: unused
            obj_ref: the cross reference to be resolved

        Returns:
            the resolved reference or None
        """
        from textx.const import RULE_COMMON, RULE_ABSTRACT
        from textx.model import ObjCrossRef
        from textx.scoping.tools import get_parser

        if obj_ref is None:
            return None  # an error! (see model.py: resolve_refs (TODO check)

        assert type(obj_ref) is ObjCrossRef, type(obj_ref)

        if get_parser(obj).debug:
            get_parser(obj).dprint("Resolving obj crossref: {}:{}"
                                   .format(obj_ref.cls, obj_ref.obj_name))

        def _inner_resolve_link_rule_ref(cls, obj_name):
            """
            Depth-first resolving of link rule reference.
            """
            if cls._tx_type is RULE_ABSTRACT:
                for inherited in cls._tx_inh_by:
                    result = _inner_resolve_link_rule_ref(inherited,
                                                          obj_name)
                    if result:
                        return result
            elif cls._tx_type == RULE_COMMON:
                # TODO make this code exchangable
                # allow to know the current attribute (model location for
                # namespace) and to navigate through the whole model...
                # OR (with another scope provider) to make custom lookups in
                # the model
                #
                # Scopeprovider
                # - needs: .current reference (in the model)
                #          .the model (?)
                # - provides: the resolved object or None
                if id(cls) in get_parser(obj)._instances:
                    objs = get_parser(obj)._instances[id(cls)]
                    return objs.get(obj_name)

        if self.multi_metamodel_support:
            from textx import get_model, get_children
            from textx import textx_isinstance
            result_lst = get_children(
                lambda x:
                hasattr(x, "name") and x.name == obj_ref.obj_name
                and textx_isinstance(x, obj_ref.cls), get_model(obj))
            if len(result_lst) == 1:
                result = result_lst[0]
            elif len(result_lst) > 1:
                line, col = get_parser(obj).pos_to_linecol(obj_ref.position)
                raise TextXSemanticError(
                    "name {} is not unique.".format(obj_ref.obj_name),
                    line=line, col=col, filename=get_model(obj)._tx_filename)
            else:
                result = None
        else:
            result = _inner_resolve_link_rule_ref(obj_ref.cls,
                                                  obj_ref.obj_name)
        if result:
            return result

        return None  # error handled outside
예제 #20
0
파일: rrel.py 프로젝트: textX/textX
    def apply(self, obj, lookup_list, matched_path, first_element):
        """
        Args:
            obj: model object
            lookup_list: non-empty name list

        Returns:
            The object indicated by the navigation object,
            Postponed, None, or a list (if a list has to be processed).
        """
        assert self.rrel_expression is not None
        from textx.scoping.tools import needs_to_be_resolved
        from textx.scoping import Postponed
        if first_element:
            from textx import get_model
            obj = get_model(obj)

        start = [obj]
        if not hasattr(obj, "parent"):  # am I a root model node?
            if self.rrel_expression.importURI:
                if hasattr(obj, "_tx_model_repository"):
                    for m in obj._tx_model_repository.local_models:
                        start.append(m)
                if obj._tx_metamodel.builtin_models:
                    for m in obj._tx_metamodel.builtin_models:
                        start.append(m)

        if len(lookup_list) == 0 and self.consume_name:
            return None, lookup_list, matched_path

        def lookup(obj):
            if needs_to_be_resolved(obj, self.name):
                return Postponed(), lookup_list, matched_path
            if hasattr(obj, self.name):
                target = getattr(obj, self.name)
                if not self.consume_name and self.fixed_name is None:
                    return target, lookup_list, matched_path  # return list
                else:
                    if not isinstance(target, list):
                        target = [target]
                    if self.fixed_name is not None:
                        lst = list(
                            filter(
                                lambda x: hasattr(x, "name") and getattr(
                                    x, "name") == self.fixed_name, target))
                        if len(lst) > 0:
                            return lst[0], lookup_list, matched_path + [
                                lst[0]
                            ]  # return obj
                        else:
                            return None, lookup_list, matched_path  # return None
                    else:
                        lst = list(
                            filter(
                                lambda x: hasattr(x, "name") and getattr(
                                    x, "name") == lookup_list[0], target))
                        if len(lst) > 0:
                            return lst[0], lookup_list[1:], matched_path + [
                                lst[0]
                            ]  # return obj
                        else:
                            return None, lookup_list, matched_path  # return None
            else:
                return None, lookup_list, matched_path

        for start_obj in start:
            res, res_lookup_list, res_lookup_path = lookup(start_obj)
            if (res):
                return res, res_lookup_list, res_lookup_path

        return None, lookup_list, matched_path
예제 #21
0
 def get_filename(self):
     return join(abspath(dirname(get_model(self)._tx_filename)), self.file)
예제 #22
0
파일: common.py 프로젝트: goto40/mdsd
def obj_is_newer_than_file(obj, filename):
    if not exists(filename):
        return True
    date = getmtime(filename)
    return obj_is_newer_than_date(get_model(obj), date)
예제 #23
0
 def basename(self, relative_to):
     n = relpath(
         get_model(self)._tx_filename,
         dirname(get_model(relative_to)._tx_filename))
     return n.replace(".exercise", "").replace(sep, ".")
예제 #24
0
def check_raw_type_has_defined_bits(rawtype):
    if rawtype.genericType != "custom" and not rawtype.genericBits:
        raise Exception("Bits need to be specified for {} in {}".format(
            rawtype.name,
            get_model(rawtype)._tx_filename))
예제 #25
0
 def get_name(self):
     return basename(get_model(self)._tx_filename).replace(".exam", "")
예제 #26
0
파일: test_rrel.py 프로젝트: textX/textX
def test_rrel_basic_lookup():
    """
    This is a basic test for the find function:
    we use a model with some structure
    and query this structure with RREL expressions.
    """
    #################################
    # META MODEL DEF
    #################################

    my_metamodel = metamodel_from_str(metamodel_str)

    #################################
    # MODEL PARSING
    #################################

    my_model = my_metamodel.model_from_str(modeltext)

    #################################
    # TEST
    #################################

    P2 = find(my_model, "P2", "packages")
    assert P2.name == "P2"
    Part2 = find(my_model, "P2.Part2", "packages.classes")
    assert Part2.name == "Part2"
    rec = find(my_model, "P2.Part2.rec", "packages.classes.attributes")
    rec_with_fixed_name = find(my_model, "P2.rec",
                               "packages.'Part2'~classes.attributes")
    assert rec_with_fixed_name is rec
    assert rec.name == "rec"
    assert rec.parent == Part2

    P2 = find(my_model, "P2", "(packages)")
    assert P2.name == "P2"

    from textx import get_model
    assert get_model(my_model) is my_model

    P2 = find(my_model, "P2", "packages*")
    assert P2.name == "P2"
    Part2 = find(my_model, "P2.Part2", "packages*.classes")
    assert Part2.name == "Part2"
    rec = find(my_model, "P2.Part2.rec", "packages*.classes.attributes")
    assert rec.name == "rec"
    assert rec.parent == Part2

    Part2_tst = find(rec, "", "..")
    assert Part2_tst is Part2

    P2_from_inner_node = find(rec, "P2", "(packages)")
    assert P2_from_inner_node is P2

    P2_tst = find(rec, "", "parent(Package)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "...")
    assert P2_tst is P2

    P2_tst = find(rec, "", ".(..).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "(..).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "...(.).(.)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "..(.).(..)")
    assert P2_tst is P2

    P2_tst = find(rec, "", "..((.)*)*.(..)")
    assert P2_tst is P2

    none = find(my_model, "", "..")
    assert none is None

    m = find(my_model, "", ".")  # '.' references the current element
    assert m is my_model

    inner = find(my_model, "inner", "~packages.~packages.~classes.attributes")
    assert inner.name == "inner"

    package_Inner = find(inner, "Inner", "parent(OBJECT)*.packages")
    assert textx_isinstance(package_Inner, my_metamodel["Package"])
    assert not textx_isinstance(package_Inner, my_metamodel["Class"])

    assert None is find(inner, "P2", "parent(Class)*.packages")

    # expensive version of a "Plain Name" scope provider:
    inner = find(my_model, "inner", "~packages*.~classes.attributes")
    assert inner.name == "inner"

    rec2 = find(my_model, "P2.Part2.rec",
                "other1,other2,packages*.classes.attributes")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec",
                "other1,packages*.classes.attributes,other2")
    assert rec2 is rec

    rec2 = find(my_model,
                "P2::Part2::rec",
                "other1,packages*.classes.attributes,other2",
                split_string="::")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec", "other1,other2,other3")
    assert rec2 is None

    rec2 = find(my_model, "P2.Part2.rec", "(packages,classes,attributes)*")
    assert rec2 is rec

    rec2 = find(my_model, "P2.Part2.rec",
                "(packages,(classes,attributes)*)*.attributes")
    assert rec2 is rec

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*")
    assert rec2.name == "rec"

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["OBJECT"])
    assert rec2.name == "rec"

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Attribute"])
    assert rec2 is rec

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Package"])
    assert rec2 is None

    rec2 = find(my_model, "rec", "(~packages,classes,attributes,~classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    rec2 = find(my_model, "rec", "(~packages,~classes,attributes,classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    t = find(my_model, "", ".")
    assert t is my_model

    t = find(my_model, "", "(.)")
    assert t is my_model

    t = find(my_model, "", "(.)*")
    assert t is my_model

    t = find(my_model, "", "(.)*.no_existent")  # inifite recursion stopper
    assert t is None

    rec2 = find(my_model, "rec",
                "(.)*.(~packages,~classes,attributes,classes)*",
                my_metamodel["Class"])
    assert rec2.name == "rec"
    assert rec2 is not rec  # it is the class...

    # Here, we test the start_from_root/start_locally logic:
    P2t = find(rec, "P2", "(.)*.packages")
    assert P2t is None
    P2t = find(rec, "P2", "(.,not_existent_but_root)*.packages")
    assert P2t is P2
    rect = find(rec, "rec", "(~packages)*.(..).attributes")
    assert rect is None
    rect = find(rec, "rec", "(.,~packages)*.(..).attributes")
    assert rect is rec