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

1"""Integration with codemetapy (to re-generate codemeta as part of somesy sync).""" 

2import contextlib 

3import logging 

4from pathlib import Path 

5 

6from importlib_metadata import version 

7 

8from ..core.models import SomesyConfig 

9from .exec import gen_codemeta 

10from .utils import cff_codemeta_tempfile, update_codemeta_file 

11 

12log = logging.getLogger("somesy") 

13 

14 

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 

21 

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 

33 

34 cmpy.metadata_from_pyproject = fixed_metadata_from_pyproject 

35 log.debug("monkeypatch codemetapy 2.5.0 -> 2.5.1") 

36 

37 

38def collect_cm_sources(conf: SomesyConfig): 

39 """Assemble list of inputs for codemetapy based on somesy config. 

40 

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 

59 

60 

61def update_codemeta(conf: SomesyConfig) -> bool: 

62 """Generate or update codemeta file based on sources that somesy supports. 

63 

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) 

68 

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)) 

74 

75 # run codemetapy 

76 with temp_cff_cm: 

77 cm_harvest = gen_codemeta(cm_sources) 

78 

79 # check output and write file if needed 

80 return update_codemeta_file(conf.codemeta_file, cm_harvest) 

81 

82 

83__all__ = ["update_codemeta"]