Skip to content

Commit

Permalink
Refactor parse_modular, docstrings and small type annotations
Browse files Browse the repository at this point in the history
- Pass only necesary data to parse_modular (the path string)

[noissue]
  • Loading branch information
pedro-psb committed Dec 11, 2023
1 parent 1a2259c commit a9d5d95
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pulp_rpm/app/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
CONTEXT="module_context",
EOL="eol_date",
OBSOLETE_BY_MODULE="obsoleted_by_module_name",
OBSOLETE_BY_STREAM="obsoleted_by_module_name",
OBSOLETE_BY_STREAM="obsoleted_by_module_stream",
)

# Mandatory fields for Modulemd types
Expand Down
23 changes: 18 additions & 5 deletions pulp_rpm/app/modulemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ def modules_packages(modules):
version.add_content(Package.objects.filter(pk__in=packages_to_add))


def split_modulemd_file(file):
def split_modulemd_file(file: str):
"""
Helper method to preserve original formatting of modulemd.
Args:
file: Absolute path to file
"""
with tempfile.TemporaryDirectory(dir=".") as tf:
decompressed_path = os.path.join(tf, "modulemd.yaml")
cr.decompress_file(file.path, decompressed_path, cr.AUTO_DETECT_COMPRESSION)
cr.decompress_file(file, decompressed_path, cr.AUTO_DETECT_COMPRESSION)
with open(decompressed_path) as modulemd_file:
for doc in modulemd_file.read().split("---"):
# strip any spaces or newlines from either side, strip the document end marking,
Expand All @@ -94,7 +97,7 @@ def check_mandatory_module_fields(module, required_fields):

def create_modulemd(modulemd, snippet):
"""
Create dict with modulemd data to can be saved to DB.
Create dict with modulemd data to be saved to DB.
"""
new_module = dict()
new_module[PULP_MODULE_ATTR.NAME] = modulemd["data"].get("name")
Expand Down Expand Up @@ -176,9 +179,12 @@ def create_modulemd_obsoletes(obsolete, snippet):
return new_obsolete


def parse_modular(file):
def parse_modular(file: str):
"""
Parse all modular metadata.
Args:
file: Absolute path to file
"""
modulemd_all = []
modulemd_defaults_all = []
Expand Down Expand Up @@ -215,7 +221,14 @@ def parse_modular(file):


class ModularYamlLoader(yaml.SafeLoader):
"""Custom Loader that preserve unquoted float in specific fields"""
"""
Custom Loader that preserve unquoted float in specific fields (see #3285).
Motivation (for customizing YAML parsing) is that libmodulemd also implement safe-quoting:
https://github.com/fedora-modularity/libmodulemd/blob/main/modulemd/tests/test-modulemd-quoting.c
This class is based on https://stackoverflow.com/a/74334992
"""

# Field to preserve (will bypass yaml casting)
PRESERVED_FIELDS = ("name", "stream", "version", "context", "arch")
Expand Down
9 changes: 7 additions & 2 deletions pulp_rpm/app/tasks/synchronizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,8 +970,13 @@ async def parse_repository_metadata(self, repomd, metadata_results):
await self.put(dc)

async def parse_modules_metadata(self, modulemd_result):
"""Parse modules' metadata which define what packages are built for specific releases."""
modulemd_all, defaults_all, obsoletes_all = parse_modular(modulemd_result)
"""
Parse modules' metadata which define what packages are built for specific releases.
Args:
modulemd_result(pulpcore.download.base.DownloadResult): downloaded modulemd file
"""
modulemd_all, defaults_all, obsoletes_all = parse_modular(modulemd_result.path)

modulemd_dcs = []

Expand Down
16 changes: 11 additions & 5 deletions pulp_rpm/tests/unit/test_modulemd.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from pulp_rpm.app.modulemd import parse_modular
from types import SimpleNamespace
import os

sample_file_data = """
Expand Down Expand Up @@ -90,10 +89,9 @@ def test_parse_modular_preserves_literal_unquoted_values_3285(tmp_path):
with open(file_name, "w") as file:
file.write(sample_file_data)

mock_obj = SimpleNamespace(path=str(file_name))
all, defaults, obsoletes = parse_modular(mock_obj)
all, defaults, obsoletes = parse_modular(file_name)

# check the first two entries
# check normal,defaults and obsoletes modulemds
kangoroo1 = all[0] # unquoted
kangoroo2 = all[1] # quoted
modulemd_defaults = defaults[0]
Expand All @@ -115,10 +113,18 @@ def test_parse_modular_preserves_literal_unquoted_values_3285(tmp_path):

# 'stream' keys which have non-scalar values (e.g. list) are parsed normally.
# Otherwise, weird results are produced (internal pyyaml objects)
assert modulemd_defaults["module"] == "avocado"
assert modulemd_defaults.get("modified") is None # not present
assert modulemd_defaults["profiles"]["stream"] == ["default"]
assert modulemd_defaults["profiles"]["5.30"] == ["default"]

# parse_modular changes the structure and key names for obsoletes
assert modulemd_obsoletes["modified"] == "2022-01-24T08:54Z"
assert modulemd_obsoletes["module_name"] == "perl"
assert modulemd_obsoletes["module_stream"] == "5.30"
assert modulemd_obsoletes["obsoleted_by_module_name"] == "5.40"
assert modulemd_obsoletes["eol_date"] == "2021-06-01T00:00Z"
assert (
modulemd_obsoletes["message"]
== "Module stream perl:5.30 is no longer supported. Please switch to perl:5.32"
)
assert modulemd_obsoletes["obsoleted_by_module_stream"] == "5.40"

0 comments on commit a9d5d95

Please sign in to comment.