rucio-clients 34.5.0__tar.gz → 35.0.0rc1__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.

Potentially problematic release.


This version of rucio-clients might be problematic. Click here for more details.

Files changed (191) hide show
  1. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/AUTHORS.rst +2 -0
  2. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/MANIFEST.in +1 -1
  3. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/PKG-INFO +13 -13
  4. rucio_clients-35.0.0rc1/README.md +27 -0
  5. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/bin/rucio +37 -3
  6. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/bin/rucio-admin +8 -8
  7. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/alembicrevision.py +1 -1
  8. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/baseclient.py +60 -49
  9. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/didclient.py +2 -2
  10. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/diracclient.py +10 -1
  11. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/downloadclient.py +91 -27
  12. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/exportclient.py +3 -1
  13. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/fileclient.py +2 -1
  14. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/importclient.py +3 -1
  15. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/lockclient.py +15 -3
  16. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/rseclient.py +127 -43
  17. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/subscriptionclient.py +2 -2
  18. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/uploadclient.py +127 -65
  19. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/constants.py +9 -1
  20. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/exception.py +10 -0
  21. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/plugins.py +5 -1
  22. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/atlas.py +6 -3
  23. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/belleii.py +6 -3
  24. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/domatpc.py +6 -3
  25. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/escape.py +6 -3
  26. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/generic.py +6 -3
  27. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/generic_multi_vo.py +6 -3
  28. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/icecube.py +6 -3
  29. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/types.py +90 -1
  30. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/utils.py +66 -71
  31. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/rsemanager.py +4 -3
  32. rucio_clients-35.0.0rc1/lib/rucio/vcsversion.py +11 -0
  33. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio_clients.egg-info/SOURCES.txt +3 -3
  34. rucio_clients-35.0.0rc1/requirements/requirements.client.txt +15 -0
  35. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/setup.py +2 -2
  36. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/setuputil.py +17 -10
  37. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_abacus_account.py +5 -3
  38. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_abacus_rse.py +5 -3
  39. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_account.py +2 -2
  40. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_authentication.py +4 -4
  41. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_bad_replica.py +3 -3
  42. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_bin_rucio.py +30 -12
  43. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_clients.py +10 -2
  44. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_conveyor.py +44 -20
  45. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_conveyor_submitter.py +35 -15
  46. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_counter.py +24 -8
  47. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_dataset_replicas.py +202 -32
  48. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_did.py +4 -4
  49. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_did_meta_plugins.py +18 -8
  50. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_download.py +10 -0
  51. rucio_clients-34.5.0/tests/test_api_external_representation.py → rucio_clients-35.0.0rc1/tests/test_gateway_external_representation.py +57 -57
  52. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_heartbeat.py +23 -3
  53. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_import_export.py +5 -2
  54. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_judge_evaluator.py +3 -1
  55. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_judge_injector.py +7 -1
  56. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_judge_repairer.py +38 -9
  57. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_lifetime.py +3 -0
  58. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_message.py +11 -10
  59. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_meta_conventions.py +15 -4
  60. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_multi_vo.py +38 -36
  61. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_oauthmanager.py +64 -23
  62. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_oidc.py +19 -11
  63. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_permission.py +3 -3
  64. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_reaper.py +44 -30
  65. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_replica.py +3 -3
  66. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse.py +35 -5
  67. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rule.py +20 -13
  68. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_subscription.py +57 -9
  69. rucio_clients-34.5.0/README.rst +0 -29
  70. rucio_clients-34.5.0/lib/rucio/vcsversion.py +0 -11
  71. rucio_clients-34.5.0/requirements.txt +0 -58
  72. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/ChangeLog +0 -0
  73. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/LICENSE +0 -0
  74. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/etc/rse-accounts.cfg.template +0 -0
  75. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/etc/rucio.cfg.atlas.client.template +0 -0
  76. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/etc/rucio.cfg.template +0 -0
  77. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/__init__.py +0 -0
  78. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/__init__.py +0 -0
  79. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/accountclient.py +0 -0
  80. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/accountlimitclient.py +0 -0
  81. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/client.py +0 -0
  82. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/configclient.py +0 -0
  83. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/credentialclient.py +0 -0
  84. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/lifetimeclient.py +0 -0
  85. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/metaconventionsclient.py +0 -0
  86. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/pingclient.py +0 -0
  87. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/replicaclient.py +0 -0
  88. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/requestclient.py +0 -0
  89. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/ruleclient.py +0 -0
  90. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/scopeclient.py +0 -0
  91. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/client/touchclient.py +0 -0
  92. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/__init__.py +0 -0
  93. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/cache.py +0 -0
  94. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/config.py +0 -0
  95. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/constraints.py +0 -0
  96. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/didtype.py +0 -0
  97. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/extra.py +0 -0
  98. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/logging.py +0 -0
  99. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/pcache.py +0 -0
  100. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/policy.py +0 -0
  101. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/schema/__init__.py +0 -0
  102. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/stomp_utils.py +0 -0
  103. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/stopwatch.py +0 -0
  104. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/common/test_rucio_server.py +0 -0
  105. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/__init__.py +0 -0
  106. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/__init__.py +0 -0
  107. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/bittorrent.py +0 -0
  108. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/cache.py +0 -0
  109. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/dummy.py +0 -0
  110. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/gfal.py +0 -0
  111. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/globus.py +0 -0
  112. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/gsiftp.py +0 -0
  113. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/http_cache.py +0 -0
  114. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/mock.py +0 -0
  115. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/ngarc.py +0 -0
  116. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/posix.py +0 -0
  117. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/protocol.py +0 -0
  118. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/rclone.py +0 -0
  119. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/rfio.py +0 -0
  120. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/srm.py +0 -0
  121. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/ssh.py +0 -0
  122. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/storm.py +0 -0
  123. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/webdav.py +0 -0
  124. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/rse/protocols/xrootd.py +0 -0
  125. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/lib/rucio/version.py +0 -0
  126. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/pylintrc +0 -0
  127. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/pyproject.toml +0 -0
  128. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/setup.cfg +0 -0
  129. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_abacus_collection_replica.py +0 -0
  130. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_account_limits.py +0 -0
  131. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_archive.py +0 -0
  132. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_auditor.py +0 -0
  133. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_auditor_hdfs.py +0 -0
  134. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_auditor_srmdumps.py +0 -0
  135. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_automatix.py +0 -0
  136. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_bb8.py +0 -0
  137. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_belleii.py +0 -0
  138. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_boolean.py +0 -0
  139. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_common_types.py +0 -0
  140. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_config.py +0 -0
  141. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_credential.py +0 -0
  142. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_curl.py +0 -0
  143. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_daemons.py +0 -0
  144. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_db.py +0 -0
  145. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_didtype.py +0 -0
  146. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_dumper.py +0 -0
  147. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_dumper_consistency.py +0 -0
  148. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_dumper_data_model.py +0 -0
  149. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_dumper_path_parsing.py +0 -0
  150. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_filter_engine.py +0 -0
  151. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_hermes.py +0 -0
  152. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_identity.py +0 -0
  153. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_impl_upload_download.py +0 -0
  154. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_judge_cleaner.py +0 -0
  155. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_meta_did.py +0 -0
  156. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_module_import.py +0 -0
  157. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_monitor.py +0 -0
  158. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_naming_convention.py +0 -0
  159. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_pfns.py +0 -0
  160. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_ping.py +0 -0
  161. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_preparer.py +0 -0
  162. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_qos.py +0 -0
  163. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_quarantined_replica.py +0 -0
  164. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_redirect.py +0 -0
  165. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_replica_recoverer.py +0 -0
  166. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_replica_sorting.py +0 -0
  167. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_request.py +0 -0
  168. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_root_proxy.py +0 -0
  169. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_expression_parser.py +0 -0
  170. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_lfn2path.py +0 -0
  171. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_gfal2.py +0 -0
  172. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_gfal2_impl.py +0 -0
  173. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_posix.py +0 -0
  174. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_rclone.py +0 -0
  175. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_rsync.py +0 -0
  176. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_srm.py +0 -0
  177. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_ssh.py +0 -0
  178. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_webdav.py +0 -0
  179. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_protocol_xrootd.py +0 -0
  180. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rse_selector.py +0 -0
  181. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_rucio_server.py +0 -0
  182. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_scope.py +0 -0
  183. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_throttler.py +0 -0
  184. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_tpc.py +0 -0
  185. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_trace.py +0 -0
  186. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_transfer.py +0 -0
  187. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_transfer_plugins.py +0 -0
  188. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_undertaker.py +0 -0
  189. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_upload.py +0 -0
  190. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tests/test_utils.py +0 -0
  191. {rucio_clients-34.5.0 → rucio_clients-35.0.0rc1}/tools/merge_rucio_configs.py +0 -0
@@ -66,6 +66,7 @@ Individual contributors to the source code
66
66
  - Jensen Zhang <hack@jensen-zhang.site>, 2022
67
67
  - Aksel Lunde Aase <aksel.lunde.aase@gmail.com>, 2022
68
68
  - Elena Gazzarrini <gazzarrini.elena@gmail.com>, 2022-2023
69
+ - Maximilian Linhoff, <maximilian.linhoff@tu-dortmund.de>, 2024
69
70
 
70
71
  Organisations employing contributors
71
72
  ------------------------------------
@@ -93,3 +94,4 @@ Organisations employing contributors
93
94
  - Imperial College London (UK)
94
95
  - University of Chicago (USA)
95
96
  - Purdue University (USA)
97
+ - TU Dortmund University (Germany)
@@ -7,7 +7,7 @@ include setuputil.py
7
7
  include setup.py
8
8
  include setup.cfg
9
9
  include pyproject.toml
10
- include requirements.txt
10
+ include requirements/requirements.client.txt
11
11
  include etc/rse-accounts.cfg.template
12
12
  include etc/rucio.cfg.atlas.client.template
13
13
  include etc/rucio.cfg.template
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rucio-clients
3
- Version: 34.5.0
3
+ Version: 35.0.0rc1
4
4
  Summary: Rucio Client Lite Package
5
5
  Home-page: https://rucio.cern.ch/
6
6
  Author: Rucio
@@ -19,22 +19,22 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Requires-Python: >=3.9, <4
20
20
  License-File: LICENSE
21
21
  License-File: AUTHORS.rst
22
- Requires-Dist: requests~=2.32.0
23
- Requires-Dist: urllib3~=1.26.18
24
- Requires-Dist: dogpile.cache~=1.2.2
25
- Requires-Dist: tabulate~=0.9.0
26
- Requires-Dist: jsonschema~=4.20.0
22
+ Requires-Dist: requests>=2.32.2
23
+ Requires-Dist: urllib3>=1.26.18
24
+ Requires-Dist: dogpile.cache>=1.2.2
25
+ Requires-Dist: tabulate>=0.9.0
26
+ Requires-Dist: jsonschema>=4.20.0
27
27
  Provides-Extra: ssh
28
- Requires-Dist: paramiko~=3.4.0; extra == "ssh"
28
+ Requires-Dist: paramiko>=3.4.0; extra == "ssh"
29
29
  Provides-Extra: kerberos
30
- Requires-Dist: kerberos~=1.3.1; extra == "kerberos"
31
- Requires-Dist: pykerberos~=1.2.4; extra == "kerberos"
30
+ Requires-Dist: kerberos>=1.3.1; extra == "kerberos"
31
+ Requires-Dist: pykerberos>=1.2.4; extra == "kerberos"
32
32
  Requires-Dist: requests-kerberos>=0.14.0; extra == "kerberos"
33
33
  Provides-Extra: swift
34
- Requires-Dist: python-swiftclient~=4.4.0; extra == "swift"
34
+ Requires-Dist: python-swiftclient>=4.4.0; extra == "swift"
35
35
  Provides-Extra: argcomplete
36
- Requires-Dist: argcomplete~=3.1.6; extra == "argcomplete"
36
+ Requires-Dist: argcomplete>=3.1.6; extra == "argcomplete"
37
37
  Provides-Extra: sftp
38
- Requires-Dist: paramiko~=3.4.0; extra == "sftp"
38
+ Requires-Dist: paramiko>=3.4.0; extra == "sftp"
39
39
  Provides-Extra: dumper
40
- Requires-Dist: python-magic~=0.4.27; extra == "dumper"
40
+ Requires-Dist: python-magic>=0.4.27; extra == "dumper"
@@ -0,0 +1,27 @@
1
+ # Rucio - Scientific Data Management
2
+
3
+ Rucio is a software framework that provides functionality to organize, manage, and access large volumes of scientific data using customisable policies.
4
+ The data can be spread across globally distributed locations and across heterogeneous data centers, uniting different storage and network technologies as a single federated entity.
5
+ Rucio offers advanced features such as distributed data recovery or adaptive replication, and is highly scalable, modular, and extensible.
6
+ Rucio has been originally developed to meet the requirements of the high-energy physics experiment ATLAS, and is continuously extended to support LHC experiments and other diverse scientific communities.
7
+
8
+ ## Documentation
9
+
10
+ General information, API/REST description and guides can be found in our [documentation](https://rucio.cern.ch/documentation) or on our [webpage](https://rucio.cern.ch).
11
+
12
+ ## Try it out
13
+
14
+ We provide a [dockerized environment](https://github.com/rucio/rucio/tree/master/etc/docker/dev) which serves both as a demo environment and a development environment.
15
+ It includes all the necessary preconfigured components for multiple storage and transfers developments.
16
+
17
+ ## Developers
18
+
19
+ For information on how to contribute to Rucio, please refer and follow our [CONTRIBUTING](https://rucio.cern.ch/documentation/contributing) guidelines. We strongly recommend to use the [dockerized environment](https://github.com/rucio/rucio/tree/master/etc/docker/dev) for development.
20
+
21
+ ## Operators
22
+
23
+ To learn how to deploy and configure Rucio, consult the [documentation](https://rucio.cern.ch/documentation) available online.
24
+
25
+ ## Getting Support
26
+
27
+ If you are looking for support, please contact us via one of our [official channels](https://rucio.cern.ch/documentation/contact_us/).
@@ -30,6 +30,7 @@ from configparser import NoOptionError, NoSectionError
30
30
  from copy import deepcopy
31
31
  from datetime import datetime
32
32
  from functools import wraps
33
+ from typing import Optional
33
34
 
34
35
  from tabulate import tabulate
35
36
 
@@ -1079,6 +1080,24 @@ def download(args):
1079
1080
  logger.debug(args.dids)
1080
1081
  item_defaults['pfn'] = args.pfn
1081
1082
  item_defaults['did'] = did_str
1083
+ if args.rses is None:
1084
+ logger.warning("No RSE was given, selecting one.")
1085
+ client = get_client(args)
1086
+ replicas = client.list_replicas(
1087
+ [{"scope": did_str.split(':')[0], "name": did_str.split(':')[-1]}],
1088
+ schemes=args.protocol,
1089
+ ignore_availability=False,
1090
+ client_location=detect_client_location(),
1091
+ resolve_archives=not args.no_resolve_archives
1092
+ )
1093
+
1094
+ download_rse = _get_rse_for_pfn(replicas, args.pfn)
1095
+ if download_rse is None:
1096
+ logger.error("Could not find RSE for pfn %s", args.pfn)
1097
+ return FAILURE
1098
+ else:
1099
+ item_defaults['rse'] = download_rse
1100
+
1082
1101
  result = download_client.download_pfns([item_defaults], 1, trace_pattern, deactivate_file_download_exceptions=deactivate_file_download_exceptions)
1083
1102
 
1084
1103
  if not result:
@@ -1120,6 +1139,21 @@ def download(args):
1120
1139
  return SUCCESS
1121
1140
 
1122
1141
 
1142
+ def _get_rse_for_pfn(replicas, pfn) -> Optional[str]:
1143
+ # Check each rse in the replica list for the pfn. If no pfn is found, returns None.
1144
+ # If it is found, stop the generator and return the item.
1145
+ for replica in replicas:
1146
+ try:
1147
+ download_rse = next(
1148
+ rse for rse in replica['rses']
1149
+ if pfn in replica['rses'][rse]
1150
+ )
1151
+ except StopIteration:
1152
+ continue
1153
+ else:
1154
+ return download_rse
1155
+
1156
+
1123
1157
  @exception_handler
1124
1158
  def get_metadata(args):
1125
1159
  """
@@ -1929,7 +1963,7 @@ To list the missing replica of a dataset of a given RSE-expression::
1929
1963
  list_file_replicas_parser.add_argument('--no-resolve-archives', dest='no_resolve_archives', default=False, action='store_true', help='Do not resolve archives which may contain the files.', required=False)
1930
1964
  list_file_replicas_parser.add_argument('--sort', dest='sort', default=None, action='store', help='Replica sort algorithm. Available options: geoip (default), random', required=False)
1931
1965
  list_file_replicas_parser.add_argument('--rses', dest='rses', default=None, action='store', help='The RSE filter expression. A comprehensive help about RSE expressions\
1932
- can be found in ' + Color.BOLD + 'http://rucio.cern.ch/documentation/rse_expressions/' + Color.END)
1966
+ can be found in ' + Color.BOLD + 'https://rucio.cern.ch/documentation/started/concepts/rse_expressions' + Color.END)
1933
1967
 
1934
1968
  # The list-dataset-replicas command
1935
1969
  list_dataset_replicas_parser = subparsers.add_parser('list-dataset-replicas', help='List the dataset replicas.',
@@ -2431,13 +2465,13 @@ You can filter by account::
2431
2465
  list_rses_parser = subparsers.add_parser('list-rses', help='Show the list of all the registered Rucio Storage Elements (RSEs).')
2432
2466
  list_rses_parser.set_defaults(function=list_rses)
2433
2467
  list_rses_parser.add_argument('--rses', dest='rses', action='store', help='The RSE filter expression. A comprehensive help about RSE expressions \
2434
- can be found in ' + Color.BOLD + 'http://rucio.cern.ch/documentation/rse_expressions/' + Color.END)
2468
+ can be found in ' + Color.BOLD + 'https://rucio.cern.ch/documentation/started/concepts/rse_expressions' + Color.END)
2435
2469
 
2436
2470
  # The list-suspicious-replicas command
2437
2471
  list_suspicious_replicas_parser = subparsers.add_parser('list-suspicious-replicas', help='Show the list of all replicas marked "suspicious".')
2438
2472
  list_suspicious_replicas_parser.set_defaults(function=list_suspicious_replicas)
2439
2473
  list_suspicious_replicas_parser.add_argument('--expression', dest='rse_expression', action='store', help='The RSE filter expression. A comprehensive help about RSE expressions \
2440
- can be found in ' + Color.BOLD + 'http://rucio.cern.ch/documentation/rse_expressions/' + Color.END)
2474
+ can be found in ' + Color.BOLD + 'https://rucio.cern.ch/documentation/started/concepts/rse_expressions' + Color.END)
2441
2475
  list_suspicious_replicas_parser.add_argument('--younger_than', '--younger-than', new_option_string='--younger-than', dest='younger_than', action=StoreAndDeprecateWarningAction, help='List files that have been marked suspicious since the date "younger_than", e.g. 2021-11-29T00:00:00.') # NOQA: E501
2442
2476
  list_suspicious_replicas_parser.add_argument('--nattempts', dest='nattempts', action='store', help='Minimum number of failed attempts to access a suspicious file.')
2443
2477
 
@@ -54,7 +54,7 @@ from rucio.common.exception import (
54
54
  ScopeNotFound,
55
55
  )
56
56
  from rucio.common.extra import import_extras
57
- from rucio.common.utils import StoreAndDeprecateWarningAction, chunks, clean_surls, construct_surl, extract_scope, get_bytes_value_from_string, parse_response, render_json, sizefmt
57
+ from rucio.common.utils import StoreAndDeprecateWarningAction, chunks, clean_pfns, construct_non_deterministic_pfn, extract_scope, get_bytes_value_from_string, parse_response, render_json, sizefmt
58
58
  from rucio.rse import rsemanager as rsemgr
59
59
 
60
60
  EXTRA_MODULES = import_extras(['argcomplete'])
@@ -1148,21 +1148,21 @@ def declare_bad_file_replicas(args):
1148
1148
  list_bad_pfns = []
1149
1149
  cnt += 1
1150
1150
  previous_pattern = None
1151
- for surl in clean_surls(chunk):
1151
+ for pfn in clean_pfns(chunk):
1152
1152
  unknown = True
1153
1153
  if previous_pattern:
1154
- if previous_pattern in surl:
1155
- list_bad_pfns.append(surl)
1154
+ if previous_pattern in pfn:
1155
+ list_bad_pfns.append(pfn)
1156
1156
  unknown = False
1157
1157
  continue
1158
1158
  for pattern in prot_dict:
1159
- if pattern in surl:
1159
+ if pattern in pfn:
1160
1160
  previous_pattern = prot_dict[pattern]
1161
- list_bad_pfns.append(surl)
1161
+ list_bad_pfns.append(pfn)
1162
1162
  unknown = False
1163
1163
  break
1164
1164
  if unknown:
1165
- print('Cannot find any RSE associated to %s' % surl)
1165
+ print('Cannot find any RSE associated to %s' % pfn)
1166
1166
  client.add_bad_pfns(pfns=list_bad_pfns, reason=args.reason, state='BAD', expires_at=None)
1167
1167
  ndeclared = len(list_bad_pfns)
1168
1168
  tot_file_declared += ndeclared
@@ -1251,7 +1251,7 @@ def list_pfns(args):
1251
1251
  logger.warning('The file has multiple parents')
1252
1252
  for did in parents:
1253
1253
  if did['type'] == 'DATASET':
1254
- path = construct_surl(did['name'], scope, name, naming_convention=naming_convention)
1254
+ path = construct_non_deterministic_pfn(did['name'], scope, name, naming_convention=naming_convention)
1255
1255
  pfn = ''.join([proto.attributes['scheme'],
1256
1256
  '://',
1257
1257
  proto.attributes['hostname'],
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- ALEMBIC_REVISION = 'a08fa8de1545' # the current alembic head revision
15
+ ALEMBIC_REVISION = 'b0070f3695c8' # the current alembic head revision
@@ -137,8 +137,6 @@ class BaseClient:
137
137
  self.logger.debug('No trace_host passed. Using rucio_host instead')
138
138
 
139
139
  self.list_hosts = [self.host]
140
- self.account = account
141
- self.vo = vo
142
140
  self.ca_cert = ca_cert
143
141
  self.auth_token = ""
144
142
  self.headers = {}
@@ -173,7 +171,9 @@ class BaseClient:
173
171
  self.logger.debug('No ca_cert found in configuration. Falling back to Mozilla default CA bundle (certifi).')
174
172
  self.ca_cert = True
175
173
 
176
- if account is None:
174
+ if account is not None:
175
+ self.account = account
176
+ else:
177
177
  self.logger.debug('No account passed. Trying to get it from the RUCIO_ACCOUNT environment variable or the config file.')
178
178
  try:
179
179
  self.account = environ['RUCIO_ACCOUNT']
@@ -183,7 +183,9 @@ class BaseClient:
183
183
  except (NoOptionError, NoSectionError):
184
184
  pass
185
185
 
186
- if vo is None:
186
+ if vo is not None:
187
+ self.vo = vo
188
+ else:
187
189
  self.logger.debug('No VO passed. Trying to get it from environment variable RUCIO_VO.')
188
190
  try:
189
191
  self.vo = environ['RUCIO_VO']
@@ -239,57 +241,62 @@ class BaseClient:
239
241
  return auth_type
240
242
 
241
243
  def _get_creds(self, creds: Optional[dict[str, Any]]) -> dict[str, Any]:
242
- if self.auth_type == 'oidc':
243
- if not creds:
244
- creds = {}
245
- # if there are default values, check if rucio.cfg does not specify them, otherwise put default
246
- if 'oidc_refresh_lifetime' not in creds or creds['oidc_refresh_lifetime'] is None:
247
- creds['oidc_refresh_lifetime'] = config_get('client', 'oidc_refresh_lifetime', False, None)
248
- if 'oidc_issuer' not in creds or creds['oidc_issuer'] is None:
249
- creds['oidc_issuer'] = config_get('client', 'oidc_issuer', False, None)
250
- if 'oidc_audience' not in creds or creds['oidc_audience'] is None:
251
- creds['oidc_audience'] = config_get('client', 'oidc_audience', False, None)
252
- if 'oidc_auto' not in creds or creds['oidc_auto'] is False:
253
- creds['oidc_auto'] = config_get_bool('client', 'oidc_auto', False, False)
254
- if creds['oidc_auto']:
255
- if 'oidc_username' not in creds or creds['oidc_username'] is None:
256
- creds['oidc_username'] = config_get('client', 'oidc_username', False, None)
257
- if 'oidc_password' not in creds or creds['oidc_password'] is None:
258
- creds['oidc_password'] = config_get('client', 'oidc_password', False, None)
259
- if 'oidc_scope' not in creds or creds['oidc_scope'] == 'openid profile':
260
- creds['oidc_scope'] = config_get('client', 'oidc_scope', False, 'openid profile')
261
- if 'oidc_polling' not in creds or creds['oidc_polling'] is False:
262
- creds['oidc_polling'] = config_get_bool('client', 'oidc_polling', False, False)
263
-
264
- if creds is None:
244
+ if not creds:
265
245
  self.logger.debug('No creds passed. Trying to get it from the config file.')
266
246
  creds = {}
267
- try:
268
- if self.auth_type in ['userpass', 'saml']:
247
+
248
+ try:
249
+ if self.auth_type == 'oidc':
250
+ # if there are default values, check if rucio.cfg does not specify them, otherwise put default
251
+ if 'oidc_refresh_lifetime' not in creds or creds['oidc_refresh_lifetime'] is None:
252
+ creds['oidc_refresh_lifetime'] = config_get('client', 'oidc_refresh_lifetime', False, None)
253
+ if 'oidc_issuer' not in creds or creds['oidc_issuer'] is None:
254
+ creds['oidc_issuer'] = config_get('client', 'oidc_issuer', False, None)
255
+ if 'oidc_audience' not in creds or creds['oidc_audience'] is None:
256
+ creds['oidc_audience'] = config_get('client', 'oidc_audience', False, None)
257
+ if 'oidc_auto' not in creds or creds['oidc_auto'] is False:
258
+ creds['oidc_auto'] = config_get_bool('client', 'oidc_auto', False, False)
259
+ if creds['oidc_auto']:
260
+ if 'oidc_username' not in creds or creds['oidc_username'] is None:
261
+ creds['oidc_username'] = config_get('client', 'oidc_username', False, None)
262
+ if 'oidc_password' not in creds or creds['oidc_password'] is None:
263
+ creds['oidc_password'] = config_get('client', 'oidc_password', False, None)
264
+ if 'oidc_scope' not in creds or creds['oidc_scope'] == 'openid profile':
265
+ creds['oidc_scope'] = config_get('client', 'oidc_scope', False, 'openid profile')
266
+ if 'oidc_polling' not in creds or creds['oidc_polling'] is False:
267
+ creds['oidc_polling'] = config_get_bool('client', 'oidc_polling', False, False)
268
+
269
+ elif self.auth_type in ['userpass', 'saml']:
270
+ if 'username' not in creds or creds['username'] is None:
269
271
  creds['username'] = config_get('client', 'username')
272
+ if 'password' not in creds or creds['password'] is None:
270
273
  creds['password'] = config_get('client', 'password')
271
- elif self.auth_type == 'x509':
274
+
275
+ elif self.auth_type == 'x509':
276
+ if 'client_cert' not in creds or creds['client_cert'] is None:
272
277
  if "RUCIO_CLIENT_CERT" in environ:
273
- client_cert = environ["RUCIO_CLIENT_CERT"]
278
+ creds['client_cert'] = environ["RUCIO_CLIENT_CERT"]
274
279
  else:
275
- client_cert = config_get('client', 'client_cert')
276
- creds['client_cert'] = path.abspath(path.expanduser(path.expandvars(client_cert)))
277
- if not path.exists(creds['client_cert']):
278
- raise MissingClientParameter('X.509 client certificate not found: %s' % creds['client_cert'])
280
+ creds['client_cert'] = config_get('client', 'client_cert')
281
+ creds['client_cert'] = path.abspath(path.expanduser(path.expandvars(creds['client_cert'])))
282
+ if not path.exists(creds['client_cert']):
283
+ raise MissingClientParameter('X.509 client certificate not found: %s' % creds['client_cert'])
279
284
 
285
+ if 'client_key' not in creds or creds['client_key'] is None:
280
286
  if "RUCIO_CLIENT_KEY" in environ:
281
- client_key = environ["RUCIO_CLIENT_KEY"]
282
- else:
283
- client_key = config_get('client', 'client_key')
284
- creds['client_key'] = path.abspath(path.expanduser(path.expandvars(client_key)))
285
- if not path.exists(creds['client_key']):
286
- raise MissingClientParameter('X.509 client key not found: %s' % creds['client_key'])
287
+ creds['client_key'] = environ["RUCIO_CLIENT_KEY"]
287
288
  else:
288
- perms = oct(os.stat(creds['client_key']).st_mode)[-3:]
289
- if perms not in ['400', '600']:
290
- raise CannotAuthenticate('X.509 authentication selected, but private key (%s) permissions are liberal (required: 400 or 600, found: %s)' % (creds['client_key'], perms))
289
+ creds['client_key'] = config_get('client', 'client_key')
290
+ creds['client_key'] = path.abspath(path.expanduser(path.expandvars(creds['client_key'])))
291
+ if not path.exists(creds['client_key']):
292
+ raise MissingClientParameter('X.509 client key not found: %s' % creds['client_key'])
293
+ else:
294
+ perms = oct(os.stat(creds['client_key']).st_mode)[-3:]
295
+ if perms not in ['400', '600']:
296
+ raise CannotAuthenticate('X.509 authentication selected, but private key (%s) permissions are liberal (required: 400 or 600, found: %s)' % (creds['client_key'], perms))
291
297
 
292
- elif self.auth_type == 'x509_proxy':
298
+ elif self.auth_type == 'x509_proxy':
299
+ if 'client_proxy' not in creds or creds['client_proxy'] is None:
293
300
  try:
294
301
  creds['client_proxy'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_x509_proxy'))))
295
302
  except NoOptionError:
@@ -307,11 +314,15 @@ class BaseClient:
307
314
  raise MissingClientParameter(
308
315
  'Cannot find a valid X509 proxy; not in %s, $X509_USER_PROXY not set, and '
309
316
  '\'x509_proxy\' not set in the configuration file.' % fname)
310
- elif self.auth_type == 'ssh':
317
+
318
+ elif self.auth_type == 'ssh':
319
+ if 'ssh_private_key' not in creds or creds['ssh_private_key'] is None:
311
320
  creds['ssh_private_key'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'ssh_private_key'))))
312
- except (NoOptionError, NoSectionError) as error:
313
- if error.args[0] != 'client_key':
314
- raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
321
+
322
+ except (NoOptionError, NoSectionError) as error:
323
+ if error.args[0] != 'client_key':
324
+ raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
325
+
315
326
  return creds
316
327
 
317
328
  def _get_exception(self, headers: dict[str, str], status_code: Optional[int] = None, data=None) -> tuple[type[exception.RucioException], str]:
@@ -21,7 +21,7 @@ from requests.status_codes import codes
21
21
 
22
22
  from rucio.client.baseclient import BaseClient, choice
23
23
  from rucio.common.exception import DeprecationError
24
- from rucio.common.utils import build_url, date_to_str, render_json, render_json_list
24
+ from rucio.common.utils import build_url, date_to_str, render_json
25
25
 
26
26
  if TYPE_CHECKING:
27
27
  from collections.abc import Iterable, Iterator, Mapping, Sequence
@@ -142,7 +142,7 @@ class DIDClient(BaseClient):
142
142
  """
143
143
  path = '/'.join([self.DIDS_BASEURL])
144
144
  url = build_url(choice(self.list_hosts), path=path)
145
- r = self._send_request(url, type_='POST', data=render_json_list(dids))
145
+ r = self._send_request(url, type_='POST', data=render_json(dids))
146
146
  if r.status_code == codes.created:
147
147
  return True
148
148
  else:
@@ -13,12 +13,16 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from json import dumps
16
+ from typing import TYPE_CHECKING, Any, Literal, Optional
16
17
 
17
18
  from requests.status_codes import codes
18
19
 
19
20
  from rucio.client.baseclient import BaseClient, choice
20
21
  from rucio.common.utils import build_url
21
22
 
23
+ if TYPE_CHECKING:
24
+ from collections.abc import Iterable, Mapping
25
+
22
26
 
23
27
  class DiracClient(BaseClient):
24
28
 
@@ -26,7 +30,12 @@ class DiracClient(BaseClient):
26
30
 
27
31
  DIRAC_BASEURL = 'dirac'
28
32
 
29
- def add_files(self, lfns, ignore_availability=False, parents_metadata=None):
33
+ def add_files(
34
+ self,
35
+ lfns: "Iterable[Mapping[str, Any]]",
36
+ ignore_availability: bool = False,
37
+ parents_metadata: Optional["Mapping[str, Mapping[str, Any]]"] = None
38
+ ) -> Literal[True]:
30
39
  """
31
40
  Bulk add files :
32
41
  - Create the file and replica.