Exemple #1
0
    def test_target_overrides_separate_namespace(self):
        conf = Config({
            "config": [
                ConfigSetting(namespace="dontchangeme",
                              name="network-default-interface-type",
                              help_text="",
                              value="WIFI"),
                ConfigSetting(namespace="changeme",
                              name="network-default-interface-type",
                              help_text="",
                              value="WIFI"),
            ]
        })

        conf.update({
            "overrides": [
                Override(namespace="changeme",
                         name="network-default-interface-type",
                         value="ETHERNET")
            ]
        })

        dontchangeme, changeme, *_ = conf["config"]
        assert changeme.namespace == "changeme"
        assert changeme.value == "ETHERNET"
        assert dontchangeme.namespace == "dontchangeme"
        assert dontchangeme.value == "WIFI"
Exemple #2
0
 def test_warns_and_skips_override_for_undefined_config_parameter(
         self, caplog):
     conf = Config()
     override_name = "this-does-not-exist"
     conf.update(prepare({"target_overrides": {"*": {override_name: ""}}}))
     assert override_name in caplog.text
     assert not conf
Exemple #3
0
    def test_target_overrides_handled(self):
        conf = Config({
            "config": [
                ConfigSetting(namespace="target",
                              name="network-default-interface-type",
                              help_text="",
                              value="WIFI")
            ],
            "device_has": ["TEST"],
        })

        conf.update({
            "overrides": [
                Override(namespace="target",
                         name="network-default-interface-type",
                         value="ETHERNET"),
                Override(namespace="target",
                         name="device_has",
                         value={"OVERRIDDEN"}),
            ]
        })

        network_iface, *_ = conf["config"]
        assert network_iface.value == "ETHERNET"
        assert conf["device_has"] == {"OVERRIDDEN"}
Exemple #4
0
    def test_macros_are_appended_to(self):
        conf = Config({"macros": {"A"}})

        conf.update({"macros": {"B"}})
        conf.update({"macros": {"B"}})

        assert conf["macros"] == {"A", "B"}
Exemple #5
0
    def test_requires_are_appended_to(self):
        conf = Config({"requires": {"A"}})

        conf.update({"requires": {"B"}})
        conf.update({"requires": {"C"}})

        assert conf["requires"] == {"A", "B", "C"}
 def from_config(cls, config: Config) -> "FileFilterData":
     """Extract file filters from a Config object."""
     return cls(
         labels=config.get("labels", set())
         | config.get("extra_labels", set()),
         features=set(config.get("features", set())),
         components=set(config.get("components", set())),
         requires=set(config.get("requires", set())),
     )
Exemple #7
0
    def test_lib_overrides_handled(self):
        conf = Config(
            {
                "config": [
                    ConfigSetting(namespace="lib", name="network-default-interface-type", help_text="", value="WIFI")
                ],
            }
        )

        conf.update({"overrides": [Override(namespace="lib", name="network-default-interface-type", value="ETHERNET")]})

        network_iface, *_ = conf["config"]
        assert network_iface.value == "ETHERNET"
Exemple #8
0
    def test_raises_when_trying_to_add_duplicate_config_setting(self):
        conf = Config(
            prepare({"config": {
                "param": {
                    "value": 0
                }
            }}, source_name="lib"))

        with pytest.raises(ValueError, match="lib.param already defined"):
            conf.update(
                prepare({"config": {
                    "param": {
                        "value": 0
                    }
                }}, source_name="lib"))
def _assemble_config_from_sources_and_lib_files(
        target_attributes: dict,
        mbed_lib_files: Iterable[Path],
        mbed_app_file: Optional[Path] = None) -> Config:
    previous_cumulative_data = None
    target_source = Source.from_target(target_attributes)
    current_cumulative_data = CumulativeData.from_sources([target_source])
    while previous_cumulative_data != current_cumulative_data:
        current_labels = current_cumulative_data.labels | current_cumulative_data.extra_labels
        filtered_files = _filter_files(mbed_lib_files, current_labels,
                                       current_cumulative_data.features,
                                       current_cumulative_data.components)
        mbed_lib_sources = [
            Source.from_mbed_lib(file, current_labels)
            for file in filtered_files
        ]
        all_sources = [target_source] + mbed_lib_sources
        if mbed_app_file:
            all_sources = all_sources + [
                Source.from_mbed_app(mbed_app_file, current_labels)
            ]

        previous_cumulative_data = current_cumulative_data
        current_cumulative_data = CumulativeData.from_sources(all_sources)

    _update_target_attributes(target_attributes, current_cumulative_data)

    return Config.from_sources(all_sources)
Exemple #10
0
    def test_builds_config_from_sources(self):
        source_a = SourceFactory(config={
            "bool": True,
            "string": "foo"
        },
                                 macros=["MACRO_A=A"])
        source_b = SourceFactory(config={"number": 1},
                                 overrides={"bool": False},
                                 macros=["MACRO_B=B"])

        config = Config.from_sources([source_a, source_b])

        self.assertEqual(
            config.options,
            {
                "bool":
                Option.build("bool", True, source_a).set_value(
                    False, source_b),
                "number":
                Option.build("number", 1, source_b),
                "string":
                Option.build("string", "foo", source_a),
            },
        )

        self.assertEqual(
            config.macros,
            {
                "MACRO_A": Macro.build("MACRO_A=A", source_a),
                "MACRO_B": Macro.build("MACRO_B=B", source_b)
            },
        )
Exemple #11
0
    def test_keeps_old_option_data(self):
        source_a = SourceFactory(
            config={"bool": {
                "help": "A simple bool",
                "value": True
            }})
        source_b = SourceFactory(overrides={"bool": False})

        config = Config.from_sources([source_a, source_b])

        self.assertEqual(config.options["bool"].help_text, "A simple bool")
Exemple #12
0
    def test_ignores_present_option(self):
        source = SourceFactory(config={
            "mbed_component.present": {
                "help": "Mbed Component",
                "value": True
            }
        })

        config = Config.from_sources([source])

        self.assertFalse(config.options)
Exemple #13
0
    def test_cumulative_fields_can_be_modified(self):
        conf = Config({"device_has": {"FLASHING_LIGHTS"}, "macros": {"A"}})

        conf.update({
            "overrides": [
                Override(namespace="target",
                         name="device_has",
                         modifier="add",
                         value={"OTHER_STUFF"}),
                Override(namespace="target",
                         name="device_has",
                         modifier="remove",
                         value={"FLASHING_LIGHTS"}),
                Override(namespace="lib",
                         name="macros",
                         modifier="remove",
                         value={"A"}),
                Override(namespace="target",
                         name="macros",
                         modifier="add",
                         value={"B"}),
            ]
        })

        conf.update({
            "overrides": [
                Override(namespace="target",
                         name="macros",
                         modifier="add",
                         value={"B"})
            ]
        })
        assert conf["device_has"] == {"OTHER_STUFF"}
        assert conf["macros"] == {"B"}
def _assemble_config_from_sources(
        target_attributes: dict,
        mbed_lib_files: List[Path],
        mbed_app_file: Optional[Path] = None) -> Config:
    config = Config(source.prepare(target_attributes, source_name="target"))
    previous_filter_data = None
    app_data = None
    if mbed_app_file:
        # We need to obtain the file filter data from mbed_app.json so we can select the correct set of mbed_lib.json
        # files to include in the config. We don't want to update the config object with all of the app settings yet
        # as we won't be able to apply overrides correctly until all relevant mbed_lib.json files have been parsed.
        app_data = source.from_file(
            mbed_app_file,
            default_name="app",
            target_filters=FileFilterData.from_config(config).labels)
        _get_app_filter_labels(app_data, config)

    current_filter_data = FileFilterData.from_config(config)
    while previous_filter_data != current_filter_data:
        filtered_files = _filter_files(mbed_lib_files, current_filter_data)
        for config_file in filtered_files:
            config.update(
                source.from_file(config_file,
                                 target_filters=current_filter_data.labels))
            # Remove any mbed_lib files we've already visited from the list so we don't parse them multiple times.
            mbed_lib_files.remove(config_file)

        previous_filter_data = current_filter_data
        current_filter_data = FileFilterData.from_config(config)

    # Apply mbed_app.json data last so config parameters are overriden in the correct order.
    if app_data:
        config.update(app_data)

    return config
Exemple #15
0
    def test_config_updated(self):
        conf = Config()

        conf.update(prepare({"config": {"param": {"value": 0}}}, source_name="lib"))
        conf.update(prepare({"config": {"param2": {"value": 0}}}, source_name="lib2"))

        assert conf["config"][0].name == "param"
        assert conf["config"][1].name == "param2"
Exemple #16
0
    def test_ignores_present_option(self):
        source = prepare({
            "name": "mbed_component",
            "config": {
                "present": {
                    "help": "Mbed Component",
                    "value": True
                }
            }
        })

        config = Config(source)

        assert not config["config"]
    def test_returns_quoted_content(self, fake_target):
        config = Config(prepare(fake_target))

        # Add an option whose value contains quotes to the config.
        config["config"] = [
            ConfigSetting(
                name="mqtt-host",
                namespace="iotc",
                help_text="",
                value='{"mqtt.2030.ltsapis.goog", IOTC_MQTT_PORT}',
            )
        ]

        result = render_mbed_config_cmake_template(config, TOOLCHAIN_NAME,
                                                   "target_name")
        assert '"-DMBED_CONF_IOTC_MQTT_HOST={\\"mqtt.2030.ltsapis.goog\\", IOTC_MQTT_PORT}"' in result
    def test_returns_rendered_content(self, fake_target):
        config = Config(prepare(fake_target))
        result = render_mbed_config_cmake_template(config, TOOLCHAIN_NAME,
                                                   "target_name")

        for label in fake_target["labels"] + fake_target["extra_labels"]:
            assert label in result

        for macro in fake_target["features"] + fake_target["components"] + [
                TOOLCHAIN_NAME
        ]:
            assert macro in result

        for toolchain in fake_target["supported_c_libs"]:
            assert toolchain in result
            for supported_c_libs in toolchain:
                assert supported_c_libs in result

        for supported_application_profiles in fake_target[
                "supported_application_profiles"]:
            assert supported_application_profiles in result
def _assemble_config_from_sources_and_lib_files(
        target_source: Source,
        mbed_lib_files: Iterable[Path],
        mbed_app_file: Optional[Path] = None) -> Config:
    previous_cumulative_data = None
    current_cumulative_data = CumulativeData.from_sources([target_source])
    while previous_cumulative_data != current_cumulative_data:
        filtered_files = _filter_files(mbed_lib_files, current_cumulative_data)
        mbed_lib_sources = [
            Source.from_mbed_lib(file, current_cumulative_data.labels)
            for file in filtered_files
        ]
        all_sources = [target_source] + mbed_lib_sources
        if mbed_app_file:
            all_sources = all_sources + [
                Source.from_mbed_app(mbed_app_file,
                                     current_cumulative_data.labels)
            ]
        previous_cumulative_data = current_cumulative_data
        current_cumulative_data = CumulativeData.from_sources(all_sources)

    return Config.from_sources(all_sources)
    def test_assembles_config_using_all_relevant_files(self):
        target = {
            "config": {
                "foo": {
                    "value": None
                }
            },
            "macros": [],
            "labels": ["A"],
            "extra_labels": [],
            "features": ["RED"],
            "components": [],
            "c_lib": "std",
            "printf_lib": "minimal-printf",
        }
        mbed_lib_files = [
            {
                "path": Path("subdir", "FEATURE_RED", "mbed_lib.json"),
                "json_contents": {
                    "name": "red",
                    "config": {
                        "bool": {
                            "value": False
                        }
                    },
                    "target_overrides": {
                        "A": {
                            "bool": True,
                            "target.features_add": ["BLUE"],
                            "target.components_add": ["LEG"]
                        }
                    },
                    "macros": ["RED_MACRO"],
                },
            },
            {
                "path": Path("TARGET_A", "mbed_lib.json"),
                "json_contents": {
                    "name": "a",
                    "config": {
                        "number": {
                            "value": 123
                        }
                    },
                    "target_overrides": {
                        "*": {
                            "target.features_add": ["RED"]
                        }
                    },
                },
            },
            {
                "path": Path("COMPONENT_LEG", "mbed_lib.json"),
                "json_contents": {
                    "name": "leg",
                    "config": {
                        "number-of-fingers": {
                            "value": 5
                        }
                    },
                    "macros": ["LEG_MACRO"],
                },
            },
        ]
        unused_mbed_lib_file = {
            "path": Path("subdir", "FEATURE_BROWN", "mbed_lib.json"),
            "json_contents": {
                "name": "brown",
                "target_overrides": {
                    "*": {
                        "red.bool": "DON'T USE ME"
                    }
                },
                "macros": ["DONT_USE_THIS_MACRO"],
            },
        }
        mbed_app_file = {
            "path": Path("mbed_app.json"),
            "json_contents": {
                "target_overrides": {
                    "*": {
                        "target.foo": "bar"
                    }
                }
            },
        }

        with TemporaryDirectory() as directory:
            created_mbed_lib_files = create_files(directory, mbed_lib_files)
            created_mbed_app_file = create_files(directory, [mbed_app_file])[0]
            create_files(directory, [unused_mbed_lib_file])

            subject = _assemble_config_from_sources(
                target, find_files("mbed_lib.json", Path(directory)),
                created_mbed_app_file)

            mbed_lib_sources = [
                prepare(decode_json_file(Path(directory, file)),
                        target_filters=["A"])
                for file in created_mbed_lib_files
            ]
            mbed_app_source = prepare(decode_json_file(
                Path(directory, created_mbed_app_file)),
                                      target_filters=["A"])
            expected_config = Config(prepare(target, source_name="target"))
            for source in mbed_lib_sources + [mbed_app_source]:
                expected_config.update(source)

            subject["config"].sort(key=lambda x: x.name)
            expected_config["config"].sort(key=lambda x: x.name)
            assert subject == expected_config
def _get_app_filter_labels(mbed_app_data: dict, config: Config) -> None:
    requires = mbed_app_data.get("requires")
    if requires:
        config["requires"] = requires

    config.update(_get_file_filter_overrides(mbed_app_data))
Exemple #22
0
 def test_does_not_explode_on_override_keys_used_by_other_parsers(self):
     for key in CUMULATIVE_OVERRIDE_KEYS_IN_SOURCE + BOOTLOADER_OVERRIDE_KEYS_IN_SOURCE:
         with self.subTest("Ignores override key '{key}'"):
             source_a = SourceFactory()
             source_b = SourceFactory(overrides={key: "boom?"})
             Config.from_sources([source_a, source_b])
Exemple #23
0
    def test_raises_when_trying_to_override_existing_macro(self):
        source_a = SourceFactory(macros=["MACRO_A=X"])
        source_b = SourceFactory(macros=["MACRO_A=Y"])

        with self.assertRaises(ValueError):
            Config.from_sources([source_a, source_b])
Exemple #24
0
    def test_raises_when_trying_to_override_unset_option(self):
        source_a = SourceFactory(config={"bool": True})
        source_b = SourceFactory(overrides={"string": "hello"})

        with self.assertRaises(ValueError):
            Config.from_sources([source_a, source_b])
Exemple #25
0
    def test_assembles_config_using_all_relevant_files(self):
        target = {
            "config": {
                "foo": None
            },
            "macros": {},
            "labels": set("A"),
            "extra_labels": set(),
            "features": set("RED"),
            "components": set(),
            "c_lib": "std",
            "printf_lib": "minimal-printf",
        }
        mbed_lib_files = [
            {
                "path": Path("TARGET_A", "mbed_lib.json"),
                "json_contents": {
                    "name": "a",
                    "config": {
                        "number": 123
                    },
                    "target_overrides": {
                        "*": {
                            "target.features_add": ["RED"]
                        }
                    },
                },
            },
            {
                "path": Path("subdir", "FEATURE_RED", "mbed_lib.json"),
                "json_contents": {
                    "name": "red",
                    "config": {
                        "bool": False
                    },
                    "target_overrides": {
                        "A": {
                            "bool": True,
                            "target.features_add": ["BLUE"],
                            "target.components_add": ["LEG"]
                        }
                    },
                    "macros": ["RED_MACRO"],
                },
            },
            {
                "path": Path("COMPONENT_LEG", "mbed_lib.json"),
                "json_contents": {
                    "name": "leg",
                    "config": {
                        "number-of-fingers": 5
                    },
                    "macros": ["LEG_MACRO"]
                },
            },
        ]
        unused_mbed_lib_file = {
            "path": Path("subdir", "FEATURE_BROWN", "mbed_lib.json"),
            "json_contents": {
                "name": "brown",
                "target_overrides": {
                    "*": {
                        "red.bool": "DON'T USE ME"
                    }
                },
                "macros": ["DONT_USE_THIS_MACRO"],
            },
        }
        mbed_app_file = {
            "path": Path("mbed_app.json"),
            "json_contents": {
                "target_overrides": {
                    "*": {
                        "target.foo": "bar"
                    }
                }
            },
        }

        with TemporaryDirectory() as directory:
            created_mbed_lib_files = create_files(directory, mbed_lib_files)
            created_mbed_app_file = create_files(directory, [mbed_app_file])[0]
            create_files(directory, [unused_mbed_lib_file])

            subject = _assemble_config_from_sources_and_lib_files(
                target, find_files("mbed_lib.json", Path(directory)),
                created_mbed_app_file)

            mbed_lib_sources = [
                Source.from_mbed_lib(Path(directory, file), ["A"])
                for file in created_mbed_lib_files
            ]
            mbed_app_source = Source.from_mbed_app(created_mbed_app_file,
                                                   ["A"])
            expected_config = Config.from_sources(
                [Source.from_target(target)] + mbed_lib_sources +
                [mbed_app_source])

            self.assertEqual(subject, expected_config)