示例#1
0
def pytest_configure(config):
    this_folder = abspath(dirname(__file__))

    mm = metamodel_for_language("item")
    assert mm is not None
    inpath = join(this_folder, "tests/model/*.item")

    outpath = join(this_folder, "src-gen")
    sys.path.append(outpath)  # add generated code to python path

    mm2 = metamodel_for_language("algo")
    assert mm2 is not None
    inpath2 = join(this_folder, "tests/model/*.algo")

    if exists(outpath):
        rmtree(outpath)
    mkdir(outpath)

    for f in glob(inpath, recursive=True):
        model = mm.model_from_file(f)
        assert model is not None
        gen = generator_for_language_target("item", "python")
        gen(mm, model, output_path=outpath, overwrite=True, debug=False)

    for f in glob(inpath2, recursive=True):
        model = mm2.model_from_file(f)
        assert model is not None
        gen = generator_for_language_target("algo", "python")
        gen(mm2, model, output_path=outpath, overwrite=True, debug=False)
def test_multi_metamodel_references_with_importURI():
    # Use a global repo.
    # This is useful, especially with circular includes or diamond shaped
    # includes. Without such a repo, you might get double instantiations of
    # model elements.
    # However, if B includes A, but A not B, both meta models might have
    # global repos on their own (global between model files of the same
    # meta model --> global_repository=True). Circular dependencies
    # will require shared grammars, like in test_metamodel_provider3.py,
    # because it is not possible to share meta models for referencing, before
    # the meta model is constructed (like in our example, mm_A cannot
    # reference mm_B, if mm_B already references mm_A because one has to
    # constructed first).

    register_languages()

    # Create two meta models with the global repo.
    # The second meta model allows referencing the first one.
    mm_A = metamodel_for_language('A')
    mm_B = metamodel_for_language('BwithImport')

    # load a model from B which includes a model from A.
    current_dir = os.path.dirname(__file__)
    model = mm_B.model_from_file(os.path.join(current_dir, 'multi_metamodel',
                                              'refs', 'b.b'))

    # check that the classes from the correct meta model are used
    # (and that the model was loaded).
    assert model.b[0].__class__ == mm_B[model.b[0].__class__.__name__]
    assert model.b[0].a.__class__ == mm_A[model.b[0].a.__class__.__name__]
def test_multi_metamodel_references_with_importURI():
    # Use a global repo.
    # This is useful, especially with circular includes or diamond shaped
    # includes. Without such a repo, you might get double instantiations of
    # model elements.
    # However, if B includes A, but A not B, both meta models might have
    # global repos on their own (global between model files of the same
    # meta model --> global_repository=True). Circular dependencies
    # will require shared grammars, like in test_metamodel_provider3.py,
    # because it is not possible to share meta models for referencing, before
    # the meta model is constructed (like in our example, mm_A cannot
    # reference mm_B, if mm_B already references mm_A because one has to
    # constructed first).

    register_languages()

    # Create two meta models with the global repo.
    # The second meta model allows referencing the first one.
    mm_A = metamodel_for_language('A')
    mm_B = metamodel_for_language('BwithImport')

    # load a model from B which includes a model from A.
    current_dir = os.path.dirname(__file__)
    model = mm_B.model_from_file(
        os.path.join(current_dir, 'multi_metamodel', 'refs', 'b.b'))

    # check that the classes from the correct meta model are used
    # (and that the model was loaded).
    assert model.b[0].__class__ == mm_B[model.b[0].__class__.__name__]
    assert model.b[0].a.__class__ == mm_A[model.b[0].a.__class__.__name__]
示例#4
0
def test_metamodel_for_language_with_params(language_registered):
    """
    Test that passing in kwargs to `metamodel_for_language` call will create a
    brand new meta-model while the old instance will be returned if no `kwargs`
    are given.
    """
    class MyModel:
        pass

    mm = metamodel_for_language('test-lang',
                                ignore_case=True,
                                classes=[MyModel])
    assert mm.ignore_case
    assert 'MyModel' in mm.user_classes

    # Now we can call without kwargs and we still get the same instance
    mm2 = metamodel_for_language('test-lang')
    assert mm is mm2

    # But, passing kwargs again creates a new meta-model
    mm3 = metamodel_for_language('test-lang',
                                 ignore_case=False,
                                 classes=[MyModel])
    assert not mm3.ignore_case
    assert 'MyModel' in mm.user_classes
示例#5
0
def test_issue196_errors_in_scope_provider_and_obj_processor():
    mmF = metamodel_for_language('flow-dsl')

    # print("-----------------------------------1---")
    # print(metamodel_for_language('flow-dsl').
    #      _tx_model_repository.all_models.filename_to_model.keys())

    cached_model_count = len(
        metamodel_for_language(
            'flow-dsl')._tx_model_repository.all_models.filename_to_model)

    with pytest.raises(TextXError, match=r'.*types must be lowercase.*'):
        mmF.model_from_file(
            os.path.join(current_dir, 'models',
                         'MODEL_WITH_IMPORT_ERROR.eflow'))

    # print("-----------------------------------2---")
    # print(metamodel_for_language('flow-dsl').
    #      _tx_model_repository.all_models.filename_to_model.keys())

    # error while reading, no file cached (cached_model_count unchanged)!
    assert cached_model_count == len(
        metamodel_for_language(
            'flow-dsl')._tx_model_repository.all_models.filename_to_model)

    with pytest.raises(TextXError,
                       match=r'.*Unknown object "A" of class "Algo".*'):
        print("loading MODEL_WITH_TYPE_ERROR")
        mmF.model_from_file(
            os.path.join(current_dir, 'models', 'MODEL_WITH_TYPE_ERROR.eflow'))

    # print("-----------------------------------3---")
    # print(metamodel_for_language('flow-dsl').
    #      _tx_model_repository.all_models.filename_to_model.keys())

    # error while reading, no file cached! (cached_model_count unchanged)!
    assert cached_model_count == len(
        metamodel_for_language(
            'flow-dsl')._tx_model_repository.all_models.filename_to_model)

    with pytest.raises(TextXError, match=r'.*types must be lowercase.*'):
        mmF.model_from_file(
            os.path.join(current_dir, 'models',
                         'MODEL_WITH_IMPORT_ERROR.eflow'))

    # error while reading, no file cached! (cached_model_count unchanged)!
    assert cached_model_count == len(
        metamodel_for_language(
            'flow-dsl')._tx_model_repository.all_models.filename_to_model)
示例#6
0
def test_lang_config():
    this_folder = dirname(abspath(__file__))
    mm = metamodel_for_language('recipe-config')
    model = mm.model_from_file(
        join(this_folder, 'demos', 'config', 'settings.config'))
    assert model is not None
    assert model.name == 'german'
示例#7
0
def test_experiment_structure():
    """
    Test full experiment structure
    """

    mm = metamodel_for_language('pyflies')

    m = mm.model_from_file(join(this_folder, 'TestModel.pf'))
    assert len(m.routine_types) == 3
    assert m.routine_types[1].__class__.__name__ == 'ScreenType'
    assert m.description == 'Model for testing purposes.\n'
    assert len(m.flow.block.statements) == 4

    # Practice run
    ptest = m.flow.block.statements[1]
    assert [x.value.eval() for x in ptest.what.args if x.name == 'practice'][0]
    assert ptest.times is None and ptest._with is None

    # Block repeat
    rtest = m.flow.block.statements[2]
    assert rtest.times.eval() == 3
    assert not rtest.what.random

    # Inner test
    itest = rtest.what.statements[1]
    assert itest.times.eval() == 5

    # Random repeat
    rtest = m.flow.block.statements[3]
    assert rtest.times.eval() == 2
    assert rtest.what.random
示例#8
0
def test_property2():
    text = r"""
    package example.one (property_set example.one.ProjExt)
    property_set ProjExt {
        property optional myprop1: STRING
        property applicable for rawtype, enum myprop2: ATTRTYPE
    }
    struct A {
        scalar x: built_in.int32 (.description="a", .myprop2=1)
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 1

    pdefs = get_all_possible_properties(items[0].attributes[0])
    assert len(pdefs) >= 7

    assert "minValue" in pdefs
    assert "maxValue" in pdefs
    assert "defaultValue" in pdefs
    assert "description" in pdefs
    assert "myprop1" in pdefs
    assert "myprop2" in pdefs
    pdefs["myprop1"].internaltype == "STRING"
    pdefs["myprop2"].internaltype == "ATTRTYPE"

    pdefs = get_all_possible_mandatory_properties(items[0].attributes[0])
    assert len(pdefs) == 1
    assert "myprop2" in pdefs
示例#9
0
def test_is_dynamic():
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_file(
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), "model", "big_example.item"
        )
    )
    assert model is not None

    Color = next(
        filter(lambda x: x.name == "Color", get_children_of_type("Struct", model))
    )
    assert Color.name == "Color"
    assert not is_dynamic(Color.attributes[0])
    assert not is_dynamic(Color)

    MultiMessage = next(
        filter(
            lambda x: x.name == "MultiMessage", get_children_of_type("Struct", model)
        )
    )
    assert MultiMessage.name == "MultiMessage"
    assert is_dynamic(MultiMessage)

    Polygon = next(
        filter(lambda x: x.name == "Polygon", get_children_of_type("Struct", model))
    )
    assert Polygon.name == "Polygon"
    assert not is_dynamic(Polygon.attributes[0])
    assert is_dynamic(Polygon.attributes[1])
    assert not is_dynamic(Polygon.attributes[2])
    assert is_dynamic(Polygon)
示例#10
0
def test_conditions_table():

    mm = metamodel_for_language('pyflies')

    m = mm.model_from_str('''
    test Test {
        | position | color | congruency  | response |
        |----------+-------+-------------+----------|
        | left     | green | congruent   | left     |
        | left     | red   | incongruent | right    |
        | right    | green | incongruent | left     |
        | right    | red   | congruent   | right    |
    }
    flow {
        execute Test
    }
    ''')

    # We have 4 rows in the table
    assert m.routine_types[0].table_spec.variables == ['position', 'color',
                                                       'congruency', 'response']

    red = m.flow.insts[0].table[1][1]
    assert type(red) is Symbol
    assert red.name == 'red'
示例#11
0
def test_attr_formula1():
    text = r"""
    package example
    struct Image {
      scalar w: built_in.uint32  (.defaultValue=1, .maxValue=1000)
      scalar h: built_in.uint32  (.defaultValue=1, .maxValue=1000)
      array pixel : built_in.float[w*h]
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 1

    model._tx_filename = "example.item"
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")
    gen2 = generator_for_language_target("item", "python")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)
    gen2(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "example", "Image.h")).read()
    print(cpp_code)
    assert "struct Image" in cpp_code
    assert "s.w*s.h" in cpp_code
示例#12
0
def test_props_load_and_import():
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_file(
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), "model", "props_example.item"
        )
    )
    assert model is not None

    model._tx_filename = "example.item"
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "example", "X.h")).read()
    print(cpp_code)
    assert "minValue" in cpp_code
    assert "maxValue" in cpp_code
    assert "myprop1" in cpp_code
    assert "myprop2" in cpp_code
    assert "myprop3" not in cpp_code
示例#13
0
def test_attr_ref2():
    text = r"""
    package example
    struct Point {
      scalar x : built_in.float
      scalar y : built_in.float
    }
    struct Header {
      scalar n : built_in.uint32 (.maxValue=100, .defaultValue=1)
      scalar nb_bytes: built_in.uint32
    }
    struct Polygon {
      scalar header: Header
      array points : Point[header.n]
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 3

    assert not items[2].attributes[1].has_fixed_size()
    Header = items[1]
    Polygon = items[2]
    r = get_children_of_type("AttrRef", Polygon.attributes[1])
    assert len(r) == 1
    assert r[0].ref == Header.attributes[0]
示例#14
0
def test_components_param_type_referencing_and_default():
    """
    Test that component instances can reference component and param types and
    that if param is not set the default value will be applied.
    """
    mm = metamodel_for_language('pyflies')

    m = mm.model_from_file(join(this_folder, 'test_component_parameters.pf'))

    t = m.routine_types[0]

    comp_time = t.components_cond[0].comp_times[0]

    comp_type = comp_time.component.type
    assert comp_type.name == 'cross'

    # Check default values for parameters
    table = m.flow.insts[0].table
    trial = table.rows[0]
    comp_inst = trial.ph_exec[0].component
    assert comp_inst.spec.type.name == 'circle'
    # Given values
    assert comp_inst.radius == 100
    assert comp_inst.position.y == 40
    # Default values defined in abstract "visual" component
    assert comp_inst.color == '#ffffff'
    assert comp_inst.fillColor == '#ffffff'
    assert comp_inst.size == 20
示例#15
0
def pyflies_language():
    "A language for psychology experiments specification"

    builtin_models = scoping.ModelRepository()
    cmm = metamodel_for_language('pyflies-comp')
    component_folder = join(dirname(pyflies.__file__), '..', 'components')

    for comp_file in os.listdir(component_folder):
        cm = cmm.model_from_file(join(component_folder, comp_file))
        reduce_exp(cm)
        builtin_models.add_model(cm)

    mm = metamodel_from_file(join(current_dir, 'pyflies.tx'),
                             autokwd=True,
                             classes=pyflies_classes,
                             builtin_models=builtin_models)

    mm.model_param_defs.add("group",
                            "A group identifier used in counterbalancing")

    # Here if necessary register object processors or scope providers
    # http://textx.github.io/textX/stable/metamodel/#object-processors
    # http://textx.github.io/textX/stable/scoping/
    mm.register_model_processor(processor)

    return mm
示例#16
0
def test_conditions_table_expansion():
    """
    Test that iterations and loops are expanded properly.
    """

    mm = metamodel_for_language('pyflies')

    m = mm.model_from_str('''
    positions = [left, right]
    colors = [green, red]

    test First {
        // Unexpanded table with loops
        | position       | color       | response  |
        |----------------+-------------+-----------|
        | positions loop | colors loop | positions |
    }

    test First_exp {

        // This should be the result of expansion
        | position | color | response |
        |----------+-------+----------|
        | left     | green | left     |
        | left     | red   | right    |
        | right    | green | left     |
        | right    | red   | right    |
    }

    test Second {
        // Lets change order a bit. Make color top loop and position inner loop
        | color       | response  | position       |
        |-------------+-----------+----------------|
        | colors loop | positions | positions loop |
    }

    test Second_exp {
        // This should be the result of expansion
        | color | response | position |
        |-------+----------+----------|
        | green | left     | left     |
        | green | right    | right    |
        | red   | left     | left     |
        | red   | right    | right    |
    }

    flow {
        execute First
        execute First_exp
        execute Second
        execute Second_exp
    }
    ''')

    # position and color will loop making color a nested loop of the position
    # response will cycle
    assert m.flow.insts[0].table == m.flow.insts[1].table

    # In this case position is inner loop of color. response still cycles.
    assert m.flow.insts[2].table == m.flow.insts[3].table
示例#17
0
def test_conditions_table_no_loop_expansion():
    """
    Test that iterations without loops are expanded properly.
    """

    mm = metamodel_for_language('pyflies')

    m = mm.model_from_str('''
    positions = [left, right]
    colors = [green, red, blue]

    test Test {
        // Unexpanded table with iterations only
        | position | color  | response  |
        |----------+--------+-----------|
        | (0, 10)  | colors | positions |
    }
    flow {
        execute Test
    }
    ''')
    assert str(m.flow.insts[0].table) == \
        '''
| position | color | response |
|----------+-------+----------|
| (0, 10)  | green | left     |
| (0, 10)  | red   | right    |
| (0, 10)  | blue  | left     |

        '''.strip()
示例#18
0
def test_metamodel_callable_must_return_a_metamodel():
    """
    Test that meta-model callable must return an instance of TextXMetaModel.
    """
    def invalid_metamodel_callable():
        return 42

    clear_language_registrations()
    register_language('test-lang',
                      pattern='*.test',
                      description='test-lang description',
                      metamodel=invalid_metamodel_callable)

    with pytest.raises(TextXRegistrationError,
                       match='.*Meta-model type for language.*'):
        metamodel_for_language('test-lang')
示例#19
0
def test_conditions_table_no_loop_no_sequence_expansion():
    """
    Test that iterations without loops and sequences are expanded properly.
    """

    mm = metamodel_for_language('pyflies')

    m = mm.model_from_str('''
    test Test {
        // Unexpanded table without loops and sequences
        | position | color | response |
        |----------+-------+----------|
        | (0, 10)  | 2 + 4 | 6 - 2    |
        | (0, 10)  | 2 + 5 | 6 - 2    |
    }
    flow { execute Test }
    ''')
    assert str(m.flow.insts[0].table) == \
        '''
| position | color | response |
|----------+-------+----------|
| (0, 10)  | 6     | 4        |
| (0, 10)  | 7     | 4        |

        '''.strip()
示例#20
0
def test_big_example():
    mm = metamodel_for_language("item")
    assert mm is not None

    inpath = join(this_folder, "model")

    model = mm.model_from_file(join(inpath, "big_example.item"))
    assert model is not None

    outpath = join(this_folder, "src-gen")
    gen = generator_for_language_target("item", "cpp_v2")

    if exists(outpath):
        rmtree(outpath)
    mkdir(outpath)
    gen(mm, model, output_path=outpath, overwrite=True, debug=False)

    refpath = join(inpath, "ref")

    structs = get_children_of_type("Struct", model)
    enums = get_children_of_type("Enum", model)
    constants = get_children_of_type("Constants", model)

    for s in structs + enums + constants:
        outputfile = output_filename(refpath, s, "regex_ref")
        if exists(outputfile):
            check_file(
                filename=output_filename(outpath, s),
                regex_reference_filename=outputfile,
            )
示例#21
0
def test_constants1():
    text = """
    package abc
    constants MyConstants (.description = "example")
    {
        constant c1: built_in.uint32 = 1 (.description = "constant")
        constant c2: built_in.float = 3.4 (.description = "constant")
    }
    struct Test1 {
        constant c3: built_in.uint32 = 1 (.description = "constant")
        scalar a: built_in.uint32 (.defaultValue = 3*MyConstants.c1)
        scalar b: built_in.uint32 (.defaultValue = c3)
    }
    constants MyConstants2 (.description = "example")
    {
        constant c1: built_in.uint32 = MyConstants.c1 (.description = "constant")
    }
    struct Test2 {
        scalar a: built_in.uint32 (.defaultValue = 3*Test1.c3)
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    assert len(model.package.constants) == 2
    assert len(model.package.constants[0].constant_entries) == 2
    assert model.package.constants[0].constant_entries[0].name == "c1"
    assert model.package.constants[0].constant_entries[1].name == "c2"

    refs = get_referenced_elements_of_constants(model.package.constants[1])
    assert len(refs) == 1
示例#22
0
def test_flow_dsl_types_validation(clear_all):
    """
    Test flow model including error raises error.
    """

    # print("-----------------------------------1---")
    # print(metamodel_for_language('flow-dsl')._tx_model_repository.all_models.filename_to_model.keys())
    # print("----------------- #={}".format(
    #    len(metamodel_for_language('flow-dsl')._tx_model_repository.all_models.filename_to_model.keys())))
    mmF = metamodel_for_language('flow-dsl')
    with pytest.raises(TextXSyntaxError, match=r'.*lowercase.*'):
        mmF.model_from_file(
            os.path.join(current_dir, 'models',
                         'data_flow_including_error.eflow'))

    # When reading a second time, the error must be reported again:

    # print("-----------------------------------2---")
    # print(metamodel_for_language('flow-dsl')._tx_model_repository.all_models.filename_to_model.keys())
    # print("----------------- #={}".format(
    #    len(metamodel_for_language('flow-dsl')._tx_model_repository.all_models.filename_to_model.keys())))
    with pytest.raises(TextXSyntaxError, match=r'.*lowercase.*'):
        mmF.model_from_file(
            os.path.join(current_dir, 'models',
                         'data_flow_including_error.eflow'))
示例#23
0
def test_example4_load_and_import():
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_file(
        os.path.join(os.path.abspath(os.path.dirname(__file__)), "model",
                     "a.item"))
    assert model is not None
示例#24
0
def test_example1():
    text = r"""
    package P1.P2.P3
    struct Point {
      scalar x : built_in.float
      scalar y : built_in.float
    }
    struct Line {
      scalar p1 : Point
      scalar p2 : Point
    }
    struct Circle {
      scalar center : Point
      scalar radius : built_in.float
    }
    struct ColoredTriangle {
      array color : built_in.float[3]
      array points : Point[3]
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 4
示例#25
0
def test_example2():
    text = r"""
    package example
    struct Point {
      scalar x : built_in.float
      scalar y : built_in.float
    }
    struct Line {
      scalar p1 : Point
      scalar p2 : Point
    }
    struct Circle {
      scalar center : Point
      scalar radius : built_in.float
    }
    struct VariantExample {
        scalar selector: built_in.uint32
        variant payload: selector -> {
            10: Point
            11: Line
            12: Circle
        }
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 4

    refs = get_referenced_elements_of_struct(items[3])
    assert len(refs) == 3
示例#26
0
def test_metamodel_for_language(language_registered):
    """
    Test finding a meta-model for the given language name.
    """

    mm = metamodel_for_language('test-lang')
    assert isinstance(mm, TextXMetaModel)
示例#27
0
def test_example2_fail_with_nonstruct_variant():
    text = r"""
    package example
    struct Point {
      scalar x : built_in.float
      scalar y : built_in.float
    }
    struct Line {
      scalar p1 : Point
      scalar p2 : Point
    }
    struct Circle {
      scalar center : Point
      scalar radius : built_in.float
    }
    struct VariantExample {
        scalar selector: built_in.uint32
        variant payload: selector -> {
            1:  built_in.float         // not allowed
            10: Point
            11: Line
            12: Circle
        }
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    with pytest.raises(TextXSemanticError):
        mm.model_from_str(text)
示例#28
0
def test_property_in_variant_mappings():
    text = r"""
    package example

    struct Point {
      scalar x : built_in.float32
      scalar y : built_in.float32
    }

    struct Poly {
        scalar n : built_in.uint32 (.defaultValue=16, .maxValue=1000)
        array p : Point[n]
    }

    struct VariantTest {
        scalar id: built_in.uint32 (.minValue=0, .maxValue=1, .defaultValue=0)
        variant payload : id -> {
            0 : Point (.fixedSizeInBytes = 20)
            1 : Poly (.description="test2")
        } (.description="test1")
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    m = mm.model_from_str(text)
    assert m is not None
    assert len(m.package.items) == 3
示例#29
0
文件: check.py 项目: vlimmere/textX
    def check(ctx,
              model_files,
              language=None,
              grammar=None,
              ignore_case=False):
        """
        Check/validate model given its file path. If grammar is given use it to
        construct the meta-model. If language is given use it to retrieve the
        registered meta-model.

        Examples:

        \b
        # textX language is built-in, so always registered:
        textx check entity.tx

        \b
        # If the language is not registered you must provide the grammar:
        textx check person.ent --grammar entity.tx

        \b
        # or if we have language registered (see: text list-languages) it's just:
        textx check person.ent

        \b
        # Use "--language" if meta-model can't be deduced by file extension:
        textx check person.txt --language entity

        \b
        # Or to check multiple model files and deduce meta-model by extension
        textx check *

        """  # noqa

        debug = ctx.obj['debug']

        try:
            per_file_metamodel = False
            if grammar:
                metamodel = metamodel_from_file(grammar,
                                                debug=debug,
                                                ignore_case=ignore_case)
            elif language:
                metamodel = metamodel_for_language(language)
            else:
                per_file_metamodel = True

            for model_file in model_files:
                if per_file_metamodel:
                    metamodel = metamodel_for_file(model_file)

                metamodel.model_from_file(model_file, debug=debug)
                click.echo("{}: OK.".format(os.path.abspath(model_file)))

        except TextXRegistrationError as e:
            raise click.ClickException(e.message)

        except TextXError as e:
            raise click.ClickException(str(e))
def test_flow_dsl_validation(clear_all):
    mmF = metamodel_for_language('flow-dsl-s')
    this_folder = os.path.dirname(__file__)
    with raises(TextXSemanticError,
                match=r'.*algo data types must match.*'):
        mmF.model_from_file(os.path.join(this_folder,
                                         'models',
                                         'data_flow_with_error.eflow2'))
def test_data_dsl(clear_all):
    mmD = metamodel_for_language('data-dsl-s')
    this_folder = os.path.dirname(__file__)
    model = mmD.model_from_file(os.path.join(this_folder,
                                             'models',
                                             'data_structures.edata2'))
    assert(model is not None)
    assert(len(model.data) == 3)
def test_multi_metamodel_references1():

    global_repo_provider = register_languages()

    mm_A = metamodel_for_language('A')
    mA = mm_A.model_from_str('''
    A a1 A a2 A a3
    ''')
    global_repo_provider.add_model(mA)

    mm_B = metamodel_for_language('B')
    mm_B.model_from_str('''
    B b1 -> a1 B b2 -> a2 B b3 -> a3
    ''')

    with raises(textx.exceptions.TextXSemanticError,
                match=r'.*UNKNOWN.*'):
        mm_B.model_from_str('''
        B b1 -> a1 B b2 -> a2 B b3 -> UNKNOWN
        ''')
示例#33
0
def test_flow_dsl_validation(clear_all):
    """
    Test flow model with semantic error raises error.
    """

    mmF = metamodel_for_language('flow-dsl')
    with pytest.raises(TextXSemanticError,
                       match=r'.*algo data types must match.*'):
        mmF.model_from_file(os.path.join(current_dir,
                                         'models',
                                         'data_flow_with_error.eflow'))
示例#34
0
def test_types_dsl(clear_all):
    """
    Test loading of correct types model.
    """

    mmT = metamodel_for_language('types-dsl')
    model = mmT.model_from_file(os.path.join(current_dir,
                                             'models',
                                             'types.etype'))
    assert(model is not None)
    assert(len(model.types) == 2)
示例#35
0
def test_types_dsl_invalid(clear_all):
    """
    Test that types model with semantic error raises the error.
    """

    mmT = metamodel_for_language('types-dsl')
    with pytest.raises(TextXSyntaxError,
                       match=r'.*lowercase.*'):
        mmT.model_from_file(os.path.join(current_dir,
                                         'models',
                                         'types_with_error.etype'))
示例#36
0
def test_flow_dsl_types_validation(clear_all):
    """
    Test flow model including error raises error.
    """

    mmF = metamodel_for_language('flow-dsl')
    with pytest.raises(TextXSyntaxError,
                       match=r'.*lowercase.*'):
        mmF.model_from_file(os.path.join(current_dir,
                                         'models',
                                         'data_flow_including_error.eflow'))
示例#37
0
def test_flow_dsl(clear_all):
    """
    Test loading of correct flow model.
    """

    mmF = metamodel_for_language('flow-dsl')
    model = mmF.model_from_file(os.path.join(current_dir,
                                             'models',
                                             'data_flow.eflow'))
    assert(model is not None)
    assert(len(model.algos) == 2)
    assert(len(model.flows) == 1)
示例#38
0
def test_data_dsl():
    """
    Test loading of correct data dsl.
    """

    clear_language_registrations()
    current_dir = os.path.dirname(__file__)
    mmD = metamodel_for_language('data-dsl')
    model = mmD.model_from_file(os.path.join(current_dir,
                                             'models',
                                             'data_structures.edata'))
    assert(model is not None)
    assert(len(model.data) == 3)
def test_language_reference_keyword():

    @language('first-test-lang', '*.ftest')
    def first_language():
        return metamodel_from_str(
            r'''
            Model: firsts*=First;
            First: name=ID num=INT;
            ''')
    register_language(first_language)

    @language('second-test-lang', '*.stest')
    def second_language():
        # We can reference here fist-test-lang since it is registered above
        mm = metamodel_from_str(
            r'''
            reference first-test-lang as f

            Model:
                includes*=Include
                refs+=Reference;
            Reference: 'ref' ref=[f.First];
            Include: 'include' importURI=STRING;
            ''', global_repository=True)
        mm.register_scope_providers(
            {"*.*": scoping_providers.FQNImportURI()})
        return mm
    register_language(second_language)

    mm = metamodel_for_language('second-test-lang')

    current_dir = os.path.dirname(__file__)
    p = os.path.join(current_dir, 'model.stest')
    model = mm.model_from_file(p)

    assert len(model.refs) == 2
    assert model.refs[0].ref.name == 'first1'
    assert model.refs[0].ref.num == 42
 def get_metamodel():
     return metamodel_for_language('data')
示例#41
0
    def generate(ctx, model_files, output_path, language, target, overwrite,
                 grammar=None, ignore_case=False):
        """
        Run code generator on a provided model(s).

        For example::

        \b
        # Generate PlantUML output from .flow models
        textx generate mymodel.flow --target PlantUML

        \b
        # or with defined output folder
        textx generate mymodel.flow -o rendered_model/ --target PlantUML

        \b
        # To chose language by name and not by file pattern use --language
        textx generate *.flow --language flow --target PlantUML

        \b
        # Use --overwrite to overwrite target files
        textx generate mymodel.flow --target PlantUML --overwrite

        \b
        # In all above cases PlantUML generator must be registered, i.e.:
        $ textx list-generators
        flow-dsl -> PlantUML  Generating PlantUML visualization from flow-dsl

        \b
        # If the source language is not registered you can use the .tx grammar
        # file for parsing but the language name used will be `any`.
        textx generate --grammar Flow.tx --target dot mymodel.flow


        """

        debug = ctx.obj['debug']
        click.echo('Generating {} target from models:'.format(target))

        try:
            per_file_metamodel = False
            if grammar:
                metamodel = metamodel_from_file(grammar, debug=debug,
                                                ignore_case=ignore_case)
                language = 'any'
            elif language:
                metamodel = metamodel_for_language(language)
            else:
                per_file_metamodel = True

            # Find all custom arguments
            model_files = list(model_files)
            model_files_without_args = []
            custom_args = {}
            while model_files:
                m = model_files.pop(0)
                if m.startswith('--'):
                    custom_args[m[2:]] = model_files.pop(0).strip('"\'')
                else:
                    model_files_without_args.append(m)

            # Call generator for each model file
            for model_file in model_files_without_args:

                click.echo(os.path.abspath(model_file))

                if per_file_metamodel:
                    language = language_for_file(model_file).name
                    metamodel = metamodel_for_file(model_file)
                model = metamodel.model_from_file(model_file)
                generator = generator_for_language_target(
                    language, target, any_permitted=per_file_metamodel)

                generator(metamodel, model, output_path, overwrite, debug,
                          **custom_args)

        except TextXRegistrationError as e:
            click.echo(e.message)

        except TextXError as e:
            click.echo(e)
 def get_metamodel():
     return metamodel_for_language('types')
 def get_metamodel():
     return metamodel_for_language('flow')