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 filepath in filepaths :
52+ files .append (* add_directory (filepath ) if Path (filepath ).is_dir () else File (filepath = filepath ))
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,17 +88,25 @@ 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
94+
6795 Raises:
6896 typer.BadParameter: If both config file and filepaths are specified
97+ typer.BadParameter: If both config file and recurse are specified
6998 typer.BadParameter: If neither config file nor required parameters are provided
7099 """
71100 if config_path is not None and len (filepaths ) > 0 :
72101 raise typer .BadParameter (
73102 "Cannot specify both a JSON/YAML file and a list of filepaths."
74103 )
75104
105+ if config_path is not None and recurse :
106+ raise typer .BadParameter (
107+ "Cannot specify both a JSON/YAML file and recurse into filepaths."
108+ )
109+
76110 _has_meta_params = all (arg is not None for arg in [pid , dataverse_url , api_token ])
77111 _has_config_file = config_path is not None
78112
@@ -94,6 +128,10 @@ def main(
94128 default = None ,
95129 help = "A list of filepaths to upload." ,
96130 ),
131+ recurse : Optional [bool ] = typer .Option (
132+ default = False ,
133+ help = "Enable recursion into filepaths." ,
134+ ),
97135 pid : str = typer .Option (
98136 default = None ,
99137 help = "The persistent identifier of the Dataverse dataset." ,
@@ -123,6 +161,7 @@ def main(
123161
124162 If using command line arguments, you must specify:
125163 - One or more filepaths to upload
164+ - (Optional) whether to recurse into the filepaths
126165 - The dataset's persistent identifier
127166 - A valid API token
128167 - The Dataverse repository URL
@@ -150,6 +189,7 @@ def main(
150189 pid = pid ,
151190 dataverse_url = dataverse_url ,
152191 api_token = api_token ,
192+ recurse = recurse ,
153193 config_path = config_path ,
154194 )
155195
@@ -161,7 +201,7 @@ def main(
161201 api_token = api_token ,
162202 dataverse_url = dataverse_url ,
163203 persistent_id = pid ,
164- files = [ File ( filepath = filepath ) for filepath in filepaths ] ,
204+ files = _enumerate_filepaths ( filepaths = filepaths , recurse = recurse ) ,
165205 )
166206
167207 uploader = DVUploader (files = cli_input .files )
0 commit comments