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__]
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
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)
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'
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
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
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)
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'
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
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
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]
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
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
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
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()
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')
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()
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, )
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
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'))
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
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
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
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)
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)
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
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 ''')
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'))
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)
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'))
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'))
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)
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')
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')