11import yaml
22import typer
33
4+ from pathlib import Path
45from pydantic import BaseModel
56from typing import List , Optional
67from dvuploader import DVUploader , File
8+ from dvuploader .utils import add_directory
79
810
911class CliInput (BaseModel ):
@@ -27,6 +29,29 @@ class CliInput(BaseModel):
2729
2830app = typer .Typer ()
2931
32+ def _enumerate_filepaths (filepaths : List [str ], recurse : bool ) -> List [File ]:
33+ """
34+ Take a list of filepaths and transform it into a list of File objects, optionally recursing into each of them.
35+
36+ Args:
37+ filepaths (List[str]): a list of files or paths for upload
38+ recurse (bool): whether to recurse into each given filepath
39+
40+ Returns:
41+ List[File]: A list of File objects representing the files extracted from all filepaths.
42+
43+ Raises:
44+ FileNotFoundError: If a filepath does not exist.
45+ IsADirectoryError: If recurse is False and a filepath points to a directory instead of a file.
46+ """
47+ if not recurse :
48+ return [File (filepath = filepath ) for filepath in filepaths ]
49+
50+ files = []
51+ for fp in filepaths :
52+ files .extend (add_directory (fp ) if Path (fp ).is_dir () else [File (filepath = fp )])
53+ return files
54+
3055
3156def _parse_yaml_config (path : str ) -> CliInput :
3257 """
@@ -50,6 +75,7 @@ def _validate_inputs(
5075 pid : str ,
5176 dataverse_url : str ,
5277 api_token : str ,
78+ recurse : bool ,
5379 config_path : Optional [str ],
5480) -> None :
5581 """
@@ -62,16 +88,23 @@ def _validate_inputs(
6288 pid (str): Persistent identifier of the dataset
6389 dataverse_url (str): URL of the Dataverse instance
6490 api_token (str): API token for authentication
91+ recurse (bool): Whether to recurse into filepaths
6592 config_path (Optional[str]): Path to configuration file
6693
6794 Raises:
6895 typer.BadParameter: If both config file and filepaths are specified
96+ typer.BadParameter: If both config file and recurse are specified
6997 typer.BadParameter: If neither config file nor required parameters are provided
7098 """
71- if config_path is not None and len (filepaths ) > 0 :
72- raise typer .BadParameter (
73- "Cannot specify both a JSON/YAML file and a list of filepaths."
74- )
99+ if config_path is not None :
100+ if len (filepaths ) > 0 :
101+ raise typer .BadParameter (
102+ "Cannot specify both a JSON/YAML file and a list of filepaths."
103+ )
104+ if recurse :
105+ raise typer .BadParameter (
106+ "Cannot specify both a JSON/YAML file and recurse into filepaths."
107+ )
75108
76109 _has_meta_params = all (arg is not None for arg in [pid , dataverse_url , api_token ])
77110 _has_config_file = config_path is not None
@@ -90,10 +123,14 @@ def _validate_inputs(
90123
91124@app .command ()
92125def main (
93- filepaths : List [str ] = typer .Argument (
126+ filepaths : Optional [ List [str ] ] = typer .Argument (
94127 default = None ,
95128 help = "A list of filepaths to upload." ,
96129 ),
130+ recurse : Optional [bool ] = typer .Option (
131+ default = False ,
132+ help = "Enable recursion into filepaths." ,
133+ ),
97134 pid : str = typer .Option (
98135 default = None ,
99136 help = "The persistent identifier of the Dataverse dataset." ,
@@ -123,6 +160,7 @@ def main(
123160
124161 If using command line arguments, you must specify:
125162 - One or more filepaths to upload
163+ - (Optional) whether to recurse into the filepaths
126164 - The dataset's persistent identifier
127165 - A valid API token
128166 - The Dataverse repository URL
@@ -141,11 +179,16 @@ def main(
141179 Upload files via config file:
142180 $ dvuploader --config-path upload_config.yaml
143181 """
182+
183+ if filepaths is None :
184+ filepaths = []
185+
144186 _validate_inputs (
145187 filepaths = filepaths ,
146188 pid = pid ,
147189 dataverse_url = dataverse_url ,
148190 api_token = api_token ,
191+ recurse = recurse ,
149192 config_path = config_path ,
150193 )
151194
@@ -157,7 +200,7 @@ def main(
157200 api_token = api_token ,
158201 dataverse_url = dataverse_url ,
159202 persistent_id = pid ,
160- files = [ File ( filepath = filepath ) for filepath in filepaths ] ,
203+ files = _enumerate_filepaths ( filepaths = filepaths , recurse = recurse ) ,
161204 )
162205
163206 uploader = DVUploader (files = cli_input .files )
0 commit comments