diff --git a/tests/README.md b/tests/README.md index 64ddc6e..d201ad5 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,13 +6,7 @@ with a database, so your own postgres installation is not affected at all. To run the tests, go to the main directory of the project and do -```sh -export QGIS_TEST_VERSION=latest # See https://hub.docker.com/r/qgis/qgis/tags/ -export GITHUB_WORKSPACE=$PWD # only for local execution -docker run -v ${GITHUB_WORKSPACE}:/usr/src -w /usr/src opengisch/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3' -``` - In one line, removing all containers. ```sh -QGIS_TEST_VERSION=latest GITHUB_WORKSPACE=$PWD docker run -v ${GITHUB_WORKSPACE}:/usr/src -w /usr/src opengisch/qgis:${QGIS_TEST_VERSION} sh -c 'xvfb-run pytest-3' +docker run -v $PWD:/usr/src -w /usr/src opengisch/qgis:latest sh -c 'xvfb-run pytest-3' ``` diff --git a/tests/test_toppingmaker.py b/tests/test_toppingmaker.py index 8327526..5ce3c61 100644 --- a/tests/test_toppingmaker.py +++ b/tests/test_toppingmaker.py @@ -43,6 +43,9 @@ class ToppingMakerTest(unittest.TestCase): def setUpClass(cls): """Run before all tests.""" cls.basetestpath = tempfile.mkdtemp() + cls.testdata_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "testdata" + ) cls.projecttopping_test_path = os.path.join(cls.basetestpath, "projecttopping") def test_target(self): @@ -143,9 +146,11 @@ def test_parse_project_with_mapthemes(self): # check variables variables = project_topping.variables # Anyway in practice no spaces should be used to be able to access them in the expressions like @first_variable - assert variables.get("First Variable") == "This is a test value." + assert variables.get("First Variable") + assert variables.get("First Variable")["value"] == "This is a test value." # QGIS is currently (3.29) not able to store structures in the project file. Still... - assert variables.get("Variable with Structure") == [ + assert variables.get("Variable with Structure") + assert variables.get("Variable with Structure")["value"] == [ "Not", "The", "Normal", @@ -416,11 +421,18 @@ def test_generate_files(self): "Case", ] foundVariableWithStructure = True + if variable_key == "Validation Path Variable": + assert ( + projecttopping_data["variables"][variable_key] + == "freddys_projects/this_specific_project/generic/freddys_validConfig.ini" + ) + foundVariableWithPath = True variable_count += 1 - assert variable_count == 2 + assert variable_count == 3 assert foundFirstVariable assert foundVariableWithStructure + assert foundVariableWithPath # check transaction mode with open(projecttopping_file_path) as yamlfile: @@ -471,12 +483,13 @@ def test_generate_files(self): countchecked = 0 - # there should be 21 toppingfiles: + # there should be 22 toppingfiles: # - one project topping # - 2 x 3 qlr files (two times since the layers are multiple times in the tree) # - 2 x 6 qml files (one layers with 3 styles, one layer with 2 styles and one layer with one style - and two times since the layers are multiple times in the tree) # - 2 qpt template files - assert len(target.toppingfileinfo_list) == 21 + # - 1 generic file (validation.ini) what is created by variable + assert len(target.toppingfileinfo_list) == 22 for toppingfileinfo in target.toppingfileinfo_list: self.print_info(toppingfileinfo["path"]) @@ -703,6 +716,11 @@ def _make_project_and_export_settings(self): QgsExpressionContextUtils.setProjectVariable( project, "Variable with Structure", ["Not", "The", "Normal", 815, "Case"] ) + QgsExpressionContextUtils.setProjectVariable( + project, + "Validation Path Variable", + os.path.join(self.testdata_path, "validConfig.ini"), + ) # create layouts layout = QgsPrintLayout(project) @@ -788,7 +806,13 @@ def _make_project_and_export_settings(self): export_settings.mapthemes = ["French Theme", "Robot Theme"] # define the custom variables to export - export_settings.variables = ["First Variable", "Variable with Structure"] + export_settings.variables = [ + "First Variable", + "Variable with Structure", + "Validation Path Variable", + ] + # content of this variable should be exported as toppingfile + export_settings.path_variables = ["Validation Path Variable"] # define the layouts to export export_settings.layouts = ["Layout One", "Layout Three"] diff --git a/tests/testdata/validConfig.ini b/tests/testdata/validConfig.ini new file mode 100644 index 0000000..1d2b550 --- /dev/null +++ b/tests/testdata/validConfig.ini @@ -0,0 +1,7 @@ +["PARAMETER"] +validation="on" +additionalModels="SH_ProjektdatenDB_Naturschutz_V1_0_AddChecks" + +["SH_ProjektdatenDB_Naturschutz_V1_0_AddChecks.SH_ProjektdatenDB_Naturschutz_V1_0_Validierung.v_Mitarbeitende.checkNameDuplikate"] +multiplicity="on" +type="on" diff --git a/toppingmaker/exportsettings.py b/toppingmaker/exportsettings.py index bff4966..ea9396c 100644 --- a/toppingmaker/exportsettings.py +++ b/toppingmaker/exportsettings.py @@ -88,6 +88,8 @@ def __init__(self): self.mapthemes = [] # keys of custom variables to be exported self.variables = [] + # list of variable keys that are defined as paths and should be resolved + self.path_variables = [] # names of layouts self.layouts = [] diff --git a/toppingmaker/projecttopping.py b/toppingmaker/projecttopping.py index 1eae40c..3154b7a 100644 --- a/toppingmaker/projecttopping.py +++ b/toppingmaker/projecttopping.py @@ -61,6 +61,7 @@ class ProjectTopping(QObject): LAYERDEFINITION_TYPE = "layerdefinition" LAYERSTYLE_TYPE = "layerstyle" LAYOUTTEMPLATE_TYPE = "layouttemplate" + GENERIC_TYPE = "generic" class TreeItemProperties: """ @@ -414,6 +415,8 @@ def make_items( class Variables(dict): """ A dict object of dict items describing a variable according to the variable keys listed in the ExportSettings passed on parsing the QGIS project. + The items have the keys 'name' and (optional) 'ispath' for the case that it's a path that needs to be resolved for the topping. + To define what variables are paths this needs to be set in the ExportSettings path_variables. """ def make_items( @@ -421,12 +424,41 @@ def make_items( project: QgsProject, export_settings: ExportSettings, ): + self.clear() for variable_key in export_settings.variables: + variable_item = {} + variable_value = QgsExpressionContextUtils.projectScope( project ).variable(variable_key) - self[variable_key] = variable_value or None + + # if it's defined as path variable, we have to expose it as toppingfile + if variable_key in export_settings.path_variables: + path = variable_value + if project.homePath() and not os.path.isabs(variable_value): + # if it's a saved project and the path is not absolute, make it absolute + path = os.path.join( + variable_value, project.homePath(), variable_value + ) + variable_item["value"] = path + variable_item["ispath"] = True + else: + variable_item["value"] = variable_value + + self[variable_key] = variable_item or None + + def resolved_dict(self, target: Target): + resolved_items = {} + for variable_key in self.keys(): + resolved_value = self[variable_key].get("value") + if self[variable_key].get("ispath", False): + resolved_value = target.toppingfile_link( + ProjectTopping.GENERIC_TYPE, + self[variable_key].get("value"), + ) + resolved_items[variable_key] = resolved_value + return resolved_items class Properties(dict): """ @@ -613,9 +645,9 @@ def _projecttopping_dict(self, target: Target): mapthemes_dict = dict(self.mapthemes) if mapthemes_dict: projecttopping_dict["mapthemes"] = mapthemes_dict - variables_dict = dict(self.variables) - if variables_dict: - projecttopping_dict["variables"] = variables_dict + variables_resolved_dict = self.variables.resolved_dict(target) + if variables_resolved_dict: + projecttopping_dict["variables"] = variables_resolved_dict properties_dict = dict(self.properties) if properties_dict: projecttopping_dict["properties"] = properties_dict