seqslab-cli 3.2.7__tar.gz → 3.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/PKG-INFO +1 -1
  2. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/__init__.py +1 -1
  3. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/cli.py +4 -2
  4. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/api/base.py +18 -4
  5. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/commands.py +42 -18
  6. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/internal/aiocopy.py +2 -2
  7. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/storage/azure.py +9 -457
  8. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/commands.py +1 -4
  9. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/commands.py +22 -8
  10. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/internal/parameters.py +3 -1
  11. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/template/base.py +5 -2
  12. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/PKG-INFO +1 -1
  13. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/requires.txt +1 -1
  14. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/requirements.txt +1 -1
  15. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/LICENSE +0 -0
  16. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/MANIFEST.in +0 -0
  17. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/README.md +0 -0
  18. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/auth/__init__.py +0 -0
  19. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/auth/azuread.py +0 -0
  20. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/auth/commands.py +0 -0
  21. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/context.py +0 -0
  22. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/__init__.py +0 -0
  23. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/api/__init__.py +0 -0
  24. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/api/azure.py +0 -0
  25. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/api/common.py +0 -0
  26. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/api/template.py +0 -0
  27. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/internal/__init__.py +0 -0
  28. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/internal/common.py +0 -0
  29. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/internal/utils.py +0 -0
  30. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/storage/__init__.py +0 -0
  31. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/storage/base.py +0 -0
  32. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/utils/__init__.py +0 -0
  33. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/utils/atgxmetadata.py +0 -0
  34. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/utils/biomimetype.py +0 -0
  35. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/drs/utils/progressbar.py +0 -0
  36. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/exceptions.py +0 -0
  37. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/organization/__init__.py +0 -0
  38. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/organization/commands.py +0 -0
  39. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/organization/resource/__init__.py +0 -0
  40. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/organization/resource/base.py +0 -0
  41. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/plugin.py +0 -0
  42. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/__init__.py +0 -0
  43. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/commands.py +0 -0
  44. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/internal/__init__.py +0 -0
  45. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/internal/common.py +0 -0
  46. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/resource/__init__.py +0 -0
  47. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/resource/azure.py +0 -0
  48. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/role/resource/base.py +0 -0
  49. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/runsheet/__init__.py +0 -0
  50. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/runsheet/runsheet.py +0 -0
  51. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/sample_sheet/__init__.py +0 -0
  52. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/sample_sheet/_version.py +0 -0
  53. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/sample_sheet/util.py +0 -0
  54. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/__init__.py +0 -0
  55. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/internal/__init__.py +0 -0
  56. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/internal/common.py +0 -0
  57. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/resource/__init__.py +0 -0
  58. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/resource/azure.py +0 -0
  59. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/scr/resource/base.py +0 -0
  60. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/session_logger.py +0 -0
  61. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/settings.py +0 -0
  62. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/statusbar.py +0 -0
  63. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/__init__.py +0 -0
  64. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/commands.py +0 -0
  65. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/internal/__init__.py +0 -0
  66. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/internal/utils.py +0 -0
  67. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/register/__init__.py +0 -0
  68. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/register/azure.py +0 -0
  69. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/register/base.py +0 -0
  70. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/register/common.py +0 -0
  71. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/register/template.py +0 -0
  72. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/resource/__init__.py +0 -0
  73. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/resource/azure.py +0 -0
  74. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/resource/base.py +0 -0
  75. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/resource/common.py +0 -0
  76. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/template/__init__.py +0 -0
  77. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/template/base.py +0 -0
  78. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/trs/template/template.py +0 -0
  79. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/usage_logger.py +0 -0
  80. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/__init__.py +0 -0
  81. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/commands.py +0 -0
  82. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/internal/__init__.py +0 -0
  83. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/internal/common.py +0 -0
  84. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/resource/__init__.py +0 -0
  85. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/resource/azure.py +0 -0
  86. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/user/resource/base.py +0 -0
  87. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/__init__.py +0 -0
  88. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/internal/__init__.py +0 -0
  89. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/internal/common.py +0 -0
  90. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/resource/__init__.py +0 -0
  91. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/resource/azure.py +0 -0
  92. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/resource/base.py +0 -0
  93. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/template/__init__.py +0 -0
  94. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/wes/template/template.py +0 -0
  95. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/__init__.py +0 -0
  96. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/commands.py +0 -0
  97. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/internal/__init__.py +0 -0
  98. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/internal/common.py +0 -0
  99. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/resource/__init__.py +0 -0
  100. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/resource/azure.py +0 -0
  101. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab/workspace/resource/base.py +0 -0
  102. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/SOURCES.txt +0 -0
  103. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/dependency_links.txt +0 -0
  104. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/entry_points.txt +0 -0
  105. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/top_level.txt +0 -0
  106. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/python/seqslab_cli.egg-info/zip-safe +0 -0
  107. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/setup.cfg +0 -0
  108. {seqslab-cli-3.2.7 → seqslab-cli-3.3.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: seqslab-cli
3
- Version: 3.2.7
3
+ Version: 3.3.1
4
4
  Summary: Atgenomix SeqsLab Command Line Tool
5
5
  Home-page: https://github.com/AnomeGAP/seqslab-cli
6
6
  Author: Allen Chang
@@ -23,7 +23,7 @@ __all__ = [
23
23
  ]
24
24
 
25
25
 
26
- __version__ = "3.2.7"
26
+ __version__ = "3.3.1"
27
27
 
28
28
  LOGGING = {
29
29
  "DIR_PATH": "/var/log/seqslab"
@@ -26,8 +26,10 @@ from seqslab.plugin import SQLBPlugin
26
26
 
27
27
 
28
28
  def signal_handler(sig, frame):
29
- msg = "Ctrl-c was pressed. Do you really want to exit? [y/n] "
30
- ans = input(msg)
29
+ msg = "\nCtrl-c was pressed. Do you really want to exit? [y/n] "
30
+ sys.stderr.write(msg)
31
+ ans = input()
32
+
31
33
  if ans == 'y':
32
34
  print("")
33
35
  exit(1)
@@ -31,6 +31,7 @@ class CopyResult(NamedTuple):
31
31
  tags: list
32
32
  checksums: dict
33
33
  access_methods: dict
34
+ deleted_time: str
34
35
 
35
36
  def __str__(self):
36
37
  return json.dumps(
@@ -133,7 +134,7 @@ class DRSregister:
133
134
  @staticmethod
134
135
  def patch_template(name: str = None, tags: List[str] = [], metadata: dict = {}, checksum: str = None,
135
136
  checksum_type: str = None,
136
- updated_time: str = None, **kwargs) -> dict:
137
+ updated_time: str = None, deleted_time: str = None, **kwargs) -> dict:
137
138
  """
138
139
  return only one template
139
140
  :param: drs_type, description, aliases, metadata, tags
@@ -151,7 +152,8 @@ class DRSregister:
151
152
  tags=tags,
152
153
  metadata=metadata,
153
154
  checksums=checksums,
154
- updated_time=updated_time)
155
+ updated_time=updated_time,
156
+ deleted_time=deleted_time)
155
157
  return template
156
158
 
157
159
  @retry(stop=stop_after_attempt(3), wait=WAIT_TWO_SECOND, reraise=True)
@@ -191,14 +193,25 @@ class DRSregister:
191
193
  tags=obj.get('tags'),
192
194
  access_methods=obj.get('access_methods'),
193
195
  checksums=obj.get('checksums'),
196
+ deleted_time=obj.get('deleted_time')
194
197
  )._asdict() for obj in drs_objects]
195
198
  return results
196
199
 
197
200
  def create_payload(self, stdin: List[dict], type: str, **kwargs) -> List[dict]:
198
- if type == 'file-blob':
201
+ if type == 'file':
199
202
  payload = stdin
200
203
  else:
201
204
  payload = self.folder_blob(stdin, **kwargs)
205
+ if tags := kwargs.get('tags'):
206
+ for p in payload:
207
+ p['tags'] = tags
208
+ if metadata := kwargs.get('metadata'):
209
+ for p in payload:
210
+ p['metadata'] = metadata
211
+ if deleted_time := kwargs.get('deleted_time'):
212
+ for p in payload:
213
+ p['deleted_time'] = deleted_time
214
+
202
215
  return payload
203
216
 
204
217
  def dst_checking(self, dst: str) -> None:
@@ -344,7 +357,8 @@ class DRSregister:
344
357
  aliases=obj.get('aliases'),
345
358
  tags=obj.get('tags'),
346
359
  access_methods=obj.get('access_methods'),
347
- checksums=obj.get('checksums')
360
+ checksums=obj.get('checksums'),
361
+ deleted_time=obj.get('deleted_time')
348
362
  )._asdict()
349
363
  return results
350
364
 
@@ -71,21 +71,24 @@ class BaseDatahub:
71
71
  if not recursive:
72
72
  raise OSError("--recursive (-r) is Required.")
73
73
  if not str(dst).endswith('/') and not kwargs.get('non_interactive'):
74
- user_input = input(
75
- f"Do you mean to rename the `{os.path.basename(str(src))}` to `{os.path.basename(str(dst))}`?(Y/N): ")
74
+ sys.stderr.write(f'f"Do you mean to rename the `{os.path.basename(str(src))}` to '
75
+ f'`{os.path.basename(str(dst))}`?(Y/N): "')
76
+ user_input = input()
76
77
  if user_input.lower() != "y":
77
78
  raise InterruptedError("Interrupt all the process.")
78
79
  coro = aiocopy.dir_to_blob(URL(*paths), dst, **kwargs)
79
80
  else:
80
81
  if not str(dst).endswith('/') and not kwargs.get('non_interactive'):
81
- user_input = input(
82
- f"Do you mean to rename `{os.path.basename(str(src))}` to `{os.path.basename(str(dst))}`?(Y/N): ")
82
+ sys.stderr.write(f'f"Do you mean to rename the `{os.path.basename(str(src))}` to '
83
+ f'`{os.path.basename(str(dst))}`?(Y/N): "')
84
+ user_input = input()
83
85
  if user_input.lower() != "y":
84
86
  raise InterruptedError("Interrupt all the process.")
85
87
  coro = aiocopy.file_to_blob([URL(*paths)], dst, **kwargs)
86
88
  else:
87
89
  if not str(dst).endswith('/') and not kwargs.get('non_interactive'):
88
- user_input = input(f"Do you mean to upload all the files into {str(dst)}/?(Y/N): ")
90
+ sys.stderr.write(f"Do you mean to upload all the files into {str(dst)}/?(Y/N): ")
91
+ user_input = input()
89
92
  if user_input.lower() != "y":
90
93
  raise InterruptedError("Interrupt all the process.")
91
94
  files = []
@@ -356,7 +359,7 @@ class BaseDatahub:
356
359
  type=str,
357
360
  positional=False,
358
361
  description="A DRS object ID (required if there is no self URI).")
359
- def share_link(self, workspace: str, id: str) -> int:
362
+ def share(self, workspace: str, id: str) -> int:
360
363
  """
361
364
  Generate a share link enabling external users to download the DRS object as a zip archive through web
362
365
  browsers. The share link expires either after the first successful download or after a period of three months.
@@ -405,10 +408,10 @@ class BaseDatahub:
405
408
  @argument("type",
406
409
  type=str,
407
410
  positional=True,
408
- description="If you want to register a file as a blob, please choose file-blob. "
409
- "If you want to register a directory as a blob, please choose dir-blob "
411
+ description="If you want to register a file as a blob, please choose file. "
412
+ "If you want to register a directory as a blob, please choose dir. "
410
413
  "(required).",
411
- choices=['file-blob', 'dir-blob'])
414
+ choices=['file', 'dir'])
412
415
  @argument("name",
413
416
  type=str,
414
417
  description="Specify the name of the object that you want to register "
@@ -487,6 +490,11 @@ class BaseDatahub:
487
490
  "must therefore contain all the required keys [name, file_type, mime_type, description, "
488
491
  "aliases, tags, created_time, updated_time, size, urls, access_tiers, regions, "
489
492
  "Authorizations, checksum, checksum_type, metadata].")
493
+ @argument("deleted_time",
494
+ type=str,
495
+ positional=False,
496
+ description="Specify a date in the format YYYY-MM-DD to set the automatic deletion time for the DRS "
497
+ "object, for example, 2024-01-01 (optional).")
490
498
  @argument("output",
491
499
  type=str,
492
500
  positional=False,
@@ -552,7 +560,8 @@ class BaseDatahub:
552
560
  "aliases": kwargs.get('aliases'),
553
561
  "metadata": json.loads(kwargs.get('metadata')) if kwargs.get('metadata') else None,
554
562
  "tags": kwargs.get('tags'),
555
- "id": kwargs.get('id')
563
+ "id": kwargs.get('id'),
564
+ "deleted_time": kwargs.get('deleted_time')
556
565
  }]
557
566
 
558
567
  results = backend.create_drsobjects(drs_type='blob', payloads=payloads)
@@ -593,6 +602,11 @@ class BaseDatahub:
593
602
  type=str,
594
603
  positional=False,
595
604
  description="Specify a custom object ID (optional).")
605
+ @argument("deleted_time",
606
+ type=str,
607
+ positional=False,
608
+ description="Specify a date in the format YYYY-MM-DD to set the automatic deletion time for the DRS "
609
+ "object, for example, 2024-01-01 (optional).")
596
610
  @argument("output",
597
611
  type=str,
598
612
  positional=False,
@@ -635,7 +649,8 @@ class BaseDatahub:
635
649
  "metadata": json.loads(kwargs.get('metadata')) if kwargs.get('metadata') else None,
636
650
  "tags": kwargs.get('tags'),
637
651
  "id": kwargs.get('id'),
638
- "contents": drs_ids
652
+ "contents": drs_ids,
653
+ "deleted_time": kwargs.get('deleted_time')
639
654
  }]
640
655
 
641
656
  results = backend.create_drsobjects(drs_type='bundle', payloads=payloads)
@@ -940,13 +955,17 @@ class BaseDatahub:
940
955
  proxy=self.proxy,
941
956
  non_interactive=non_interactive,
942
957
  expiry_time=expiry_time
943
- )[0]
944
- result['metadata'] = payload.get('metadata')
945
- result['tags'] = payload.get('tags')
946
- if payload.get('id'):
947
- result['id'] = payload.get('id')
948
- ret.append(result)
949
- if result['status'] != 'complete':
958
+ )
959
+ if isinstance(result, list):
960
+ r = result[0]
961
+ r['metadata'] = payload.get('metadata')
962
+ r['tags'] = payload.get('tags')
963
+ if payload.get('id'):
964
+ r['id'] = payload.get('id')
965
+ ret.append(r)
966
+ if r['status'] != 'complete':
967
+ failed = True
968
+ else:
950
969
  failed = True
951
970
  cprint(json.dumps(ret, indent=4), 'yellow')
952
971
 
@@ -991,6 +1010,11 @@ class BaseDatahub:
991
1010
  description="Specify the timestamp when the DRS object was updated (optional). "
992
1011
  "The time format must be in RFC3339. "
993
1012
  "For example, 2021-09-13 02:54:03.636044+00:00.")
1013
+ @argument("deleted_time",
1014
+ type=str,
1015
+ positional=False,
1016
+ description="Specify a date in the format YYYY-MM-DD to set the automatic deletion time for the DRS "
1017
+ "object, for example, 2024-01-01 (optional).")
994
1018
  @argument("stdin",
995
1019
  type=bool,
996
1020
  positional=False,
@@ -286,7 +286,7 @@ async def file_to_blob(
286
286
  while progress < len(files):
287
287
  tasks = []
288
288
  for p in range(progress, progress + min(multiprocessing, len(files) - progress)):
289
- _dst = URL(os.path.join(str(dst), os.path.basename(files[p].path))) if str(dst).endswith('/') else dst
289
+ _dst = URL(os.path.join(str(dst), os.path.basename(files[p].path)), encoded=True) if str(dst).endswith('/') else dst
290
290
  tasks.append(store.upload(_dst, files[p].path, **optargs))
291
291
  resp = await asyncio.gather(*tasks, return_exceptions=True)
292
292
 
@@ -354,7 +354,7 @@ async def dir_to_blob(
354
354
  while progress < len(files):
355
355
  tasks = []
356
356
  for p in range(progress, progress + min(multiprocessing, len(files) - progress)):
357
- uri = dst.with_path(os.path.join(dst.path.strip("/"), relpath[p].strip("/")))
357
+ uri = dst.with_path(os.path.join(dst.path.strip("/"), relpath[p].strip("/")), encoded=True)
358
358
  tasks.append(store.upload(uri, files[p].path, **optargs))
359
359
 
360
360
  resp = await asyncio.gather(*tasks, return_exceptions=True)