Coverage for src/somesy/cli/sync.py: 95%
39 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"""Sync command for somesy."""
2import logging
3from pathlib import Path
4from typing import Optional
6import typer
7from rich.pretty import pretty_repr
9from somesy.commands import sync as sync_command
10from somesy.core.core import discover_input
11from somesy.core.log import SomesyLogLevel, get_log_level, set_log_level
12from somesy.core.models import SomesyConfig, SomesyInput
14from .util import wrap_exceptions
16logger = logging.getLogger("somesy")
18app = typer.Typer()
21@app.callback(invoke_without_command=True)
22@wrap_exceptions
23def sync(
24 input_file: Path = typer.Option(
25 None,
26 "--input-file",
27 "-i",
28 exists=False,
29 file_okay=True,
30 dir_okay=False,
31 writable=True,
32 readable=True,
33 resolve_path=True,
34 help="Somesy input file path (default: .somesy.toml)",
35 ),
36 no_sync_pyproject: bool = typer.Option(
37 None,
38 "--no-sync-pyproject",
39 "-P",
40 help="Do not sync pyproject.toml file (default: False)",
41 ),
42 pyproject_file: Path = typer.Option(
43 None,
44 "--pyproject-file",
45 "-p",
46 exists=True,
47 file_okay=True,
48 dir_okay=False,
49 writable=True,
50 readable=True,
51 resolve_path=True,
52 help="Existing pyproject.toml file path (default: pyproject.toml)",
53 ),
54 no_sync_package_json: bool = typer.Option(
55 None,
56 "--sync-package-json",
57 "-J",
58 help="Do not sync package.json file (default: False)",
59 ),
60 package_json_file: Path = typer.Option(
61 None,
62 "--package-json-file",
63 "-j",
64 exists=True,
65 file_okay=True,
66 dir_okay=False,
67 writable=True,
68 readable=True,
69 resolve_path=True,
70 help="Existing package.json file path (default: package.json)",
71 ),
72 no_sync_cff: bool = typer.Option(
73 None,
74 "--no-sync-cff",
75 "-C",
76 help="Do not sync CITATION.cff file (default: False)",
77 ),
78 cff_file: Path = typer.Option(
79 None,
80 "--cff-file",
81 "-c",
82 exists=False,
83 file_okay=True,
84 dir_okay=False,
85 writable=True,
86 readable=True,
87 resolve_path=True,
88 help="CITATION.cff file path (default: CITATION.cff)",
89 ),
90 no_sync_codemeta: bool = typer.Option(
91 None,
92 "--no-sync-codemeta",
93 "-M",
94 help="Do not sync codemeta.json file",
95 ),
96 codemeta_file: Path = typer.Option(
97 None,
98 "--codemeta-file",
99 "-m",
100 exists=False,
101 file_okay=True,
102 dir_okay=False,
103 writable=True,
104 readable=True,
105 resolve_path=True,
106 help="Custom codemeta.json file path",
107 ),
108):
109 """Sync project metadata input with metadata files."""
110 # ---------------
111 # config from CLI (merged with possibly set CLI flags for logging)
112 passed_cli_args = {
113 k: v
114 for k, v in dict(
115 input_file=discover_input(input_file),
116 no_sync_cff=no_sync_cff,
117 cff_file=cff_file,
118 no_sync_pyproject=no_sync_pyproject,
119 pyproject_file=pyproject_file,
120 no_sync_package_json=no_sync_package_json,
121 package_json_file=package_json_file,
122 no_sync_codemeta=no_sync_codemeta,
123 codemeta_file=codemeta_file,
124 ).items()
125 if v is not None
126 }
127 somesy_conf = SomesyConfig(**passed_cli_args)
129 # cli_log_level is None if the user did not pass a log level (-> "default")
130 cli_log_level: Optional[SomesyLogLevel] = get_log_level()
132 if cli_log_level is not None:
133 # update log level flags if cli log level was set
134 somesy_conf.update_log_level(cli_log_level)
136 somesy_input: SomesyInput = somesy_conf.get_input()
138 if cli_log_level is None:
139 # no cli log level -> set it according to the loaded configuration
140 set_log_level(somesy_input.config.log_level())
142 logger.debug(
143 f"Combined config (Defaults + File + CLI):\n{pretty_repr(somesy_input.config)}"
144 )
145 # --------
146 run_sync(somesy_input)
149def run_sync(somesy_input: SomesyInput):
150 """Write log messages and run synchronization based on passed config."""
151 conf = somesy_input.config
152 logger.info("[bold green]Synchronizing project metadata...[/bold green]")
153 logger.info("Files to sync:")
154 if not conf.no_sync_pyproject:
155 logger.info(
156 f" - [italic]pyproject.toml[/italic]:\t[grey]{conf.pyproject_file}[/grey]"
157 )
158 if not conf.no_sync_package_json:
159 logger.info(
160 f" - [italic]package.json[/italic]:\t[grey]{conf.package_json_file}[/grey]"
161 )
162 if not conf.no_sync_cff:
163 logger.info(f" - [italic]CITATION.cff[/italic]:\t[grey]{conf.cff_file}[/grey]")
164 if not conf.no_sync_codemeta:
165 logger.info(
166 f" - [italic]codemeta.json[/italic]:\t[grey]{conf.codemeta_file}[/grey]\n"
167 )
168 # ----
169 sync_command(somesy_input)
170 # ----
171 logger.info("[bold green]Metadata synchronization completed.[/bold green]")