Skip to content

Commit a897247

Browse files
committed
update cli and add a test
1 parent f18b3ff commit a897247

3 files changed

Lines changed: 94 additions & 47 deletions

File tree

src/somesy/cli/sync.py

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import logging
44
from pathlib import Path
5+
from typing import List, Optional
56

67
import typer
78

@@ -23,136 +24,136 @@
2324
@app.callback(invoke_without_command=True)
2425
@wrap_exceptions
2526
def sync(
26-
input_file: Path = typer.Option(
27+
input_file: Optional[Path] = typer.Option(
2728
None,
2829
"--input-file",
2930
"-i",
3031
help="Somesy input file path (default: .somesy.toml)",
3132
**file_arg_config,
3233
),
33-
no_sync_pyproject: bool = typer.Option(
34+
no_sync_pyproject: Optional[bool] = typer.Option(
3435
None,
3536
"--no-sync-pyproject",
3637
"-P",
3738
help="Do not sync pyproject.toml file (default: False)",
3839
),
39-
pyproject_file: Path = typer.Option(
40+
pyproject_file: Optional[List[Path]] = typer.Option(
4041
None,
4142
"--pyproject-file",
4243
"-p",
43-
help="Existing pyproject.toml file path (default: pyproject.toml)",
44+
help="Existing pyproject.toml file path(s) (default: pyproject.toml)",
4445
**existing_file_arg_config,
4546
),
46-
no_sync_package_json: bool = typer.Option(
47+
no_sync_package_json: Optional[bool] = typer.Option(
4748
None,
4849
"--no-sync-package-json",
4950
"-J",
5051
help="Do not sync package.json file (default: False)",
5152
),
52-
package_json_file: Path = typer.Option(
53+
package_json_file: Optional[List[Path]] = typer.Option(
5354
None,
5455
"--package-json-file",
5556
"-j",
56-
help="Existing package.json file path (default: package.json)",
57+
help="Existing package.json file path(s) (default: package.json)",
5758
**existing_file_arg_config,
5859
),
59-
no_sync_julia: bool = typer.Option(
60+
no_sync_julia: Optional[bool] = typer.Option(
6061
None,
6162
"--no-sync-julia",
6263
"-L",
6364
help="Do not sync Project.toml (Julia) file (default: False)",
6465
),
65-
julia_file: Path = typer.Option(
66+
julia_file: Optional[List[Path]] = typer.Option(
6667
None,
6768
"--julia-file",
6869
"-l",
69-
help="Custom Project.toml (Julia) file path (default: Project.toml)",
70+
help="Custom Project.toml (Julia) file path(s) (default: Project.toml)",
7071
**existing_file_arg_config,
7172
),
72-
no_sync_fortran: bool = typer.Option(
73+
no_sync_fortran: Optional[bool] = typer.Option(
7374
None,
7475
"--no-sync-fortran",
7576
"-F",
7677
help="Do not sync fpm.toml (Fortran) file (default: False)",
77-
**existing_file_arg_config,
7878
),
79-
fortran_file: Path = typer.Option(
79+
fortran_file: Optional[List[Path]] = typer.Option(
8080
None,
8181
"--fortran-file",
8282
"-f",
83-
help="Custom fpm.toml (Fortran) file path (default: fpm.toml)",
83+
help="Custom fpm.toml (Fortran) file path(s) (default: fpm.toml)",
84+
**existing_file_arg_config,
8485
),
85-
no_sync_pom_xml: bool = typer.Option(
86+
no_sync_pom_xml: Optional[bool] = typer.Option(
8687
None,
8788
"--no-sync-pomxml",
8889
"-X",
8990
help="Do not sync pom.xml (Java Maven) file (default: False)",
9091
),
91-
pom_xml_file: Path = typer.Option(
92+
pom_xml_file: Optional[List[Path]] = typer.Option(
9293
None,
9394
"--pomxml-file",
9495
"-x",
95-
help="Custom pom.xml (Java Maven) file path (default: pom.xml)",
96+
help="Custom pom.xml (Java Maven) file path(s) (default: pom.xml)",
9697
**existing_file_arg_config,
9798
),
98-
no_sync_mkdocs: bool = typer.Option(
99+
no_sync_mkdocs: Optional[bool] = typer.Option(
99100
None,
100101
"--no-sync-mkdocs",
101102
"-D",
102103
help="Do not sync mkdocs.yml file (default: False)",
103104
),
104-
mkdocs_file: Path = typer.Option(
105+
mkdocs_file: Optional[List[Path]] = typer.Option(
105106
None,
106107
"--mkdocs-file",
107108
"-d",
108-
help="Custom mkdocs.yml file path (default: mkdocs.yml)",
109+
help="Custom mkdocs.yml file path(s) (default: mkdocs.yml)",
109110
**existing_file_arg_config,
110111
),
111-
no_sync_rust: bool = typer.Option(
112+
no_sync_rust: Optional[bool] = typer.Option(
112113
None,
113114
"--no-sync-rust",
114115
"-R",
115116
help="Do not sync Cargo.toml file (default: False)",
116117
),
117-
rust_file: Path = typer.Option(
118+
rust_file: Optional[List[Path]] = typer.Option(
118119
None,
119120
"--rust-file",
120121
"-r",
121-
help="Custom Cargo.toml file path (default: Cargo.toml)",
122+
help="Custom Cargo.toml file path(s) (default: Cargo.toml)",
122123
**existing_file_arg_config,
123124
),
124-
no_sync_cff: bool = typer.Option(
125+
no_sync_cff: Optional[bool] = typer.Option(
125126
None,
126127
"--no-sync-cff",
127128
"-C",
128129
help="Do not sync CITATION.cff file (default: False)",
129130
),
130-
cff_file: Path = typer.Option(
131+
cff_file: Optional[List[Path]] = typer.Option(
131132
None,
132133
"--cff-file",
133134
"-c",
134-
help="CITATION.cff file path (default: CITATION.cff)",
135+
help="CITATION.cff file path(s) (default: CITATION.cff)",
135136
**file_arg_config,
136137
),
137-
no_sync_codemeta: bool = typer.Option(
138+
no_sync_codemeta: Optional[bool] = typer.Option(
138139
None,
139140
"--no-sync-codemeta",
140141
"-M",
141142
help="Do not sync codemeta.json file (default: False)",
142143
),
143-
codemeta_file: Path = typer.Option(
144+
codemeta_file: Optional[List[Path]] = typer.Option(
144145
None,
145146
"--codemeta-file",
146147
"-m",
147-
help="Custom codemeta.json file path (default: codemeta.json)",
148+
help="Custom codemeta.json file path(s) (default: codemeta.json)",
148149
**file_arg_config,
149150
),
150-
merge_codemeta: bool = typer.Option(
151+
merge_codemeta: Optional[bool] = typer.Option(
151152
False,
152153
"--merge/--overwrite",
153154
help="Merge codemeta.json with with an existing codemeta.json file (default: False)",
154155
),
155-
pass_validation: bool = typer.Option(
156+
pass_validation: Optional[bool] = typer.Option(
156157
False,
157158
"--pass-validation",
158159
"-P",

src/somesy/commands/sync.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ def _sync_file(
4040
logger.verbose(f"Saved synced '{file.name}'.\n")
4141

4242

43+
def _sync_files(metadata, files, writer_class, **kwargs):
44+
if isinstance(files, Path):
45+
files = [files]
46+
for file in files:
47+
if file.is_file():
48+
_sync_file(metadata, file, writer_class, **kwargs)
49+
50+
4351
def sync(somesy_input: SomesyInput):
4452
"""Sync selected metadata files with given input file."""
4553
conf, metadata = somesy_input.config, somesy_input.project
@@ -49,56 +57,56 @@ def sync(somesy_input: SomesyInput):
4957

5058
# update these only if they exist:
5159

52-
if conf.pyproject_file.is_file() and not conf.no_sync_pyproject:
53-
_sync_file(
60+
if conf.pyproject_file and not conf.no_sync_pyproject:
61+
_sync_files(
5462
metadata,
5563
conf.pyproject_file,
5664
Pyproject,
5765
pass_validation=conf.pass_validation,
5866
)
5967

60-
if conf.package_json_file.is_file() and not conf.no_sync_package_json:
61-
_sync_file(
68+
if conf.package_json_file and not conf.no_sync_package_json:
69+
_sync_files(
6270
metadata,
6371
conf.package_json_file,
6472
PackageJSON,
6573
pass_validation=conf.pass_validation,
6674
)
6775

68-
if conf.julia_file.is_file() and not conf.no_sync_julia:
69-
_sync_file(
76+
if conf.julia_file and not conf.no_sync_julia:
77+
_sync_files(
7078
metadata,
7179
conf.julia_file,
7280
Julia,
7381
pass_validation=conf.pass_validation,
7482
)
7583

76-
if conf.fortran_file.is_file() and not conf.no_sync_fortran:
77-
_sync_file(
84+
if conf.fortran_file and not conf.no_sync_fortran:
85+
_sync_files(
7886
metadata,
7987
conf.fortran_file,
8088
Fortran,
8189
pass_validation=conf.pass_validation,
8290
)
8391

84-
if conf.pom_xml_file.is_file() and not conf.no_sync_pom_xml:
85-
_sync_file(
92+
if conf.pom_xml_file and not conf.no_sync_pom_xml:
93+
_sync_files(
8694
metadata,
8795
conf.pom_xml_file,
8896
POM,
8997
pass_validation=conf.pass_validation,
9098
)
9199

92-
if conf.mkdocs_file.is_file() and not conf.no_sync_mkdocs:
93-
_sync_file(
100+
if conf.mkdocs_file and not conf.no_sync_mkdocs:
101+
_sync_files(
94102
metadata,
95103
conf.mkdocs_file,
96104
MkDocs,
97105
pass_validation=conf.pass_validation,
98106
)
99107

100-
if conf.rust_file.is_file() and not conf.no_sync_rust:
101-
_sync_file(
108+
if conf.rust_file and not conf.no_sync_rust:
109+
_sync_files(
102110
metadata,
103111
conf.rust_file,
104112
Rust,
@@ -107,15 +115,15 @@ def sync(somesy_input: SomesyInput):
107115

108116
# create these by default if they are missing:
109117
if not conf.no_sync_cff:
110-
_sync_file(
118+
_sync_files(
111119
metadata,
112120
conf.cff_file,
113121
CFF,
114122
pass_validation=conf.pass_validation,
115123
)
116124

117125
if not conf.no_sync_codemeta:
118-
_sync_file(
126+
_sync_files(
119127
metadata,
120128
conf.codemeta_file,
121129
CodeMeta,

tests/input/test_core_core.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,41 @@ def test_somesy_input(somesy_input):
9999

100100
# check publication author
101101
assert authors[1].publication_author is True
102+
103+
104+
def test_multiple_inputs(create_files, file_types):
105+
"""Test handling of multiple input files for the same format."""
106+
# Create test files in multiple locations
107+
tmp_path = create_files(
108+
[
109+
(file_types.POETRY, "pyproject.toml"),
110+
(file_types.POETRY, "subproject/pyproject.toml"),
111+
(file_types.PACKAGE_JSON, "package.json"),
112+
(file_types.PACKAGE_JSON, "subproject/package.json"),
113+
]
114+
)
115+
116+
# Test configuration with multiple file paths
117+
config = SomesyConfig(
118+
pyproject_file=[
119+
tmp_path / "pyproject.toml",
120+
tmp_path / "subproject/pyproject.toml",
121+
],
122+
package_json_file=[
123+
tmp_path / "package.json",
124+
tmp_path / "subproject/package.json",
125+
],
126+
)
127+
128+
# Verify the paths are correctly set
129+
assert isinstance(config.pyproject_file, list)
130+
assert len(config.pyproject_file) == 2
131+
assert all(isinstance(p, Path) for p in config.pyproject_file)
132+
assert config.pyproject_file[0] == tmp_path / "pyproject.toml"
133+
assert config.pyproject_file[1] == tmp_path / "subproject/pyproject.toml"
134+
135+
assert isinstance(config.package_json_file, list)
136+
assert len(config.package_json_file) == 2
137+
assert all(isinstance(p, Path) for p in config.package_json_file)
138+
assert config.package_json_file[0] == tmp_path / "package.json"
139+
assert config.package_json_file[1] == tmp_path / "subproject/package.json"

0 commit comments

Comments
 (0)