diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py
index 18329f486ec..696b992b2da 100644
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -2669,6 +2669,14 @@ class DirectoryUriToolParameter(SimpleTextToolParameter):
if not user_has_access:
raise ParameterValueError(f"The user cannot access {value}.", self.name)
+ def to_param_dict_string(self, value, other_values=None) -> str:
+ """Called via __str__ when used in the Cheetah template"""
+ if value is None:
+ value = ""
+ elif not isinstance(value, str):
+ value = str(value)
+ return value
+
class RulesListToolParameter(BaseJsonToolParameter):
"""
diff --git a/test/integration/test_remote_files.py b/test/integration/test_remote_files.py
index c56759bb6f7..6ac53a15550 100644
--- a/test/integration/test_remote_files.py
+++ b/test/integration/test_remote_files.py
@@ -205,6 +205,46 @@ class TestRemoteFilesIntegration(ConfiguresRemoteFilesIntegrationTestCase):
with open(os.path.join(ftp_dir, "my_cool", "utf8_name_😻.txt")) as f:
assert "example content\n" == f.read()
+ def test_export_remote_tool_with_space(self):
+ dataset_populator = self.dataset_populator
+ ftp_dir = self.user_ftp_dir
+ _write_file_fixtures(self.root, ftp_dir)
+ dir_with_space = os.path.join(ftp_dir, "space dir")
+ os.makedirs(dir_with_space)
+ with dataset_populator.test_history() as history_id:
+ dataset = dataset_populator.new_dataset(history_id, content="example content", wait=True, name="foo")
+ infile = {"src": "hda", "id": dataset["id"]}
+ inputs = {
+ "d_uri": "gxftp://space dir/",
+ "export_type|export_type_selector": "datasets_named",
+ "export_type|datasets_0|infile": infile,
+ "export_type|datasets_0|name": ".my_cool/utf8_name_😻.txt",
+ }
+ response = dataset_populator.run_tool("export_remote", inputs, history_id)
+ dataset_populator.wait_for_job(response["jobs"][0]["id"], assert_ok=True)
+ with open(os.path.join(ftp_dir, "space dir", "my_cool", "utf8_name_😻.txt")) as f:
+ assert "example content\n" == f.read()
+
+ def test_export_remote_tool_with_space_encoded(self):
+ dataset_populator = self.dataset_populator
+ ftp_dir = self.user_ftp_dir
+ _write_file_fixtures(self.root, ftp_dir)
+ dir_with_space = os.path.join(ftp_dir, "space%20dir")
+ os.makedirs(dir_with_space)
+ with dataset_populator.test_history() as history_id:
+ dataset = dataset_populator.new_dataset(history_id, content="example content", wait=True, name="foo")
+ infile = {"src": "hda", "id": dataset["id"]}
+ inputs = {
+ "d_uri": "gxftp://space%20dir/",
+ "export_type|export_type_selector": "datasets_named",
+ "export_type|datasets_0|infile": infile,
+ "export_type|datasets_0|name": ".my_cool/utf8_name_😻.txt",
+ }
+ response = dataset_populator.run_tool("export_remote", inputs, history_id)
+ dataset_populator.wait_for_job(response["jobs"][0]["id"], assert_ok=True)
+ with open(os.path.join(ftp_dir, "space%20dir", "my_cool", "utf8_name_😻.txt")) as f:
+ assert "example content\n" == f.read()
+
def test_export_remote_tool_default_duplicate_name_fails(self):
dataset_populator = self.dataset_populator
ftp_dir = self.user_ftp_dir
diff --git a/tools/data_export/export_remote.py b/tools/data_export/export_remote.py
index 6574756a85f..f0b027e5a92 100644
--- a/tools/data_export/export_remote.py
+++ b/tools/data_export/export_remote.py
@@ -35,15 +35,23 @@ def write_if_not_exists(file_sources, target_uri, real_data_path):
file_source.write_from(file_source_path.path, real_data_path)
+def get_directory_uri(args):
+ directory_uri = args.directory_uri
+ if not directory_uri:
+ inputs = json.load(open(args.inputs, "r"))
+ directory_uri = inputs["d_uri"]
+ if not directory_uri.endswith("/"):
+ directory_uri = f"{directory_uri}/"
+ return directory_uri
+
+
def main(argv=None):
if argv is None:
argv = sys.argv[1:]
args = _parser().parse_args(argv)
exit_code = 0
file_sources = get_file_sources(args.file_sources)
- directory_uri = args.directory_uri
- if not directory_uri.endswith("/"):
- directory_uri = f"{directory_uri}/"
+ directory_uri = get_directory_uri(args)
export_metadata_files = args.export_metadata_files
with open(args.files_to_export) as f:
files_to_export = json.load(f)
@@ -68,6 +76,8 @@ def main(argv=None):
def _parser():
parser = argparse.ArgumentParser()
+ parser.add_argument("--inputs", type=str, help="galaxy inputs")
+ # post 2026.XX drop the directory-uri argument and just assume inputs always contains d_uri.
parser.add_argument("--directory-uri", type=str, help="directory target URI")
parser.add_argument("--file-sources", type=str, help="file sources json")
parser.add_argument("--files-to-export", type=str, help="files to export")
diff --git a/tools/data_export/export_remote.xml b/tools/data_export/export_remote.xml
index fe544c48e20..63f2318a6c5 100644
--- a/tools/data_export/export_remote.xml
+++ b/tools/data_export/export_remote.xml
@@ -8,7 +8,7 @@
+
#import json
#from galaxy.util import filesystem_safe_string
#if $export_type.export_type_selector == "datasets_auto":