diff --git a/python-scripts/metadatavalidator/README.rst b/python-scripts/metadatavalidator/README.rst index 709207fdd..9ea4eec46 100644 --- a/python-scripts/metadatavalidator/README.rst +++ b/python-scripts/metadatavalidator/README.rst @@ -79,3 +79,7 @@ recognized: * :var:`require_meta_architecture`: Requires a ```` tag or not. * :var:`valid_meta_architecture`: Lists the valid architecture names for ``/``. + + * :var:`require_meta_category`: Requires a ```` tag or not. + + * :var:`valid_meta_category`: Lists the valid category names for ``/``. \ No newline at end of file diff --git a/python-scripts/metadatavalidator/metadatavalidator.ini b/python-scripts/metadatavalidator/metadatavalidator.ini index a502e414c..540e22b3a 100644 --- a/python-scripts/metadatavalidator/metadatavalidator.ini +++ b/python-scripts/metadatavalidator/metadatavalidator.ini @@ -27,4 +27,8 @@ require_meta_platform = off # require_meta_architecture = off -valid_meta_architecture = Arm, AMD64/Intel\u00a064, POWER, IBM LinuxONE \ No newline at end of file +valid_meta_architecture = Arm, AMD64/Intel\u00a064, POWER, IBM LinuxONE + +# +require_meta_category = off +valid_meta_category = 3rd Party, Cloud, Containerization, Developer Tools, High Availability, Tuning & Performance, SAP, Security, Storage, Systems Management, Virtualization \ No newline at end of file diff --git a/python-scripts/metadatavalidator/src/metadatavalidator/checks/__init__.py b/python-scripts/metadatavalidator/src/metadatavalidator/checks/__init__.py index 6b8133c88..9505d357b 100644 --- a/python-scripts/metadatavalidator/src/metadatavalidator/checks/__init__.py +++ b/python-scripts/metadatavalidator/src/metadatavalidator/checks/__init__.py @@ -17,6 +17,7 @@ check_meta_techpartner, check_meta_platform, check_meta_architecture, + check_meta_category, ) # Keep the order. The next item is dependent on the previous item. @@ -36,5 +37,6 @@ "check_meta_techpartner", "check_meta_platform", "check_meta_architecture", + "check_meta_category", ] diff --git a/python-scripts/metadatavalidator/src/metadatavalidator/checks/check_meta.py b/python-scripts/metadatavalidator/src/metadatavalidator/checks/check_meta.py index 9a33a2fb7..6b13ff9f7 100644 --- a/python-scripts/metadatavalidator/src/metadatavalidator/checks/check_meta.py +++ b/python-scripts/metadatavalidator/src/metadatavalidator/checks/check_meta.py @@ -166,4 +166,48 @@ def check_meta_architecture(tree: etree._ElementTree, f"Unknown architecture(s) {wrong_items}. " f"Allowed are {valid_archs}." ) - print(">>>", wrong_items, valid_archs, archs) + + +def check_meta_category(tree: etree._ElementTree, + config: dict[t.Any, t.Any]): + """Checks for a element""" + root = tree.getroot() + meta = root.find("./d:info/d:meta[@name='category']", + namespaces=NAMESPACES) + required = config.get("metadata", {}).get("require_meta_category", False) + if meta is None: + if required: + raise InvalidValueError( + f"Couldn't find required meta[@name='category'] element " + f"in {root.tag}." + ) + return + + valid_cats = [ + x.strip() for x in config.get("metadata", {} + ).get("valid_meta_category", []) + if x + ] + + # Do we have children? + cats = [tag.text.strip() for tag in meta.iterchildren()] + if not cats: + raise InvalidValueError( + f"Couldn't find any child elements in meta[@name='category'] " + f"(line {meta.sourceline})." + ) + + # Are they unique? + if len(cats) != len(set(cats)): + raise InvalidValueError( + f"Duplicate categories found in meta[@name='category'] " + f"(line {meta.sourceline})." + ) + + # Do we have items that don't conform to our predefined list? + wrong_items = set(cats) - set(valid_cats) + if wrong_items: + raise InvalidValueError( + f"Unknown category(ies) {wrong_items}. " + f"Allowed are {valid_cats}." + ) \ No newline at end of file diff --git a/python-scripts/metadatavalidator/src/metadatavalidator/config.py b/python-scripts/metadatavalidator/src/metadatavalidator/config.py index fd0fa247e..9dee23582 100644 --- a/python-scripts/metadatavalidator/src/metadatavalidator/config.py +++ b/python-scripts/metadatavalidator/src/metadatavalidator/config.py @@ -107,6 +107,30 @@ def validate_and_convert_config(config: configparser.ConfigParser) -> dict[t.Any ) theconfig.setdefault("metadata", {})["require_meta_series"] = require_meta_series + # architectures + require_meta_architecture = truefalse( + theconfig.get("metadata", {}).get("require_meta_architecture", False) + ) + theconfig.setdefault("metadata", {})["require_meta_architecture"] = require_meta_architecture + try: + architectures = split.split(theconfig.get("metadata", {}).get("valid_meta_architecture", [])) + theconfig.setdefault("metadata", {})["valid_meta_architecture"] = architectures + except TypeError: + raise MissingKeyError("metadata.valid_meta_architecture") + + + # categories + require_meta_category = truefalse( + theconfig.get("metadata", {}).get("require_meta_category", False) + ) + theconfig.setdefault("metadata", {})["require_meta_category"] = require_meta_category + try: + categories = split.split(theconfig.get("metadata", {}).get("valid_meta_category", [])) + theconfig.setdefault("metadata", {})["valid_meta_category"] = categories + except TypeError: + raise MissingKeyError("metadata.valid_meta_category") + + # Store the configfiles theconfig["configfiles"] = getattr(config, "configfiles") return theconfig diff --git a/python-scripts/metadatavalidator/tests/integration/badcase1/article.xml b/python-scripts/metadatavalidator/tests/integration/badcase1/article.xml new file mode 100644 index 000000000..d766a4375 --- /dev/null +++ b/python-scripts/metadatavalidator/tests/integration/badcase1/article.xml @@ -0,0 +1,7 @@ +
+ + Test + The very long, long, long long SEO title + + +
diff --git a/python-scripts/metadatavalidator/tests/integration/badcase1/config-test.ini b/python-scripts/metadatavalidator/tests/integration/badcase1/config-test.ini new file mode 100644 index 000000000..636b78b88 --- /dev/null +++ b/python-scripts/metadatavalidator/tests/integration/badcase1/config-test.ini @@ -0,0 +1,23 @@ +[validator] +file_extension = .xml +check_root_elements = book article topic +valid_languages = en-us + +[metadata] +revhistory = 0 +require_xmlid_on_revision = 0 + +# +require_meta_title = on +meta_title_length = 55 + +# +require_meta_description = off +meta_description_length = 150 + +require_meta_architecture = off +valid_meta_architecture = Arm, AMD64/Intel\u00a064, POWER, IBM LinuxONE + +# +require_meta_category = off +valid_meta_category = 3rd Party, Cloud, Containerization, Developer Tools, High Availability, Tuning & Performance, SAP, Security, Storage, Systems Management, Virtualization \ No newline at end of file diff --git a/python-scripts/metadatavalidator/tests/integration/badcase1/test_badcase1.py b/python-scripts/metadatavalidator/tests/integration/badcase1/test_badcase1.py new file mode 100644 index 000000000..a769f5446 --- /dev/null +++ b/python-scripts/metadatavalidator/tests/integration/badcase1/test_badcase1.py @@ -0,0 +1,23 @@ +import os.path +import json +import pytest + +from metadatavalidator.cli import main + + +BASEDIR = os.path.dirname(os.path.realpath(__file__)) +RELATIVE_PATH = os.path.relpath(BASEDIR, os.getcwd()) + + +def test_case1_integration(capsys): + cli = ["--config", f"{BASEDIR}/config-test.ini", + "--format", "json", # needed to avoid formatting issues + f"{RELATIVE_PATH}/article.xml"] + + result = main(cli) + captured = capsys.readouterr() + assert result == 0 + result = json.loads(captured.out) + assert result[0]['errors'] == [] + assert result[0]['xmlfile'] == f"{RELATIVE_PATH}/article.xml" + diff --git a/python-scripts/metadatavalidator/tests/integration/goodcase1/config-test.ini b/python-scripts/metadatavalidator/tests/integration/goodcase1/config-test.ini index 08afdc93d..636b78b88 100644 --- a/python-scripts/metadatavalidator/tests/integration/goodcase1/config-test.ini +++ b/python-scripts/metadatavalidator/tests/integration/goodcase1/config-test.ini @@ -14,3 +14,10 @@ meta_title_length = 55 # require_meta_description = off meta_description_length = 150 + +require_meta_architecture = off +valid_meta_architecture = Arm, AMD64/Intel\u00a064, POWER, IBM LinuxONE + +# +require_meta_category = off +valid_meta_category = 3rd Party, Cloud, Containerization, Developer Tools, High Availability, Tuning & Performance, SAP, Security, Storage, Systems Management, Virtualization \ No newline at end of file diff --git a/python-scripts/metadatavalidator/tests/unit/checks/test_check_meta.py b/python-scripts/metadatavalidator/tests/unit/checks/test_check_meta.py index 01e9734a2..c3e51ecce 100644 --- a/python-scripts/metadatavalidator/tests/unit/checks/test_check_meta.py +++ b/python-scripts/metadatavalidator/tests/unit/checks/test_check_meta.py @@ -8,6 +8,7 @@ check_meta_techpartner, check_meta_platform, check_meta_architecture, + check_meta_category, ) from metadatavalidator.exceptions import InvalidValueError @@ -406,3 +407,19 @@ def test_check_unknown_child_meta_architecture(xmlparser): with pytest.raises(InvalidValueError, match=r".*Unknown architecture.*"): check_meta_architecture(tree, config) + + +def test_meta_category(xmlparser): + xmlcontent = """
+ + Test + + Systems Management + + + +
""" + tree = etree.ElementTree(etree.fromstring(xmlcontent, parser=xmlparser)) + config = dict(metadata=dict(require_meta_category=True, + valid_meta_category=["Systems Management"])) + assert check_meta_category(tree, config) is None \ No newline at end of file diff --git a/python-scripts/metadatavalidator/tests/unit/data/metadatavalidator.ini b/python-scripts/metadatavalidator/tests/unit/data/metadatavalidator.ini index 9dcf1e744..e9cc4c1b8 100644 --- a/python-scripts/metadatavalidator/tests/unit/data/metadatavalidator.ini +++ b/python-scripts/metadatavalidator/tests/unit/data/metadatavalidator.ini @@ -13,6 +13,20 @@ meta_title_length = 55 # require_meta_description = off meta_description_length = 150 -# + +# require_meta_series = off -valid_meta_series = Products & Solutions, Best Practices, Technical References \ No newline at end of file +valid_meta_series = Products & Solutions, Best Practices, Technical References + +# +require_meta_techpartner = off + +# +require_meta_platform = off + +# +require_meta_architecture = off +valid_meta_architecture = Arm, AMD64/Intel\u00a064, POWER, IBM LinuxONE + +require_meta_category = off +valid_meta_category = 3rd Party, Cloud, Containerization, Developer Tools, High Availability, Tuning & Performance, SAP, Security, Storage, Systems Management, Virtualization \ No newline at end of file diff --git a/python-scripts/metadatavalidator/tests/unit/test_script_config.py b/python-scripts/metadatavalidator/tests/unit/test_script_config.py index 189204547..b9dbdd7f1 100644 --- a/python-scripts/metadatavalidator/tests/unit/test_script_config.py +++ b/python-scripts/metadatavalidator/tests/unit/test_script_config.py @@ -3,8 +3,16 @@ import pytest -from metadatavalidator.config import readconfig, validate_and_convert_config, truefalse -from metadatavalidator.exceptions import MissingKeyError, MissingSectionError, NoConfigFilesFoundError +from metadatavalidator.config import ( + readconfig, + validate_and_convert_config, + truefalse, + ) +from metadatavalidator.exceptions import ( + MissingKeyError, + MissingSectionError, + NoConfigFilesFoundError, + ) def create_config(): config = ConfigParser() @@ -19,6 +27,8 @@ def create_config(): config.set("metadata", "meta_title_length", "50") config.set("metadata", "meta_description_length", "150") # + config.set("metadata", "valid_meta_architecture", "A, B, C") + config.set("metadata", "valid_meta_category", "D, E, F") setattr(config, "configfiles", None) return config @@ -49,7 +59,8 @@ def test_valid_validate_and_convert_config(): assert result.get("validator") == { "check_root_elements": ["book", "article"], "file_extension": ".xml", - "valid_languages": ["en-us", "de-de",] + "valid_languages": ["en-us", "de-de",], + # "" }