Coverage for src/somesy/codemeta/__init__.py: 85%
40 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-08-10 14:33 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-08-10 14:33 +0000
1"""Integration with codemetapy (to re-generate codemeta as part of somesy sync)."""
2import contextlib
3import logging
4from pathlib import Path
6from importlib_metadata import version
8from ..core.models import SomesyConfig
9from .exec import gen_codemeta
10from .utils import cff_codemeta_tempfile, update_codemeta_file
12log = logging.getLogger("somesy")
15def patch_codemetapy():
16 """Monkey-patch codemetapy (2.5.0 -> 2.5.1)."""
17 # TODO: remove once codemeta update is published)
18 if version("codemetapy") != "2.5.0":
19 return
20 from codemeta.parsers import python as cmpy
22 # https://github.com/proycon/codemetapy/blob/88098dc638e4cdfed9de6ad98002e16dfeede952/codemeta/parsers/python.py
23 def fixed_metadata_from_pyproject(pyproject):
24 """Parse metadata from pyproject.toml."""
25 if pyproject.project and "name" in pyproject.project:
26 return pyproject.project
27 elif "poetry" in pyproject.tool:
28 return pyproject.tool["poetry"]
29 elif pyproject.tool and "name" in list(pyproject.tool.values())[0]:
30 # fallback: no poetry but another tool that defines at least a name
31 return list(pyproject.tool.values())[0]
32 return None
34 cmpy.metadata_from_pyproject = fixed_metadata_from_pyproject
35 log.debug("monkeypatch codemetapy 2.5.0 -> 2.5.1")
38def collect_cm_sources(conf: SomesyConfig):
39 """Assemble list of inputs for codemetapy based on somesy config.
41 Returns files that are supported by both somesy and codemetapy and are enabled for somesy.
42 """
43 cm_sources = []
44 if (
45 not conf.no_sync_pyproject
46 and conf.pyproject_file is not None
47 and conf.pyproject_file.is_file()
48 ):
49 cm_sources.append(conf.pyproject_file)
50 # NOTE: we don't add CFF directly, because it must be handled separately
51 # NOTE: add other suitable somesy targets / codemeta sources (except CFF and codemeta) here
52 if (
53 conf.no_sync_package_json
54 and conf.package_json_file is not None
55 and conf.package_json_file.is_file()
56 ):
57 cm_sources.append(conf.package_json_file)
58 return cm_sources
61def update_codemeta(conf: SomesyConfig) -> bool:
62 """Generate or update codemeta file based on sources that somesy supports.
64 Returns True if file has been written, False if it was up to date.
65 """
66 patch_codemetapy()
67 cm_sources = collect_cm_sources(conf)
69 # if cff file is given, convert it to codemeta tempfile and pass as extra input
70 temp_cff_cm = contextlib.nullcontext(None)
71 if not conf.no_sync_cff and conf.cff_file is not None:
72 temp_cff_cm = cff_codemeta_tempfile(conf.cff_file)
73 cm_sources.append(Path(temp_cff_cm.name))
75 # run codemetapy
76 with temp_cff_cm:
77 cm_harvest = gen_codemeta(cm_sources)
79 # check output and write file if needed
80 return update_codemeta_file(conf.codemeta_file, cm_harvest)
83__all__ = ["update_codemeta"]