rucio-clients 34.6.0__tar.gz → 35.0.0__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.6.0 → rucio_clients-35.0.0}/AUTHORS.rst +2 -0
  2. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/MANIFEST.in +1 -1
  3. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/PKG-INFO +12 -13
  4. rucio_clients-35.0.0/README.md +27 -0
  5. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/bin/rucio +34 -0
  6. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/bin/rucio-admin +8 -8
  7. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/alembicrevision.py +1 -1
  8. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/baseclient.py +60 -49
  9. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/didclient.py +2 -2
  10. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/downloadclient.py +81 -23
  11. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/subscriptionclient.py +2 -2
  12. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/uploadclient.py +127 -65
  13. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/constants.py +3 -0
  14. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/exception.py +10 -0
  15. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/plugins.py +5 -1
  16. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/atlas.py +6 -3
  17. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/belleii.py +6 -3
  18. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/domatpc.py +6 -3
  19. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/escape.py +6 -3
  20. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/generic.py +6 -3
  21. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/generic_multi_vo.py +6 -3
  22. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/icecube.py +6 -3
  23. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/types.py +90 -1
  24. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/utils.py +66 -66
  25. rucio_clients-35.0.0/lib/rucio/vcsversion.py +11 -0
  26. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio_clients.egg-info/SOURCES.txt +3 -3
  27. rucio_clients-35.0.0/requirements/requirements.client.txt +15 -0
  28. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/setup.py +2 -2
  29. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/setuputil.py +19 -12
  30. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_account.py +2 -2
  31. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_authentication.py +4 -4
  32. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_bad_replica.py +3 -3
  33. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_bin_rucio.py +18 -3
  34. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_clients.py +10 -2
  35. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_did.py +4 -4
  36. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_did_meta_plugins.py +18 -8
  37. rucio_clients-34.6.0/tests/test_api_external_representation.py → rucio_clients-35.0.0/tests/test_gateway_external_representation.py +57 -57
  38. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_lifetime.py +3 -0
  39. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_multi_vo.py +26 -26
  40. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_permission.py +3 -3
  41. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_reaper.py +18 -18
  42. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_replica.py +3 -3
  43. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rule.py +5 -5
  44. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_subscription.py +57 -9
  45. rucio_clients-34.6.0/README.rst +0 -29
  46. rucio_clients-34.6.0/lib/rucio/vcsversion.py +0 -11
  47. rucio_clients-34.6.0/requirements.txt +0 -58
  48. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/ChangeLog +0 -0
  49. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/LICENSE +0 -0
  50. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/etc/rse-accounts.cfg.template +0 -0
  51. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/etc/rucio.cfg.atlas.client.template +0 -0
  52. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/etc/rucio.cfg.template +0 -0
  53. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/__init__.py +0 -0
  54. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/__init__.py +0 -0
  55. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/accountclient.py +0 -0
  56. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/accountlimitclient.py +0 -0
  57. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/client.py +0 -0
  58. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/configclient.py +0 -0
  59. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/credentialclient.py +0 -0
  60. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/diracclient.py +0 -0
  61. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/exportclient.py +0 -0
  62. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/fileclient.py +0 -0
  63. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/importclient.py +0 -0
  64. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/lifetimeclient.py +0 -0
  65. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/lockclient.py +0 -0
  66. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/metaconventionsclient.py +0 -0
  67. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/pingclient.py +0 -0
  68. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/replicaclient.py +0 -0
  69. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/requestclient.py +0 -0
  70. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/rseclient.py +0 -0
  71. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/ruleclient.py +0 -0
  72. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/scopeclient.py +0 -0
  73. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/client/touchclient.py +0 -0
  74. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/__init__.py +0 -0
  75. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/cache.py +0 -0
  76. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/config.py +0 -0
  77. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/constraints.py +0 -0
  78. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/didtype.py +0 -0
  79. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/extra.py +0 -0
  80. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/logging.py +0 -0
  81. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/pcache.py +0 -0
  82. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/policy.py +0 -0
  83. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/schema/__init__.py +0 -0
  84. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/stomp_utils.py +0 -0
  85. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/stopwatch.py +0 -0
  86. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/common/test_rucio_server.py +0 -0
  87. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/__init__.py +0 -0
  88. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/__init__.py +0 -0
  89. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/bittorrent.py +0 -0
  90. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/cache.py +0 -0
  91. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/dummy.py +0 -0
  92. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/gfal.py +0 -0
  93. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/globus.py +0 -0
  94. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/gsiftp.py +0 -0
  95. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/http_cache.py +0 -0
  96. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/mock.py +0 -0
  97. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/ngarc.py +0 -0
  98. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/posix.py +0 -0
  99. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/protocol.py +0 -0
  100. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/rclone.py +0 -0
  101. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/rfio.py +0 -0
  102. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/srm.py +0 -0
  103. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/ssh.py +0 -0
  104. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/storm.py +0 -0
  105. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/webdav.py +0 -0
  106. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/protocols/xrootd.py +0 -0
  107. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/rse/rsemanager.py +0 -0
  108. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/lib/rucio/version.py +0 -0
  109. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/pylintrc +0 -0
  110. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/pyproject.toml +0 -0
  111. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/setup.cfg +0 -0
  112. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_abacus_account.py +0 -0
  113. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_abacus_collection_replica.py +0 -0
  114. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_abacus_rse.py +0 -0
  115. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_account_limits.py +0 -0
  116. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_archive.py +0 -0
  117. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_auditor.py +0 -0
  118. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_auditor_hdfs.py +0 -0
  119. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_auditor_srmdumps.py +0 -0
  120. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_automatix.py +0 -0
  121. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_bb8.py +0 -0
  122. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_belleii.py +0 -0
  123. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_boolean.py +0 -0
  124. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_common_types.py +0 -0
  125. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_config.py +0 -0
  126. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_conveyor.py +0 -0
  127. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_conveyor_submitter.py +0 -0
  128. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_counter.py +0 -0
  129. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_credential.py +0 -0
  130. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_curl.py +0 -0
  131. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_daemons.py +0 -0
  132. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_dataset_replicas.py +0 -0
  133. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_db.py +0 -0
  134. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_didtype.py +0 -0
  135. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_download.py +0 -0
  136. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_dumper.py +0 -0
  137. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_dumper_consistency.py +0 -0
  138. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_dumper_data_model.py +0 -0
  139. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_dumper_path_parsing.py +0 -0
  140. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_filter_engine.py +0 -0
  141. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_heartbeat.py +0 -0
  142. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_hermes.py +0 -0
  143. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_identity.py +0 -0
  144. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_impl_upload_download.py +0 -0
  145. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_import_export.py +0 -0
  146. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_judge_cleaner.py +0 -0
  147. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_judge_evaluator.py +0 -0
  148. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_judge_injector.py +0 -0
  149. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_judge_repairer.py +0 -0
  150. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_message.py +0 -0
  151. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_meta_conventions.py +0 -0
  152. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_meta_did.py +0 -0
  153. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_module_import.py +0 -0
  154. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_monitor.py +0 -0
  155. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_naming_convention.py +0 -0
  156. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_oauthmanager.py +0 -0
  157. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_oidc.py +0 -0
  158. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_pfns.py +0 -0
  159. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_ping.py +0 -0
  160. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_preparer.py +0 -0
  161. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_qos.py +0 -0
  162. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_quarantined_replica.py +0 -0
  163. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_redirect.py +0 -0
  164. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_replica_recoverer.py +0 -0
  165. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_replica_sorting.py +0 -0
  166. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_request.py +0 -0
  167. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_root_proxy.py +0 -0
  168. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse.py +0 -0
  169. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_expression_parser.py +0 -0
  170. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_lfn2path.py +0 -0
  171. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_gfal2.py +0 -0
  172. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_gfal2_impl.py +0 -0
  173. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_posix.py +0 -0
  174. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_rclone.py +0 -0
  175. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_rsync.py +0 -0
  176. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_srm.py +0 -0
  177. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_ssh.py +0 -0
  178. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_webdav.py +0 -0
  179. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_protocol_xrootd.py +0 -0
  180. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rse_selector.py +0 -0
  181. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_rucio_server.py +0 -0
  182. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_scope.py +0 -0
  183. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_throttler.py +0 -0
  184. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_tpc.py +0 -0
  185. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_trace.py +0 -0
  186. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_transfer.py +0 -0
  187. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_transfer_plugins.py +0 -0
  188. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_undertaker.py +0 -0
  189. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_upload.py +0 -0
  190. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/tests/test_utils.py +0 -0
  191. {rucio_clients-34.6.0 → rucio_clients-35.0.0}/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.6.0
3
+ Version: 35.0.0
4
4
  Summary: Rucio Client Lite Package
5
5
  Home-page: https://rucio.cern.ch/
6
6
  Author: Rucio
@@ -19,22 +19,21 @@ 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: tabulate>=0.9.0
25
+ Requires-Dist: jsonschema>=4.20.0
27
26
  Provides-Extra: ssh
28
- Requires-Dist: paramiko~=3.4.0; extra == "ssh"
27
+ Requires-Dist: paramiko>=3.4.0; extra == "ssh"
29
28
  Provides-Extra: kerberos
30
- Requires-Dist: kerberos~=1.3.1; extra == "kerberos"
31
- Requires-Dist: pykerberos~=1.2.4; extra == "kerberos"
29
+ Requires-Dist: kerberos>=1.3.1; extra == "kerberos"
30
+ Requires-Dist: pykerberos>=1.2.4; extra == "kerberos"
32
31
  Requires-Dist: requests-kerberos>=0.14.0; extra == "kerberos"
33
32
  Provides-Extra: swift
34
- Requires-Dist: python-swiftclient~=4.4.0; extra == "swift"
33
+ Requires-Dist: python-swiftclient>=4.4.0; extra == "swift"
35
34
  Provides-Extra: argcomplete
36
- Requires-Dist: argcomplete~=3.1.6; extra == "argcomplete"
35
+ Requires-Dist: argcomplete>=3.1.6; extra == "argcomplete"
37
36
  Provides-Extra: sftp
38
- Requires-Dist: paramiko~=3.4.0; extra == "sftp"
37
+ Requires-Dist: paramiko>=3.4.0; extra == "sftp"
39
38
  Provides-Extra: dumper
40
- Requires-Dist: python-magic~=0.4.27; extra == "dumper"
39
+ 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
  """
@@ -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:
@@ -25,7 +25,7 @@ import subprocess
25
25
  import time
26
26
  from queue import Empty, Queue, deque
27
27
  from threading import Thread
28
- from typing import Any, Optional
28
+ from typing import TYPE_CHECKING, Any, Optional
29
29
 
30
30
  from rucio import version
31
31
  from rucio.client.client import Client
@@ -36,6 +36,13 @@ from rucio.common.pcache import Pcache
36
36
  from rucio.common.utils import CHECKSUM_ALGO_DICT, GLOBALLY_SUPPORTED_CHECKSUMS, PREFERRED_CHECKSUM, adler32, detect_client_location, execute, extract_scope, generate_uuid, parse_replicas_from_file, parse_replicas_from_string, send_trace, sizefmt
37
37
  from rucio.rse import rsemanager as rsemgr
38
38
 
39
+ if TYPE_CHECKING:
40
+ from collections.abc import Iterable, Iterator
41
+ from xmlrpc.client import ServerProxy as RPCServerProxy
42
+
43
+ from rucio.common.constants import SORTING_ALGORITHMS_LITERAL
44
+ from rucio.common.types import LoggerFunction
45
+
39
46
 
40
47
  @enum.unique
41
48
  class FileDownloadState(str, enum.Enum):
@@ -54,7 +61,13 @@ class FileDownloadState(str, enum.Enum):
54
61
 
55
62
  class BaseExtractionTool:
56
63
 
57
- def __init__(self, program_name, useability_check_args, extract_args, logger=logging.log):
64
+ def __init__(
65
+ self,
66
+ program_name: str,
67
+ useability_check_args: str,
68
+ extract_args: str,
69
+ logger: "LoggerFunction" = logging.log
70
+ ):
58
71
  """
59
72
  Initialises a extraction tool object
60
73
 
@@ -69,7 +82,7 @@ class BaseExtractionTool:
69
82
  self.logger = logger
70
83
  self.is_useable_result = None
71
84
 
72
- def is_useable(self):
85
+ def is_useable(self) -> bool:
73
86
  """
74
87
  Checks if the extraction tool is installed and usable
75
88
 
@@ -89,7 +102,12 @@ class BaseExtractionTool:
89
102
  self.logger(logging.DEBUG, error)
90
103
  return self.is_usable_result
91
104
 
92
- def try_extraction(self, archive_file_path, file_to_extract, dest_dir_path):
105
+ def try_extraction(
106
+ self,
107
+ archive_file_path: str,
108
+ file_to_extract: str,
109
+ dest_dir_path: str
110
+ ) -> bool:
93
111
  """
94
112
  Calls the extraction program to extract a file from an archive
95
113
 
@@ -119,7 +137,14 @@ class BaseExtractionTool:
119
137
 
120
138
  class DownloadClient:
121
139
 
122
- def __init__(self, client=None, logger=None, tracing=True, check_admin=False, check_pcache=False):
140
+ def __init__(
141
+ self,
142
+ client: Optional[Client] = None,
143
+ logger: Optional["LoggerFunction"] = None,
144
+ tracing: bool = True,
145
+ check_admin: bool = False,
146
+ check_pcache: bool = False
147
+ ):
123
148
  """
124
149
  Initialises the basic settings for an DownloadClient object
125
150
 
@@ -272,7 +297,7 @@ class DownloadClient:
272
297
  trace_custom_fields: Optional[dict[str, Any]] = None,
273
298
  traces_copy_out: Optional[list[dict[str, Any]]] = None,
274
299
  deactivate_file_download_exceptions: bool = False,
275
- sort: Optional[str] = None
300
+ sort: Optional["SORTING_ALGORITHMS_LITERAL"] = None
276
301
  ) -> list[dict[str, Any]]:
277
302
  """
278
303
  Download items with given DIDs. This function can also download datasets and wildcarded DIDs.
@@ -445,7 +470,14 @@ class DownloadClient:
445
470
  thread.kill_received = True
446
471
  return list(output_queue.queue)
447
472
 
448
- def _download_worker(self, input_queue, output_queue, trace_custom_fields, traces_copy_out, log_prefix):
473
+ def _download_worker(
474
+ self,
475
+ input_queue: Queue,
476
+ output_queue: Queue,
477
+ trace_custom_fields: dict[str, Any],
478
+ traces_copy_out: Optional[list[dict[str, Any]]],
479
+ log_prefix: str
480
+ ) -> None:
449
481
  """
450
482
  This function runs as long as there are items in the input queue,
451
483
  downloads them and stores the output in the output queue.
@@ -481,7 +513,7 @@ class DownloadClient:
481
513
  output_queue.put(item)
482
514
 
483
515
  @staticmethod
484
- def _compute_actual_transfer_timeout(item):
516
+ def _compute_actual_transfer_timeout(item: dict[str, Any]) -> int:
485
517
  """
486
518
  Merge the two options related to timeout into the value which will be used for protocol download.
487
519
  :param item: dictionary that describes the item to download
@@ -493,11 +525,11 @@ class DownloadClient:
493
525
  # establishing connections and download of small files
494
526
  transfer_speed_timeout_static_increment = 60
495
527
 
496
- transfer_timeout = item.get('merged_options', {}).get('transfer_timeout')
528
+ transfer_timeout: Optional[int] = item.get('merged_options', {}).get('transfer_timeout')
497
529
  if transfer_timeout is not None:
498
530
  return transfer_timeout
499
531
 
500
- transfer_speed_timeout = item.get('merged_options', {}).get('transfer_speed_timeout')
532
+ transfer_speed_timeout: Optional[int] = item.get('merged_options', {}).get('transfer_speed_timeout')
501
533
  bytes_ = item.get('bytes')
502
534
  if not bytes_ or transfer_speed_timeout is None:
503
535
  return default_transfer_timeout
@@ -510,7 +542,13 @@ class DownloadClient:
510
542
  timeout = bytes_ // transfer_speed_timeout + transfer_speed_timeout_static_increment
511
543
  return timeout
512
544
 
513
- def _download_item(self, item, trace, traces_copy_out, log_prefix=''):
545
+ def _download_item(
546
+ self,
547
+ item: dict[str, Any],
548
+ trace: dict[str, Any],
549
+ traces_copy_out: Optional[list[dict[str, Any]]],
550
+ log_prefix: str = ''
551
+ ) -> dict[str, Any]:
514
552
  """
515
553
  Downloads the given item and sends traces for success/failure.
516
554
  (This function is meant to be used as class internal only)
@@ -775,7 +813,7 @@ class DownloadClient:
775
813
  trace_custom_fields: Optional[dict[str, Any]] = None,
776
814
  filters: Optional[dict[str, Any]] = None,
777
815
  deactivate_file_download_exceptions: bool = False,
778
- sort: Optional[str] = None
816
+ sort: Optional["SORTING_ALGORITHMS_LITERAL"] = None
779
817
  ) -> list[dict[str, Any]]:
780
818
  """
781
819
  Uses aria2c to download the items with given DIDs. This function can also download datasets and wildcarded DIDs.
@@ -838,7 +876,7 @@ class DownloadClient:
838
876
 
839
877
  return self._check_output(output_items, deactivate_file_download_exceptions=deactivate_file_download_exceptions)
840
878
 
841
- def _start_aria2c_rpc(self, rpc_secret):
879
+ def _start_aria2c_rpc(self, rpc_secret: str) -> tuple[subprocess.Popen, "RPCServerProxy"]:
842
880
  """
843
881
  Starts aria2c in RPC mode as a subprocess. Also creates
844
882
  the RPC proxy instance.
@@ -1072,7 +1110,7 @@ class DownloadClient:
1072
1110
 
1073
1111
  return items
1074
1112
 
1075
- def _resolve_one_item_dids(self, item):
1113
+ def _resolve_one_item_dids(self, item: dict[str, Any]) -> "Iterator[dict[str, Any]]":
1076
1114
  """
1077
1115
  Resolve scopes or wildcard DIDs to lists of full did names:
1078
1116
  :param item: One input item
@@ -1105,7 +1143,11 @@ class DownloadClient:
1105
1143
  if not any_did_resolved and '*' not in did_name:
1106
1144
  yield {'scope': scope, 'name': did_name}
1107
1145
 
1108
- def _resolve_and_merge_input_items(self, input_items, sort=None):
1146
+ def _resolve_and_merge_input_items(
1147
+ self,
1148
+ input_items: list[dict[str, Any]],
1149
+ sort: Optional["SORTING_ALGORITHMS_LITERAL"] = None
1150
+ ) -> tuple[dict[str, Any], list[dict[str, Any]]]:
1109
1151
  """
1110
1152
  This function takes the input items given to download_dids etc.
1111
1153
  and resolves the sources.
@@ -1282,7 +1324,7 @@ class DownloadClient:
1282
1324
 
1283
1325
  return did_to_input_items, merged_items_with_sources
1284
1326
 
1285
- def _options_from_input_items(self, input_items):
1327
+ def _options_from_input_items(self, input_items: "Iterable[dict[str, Any]]") -> dict[str, Any]:
1286
1328
  """
1287
1329
  Best-effort generation of download options from multiple input items which resolve to the same file DID.
1288
1330
  This is done to download each file DID only once, even if it is requested multiple times via overlapping
@@ -1323,7 +1365,11 @@ class DownloadClient:
1323
1365
  options['transfer_speed_timeout'] = float(new_transfer_speed_timeout)
1324
1366
  return options
1325
1367
 
1326
- def _prepare_items_for_download(self, did_to_input_items, file_items):
1368
+ def _prepare_items_for_download(
1369
+ self,
1370
+ did_to_input_items: dict[str, Any],
1371
+ file_items: list[dict[str, Any]]
1372
+ ) -> list[dict[str, Any]]:
1327
1373
  """
1328
1374
  Optimises the amount of files to download
1329
1375
  (This function is meant to be used as class internal only)
@@ -1550,7 +1596,7 @@ class DownloadClient:
1550
1596
  download_packs.append(file_item)
1551
1597
  return download_packs
1552
1598
 
1553
- def _split_did_str(self, did_str):
1599
+ def _split_did_str(self, did_str: str) -> tuple[str, str]:
1554
1600
  """
1555
1601
  Splits a given DID string (e.g. 'scope1:name.file') into its scope and name part
1556
1602
  (This function is meant to be used as class internal only)
@@ -1583,7 +1629,12 @@ class DownloadClient:
1583
1629
 
1584
1630
  return did_scope, did_name
1585
1631
 
1586
- def _prepare_dest_dir(self, base_dir, dest_dir_name, no_subdir):
1632
+ def _prepare_dest_dir(
1633
+ self,
1634
+ base_dir: str,
1635
+ dest_dir_name: str,
1636
+ no_subdir: Optional[bool]
1637
+ ) -> str:
1587
1638
  """
1588
1639
  Builds the final destination path for a file and creates the
1589
1640
  destination directory if it's not existent.
@@ -1605,7 +1656,11 @@ class DownloadClient:
1605
1656
 
1606
1657
  return dest_dir_path
1607
1658
 
1608
- def _check_output(self, output_items, deactivate_file_download_exceptions=False):
1659
+ def _check_output(
1660
+ self,
1661
+ output_items: list[dict[str, Any]],
1662
+ deactivate_file_download_exceptions: bool = False
1663
+ ) -> list[dict[str, Any]]:
1609
1664
  """
1610
1665
  Checks if all files were successfully downloaded
1611
1666
  (This function is meant to be used as class internal only)
@@ -1635,7 +1690,7 @@ class DownloadClient:
1635
1690
 
1636
1691
  return output_items
1637
1692
 
1638
- def _send_trace(self, trace):
1693
+ def _send_trace(self, trace: dict[str, Any]) -> None:
1639
1694
  """
1640
1695
  Checks if sending trace is allowed and send the trace.
1641
1696
 
@@ -1644,7 +1699,7 @@ class DownloadClient:
1644
1699
  if self.tracing:
1645
1700
  send_trace(trace, self.client.trace_host, self.client.user_agent)
1646
1701
 
1647
- def preferred_impl(self, sources):
1702
+ def preferred_impl(self, sources: list[dict[str, Any]]) -> Optional[str]:
1648
1703
  """
1649
1704
  Finds the optimum protocol impl preferred by the client and
1650
1705
  supported by the remote RSE.
@@ -1708,7 +1763,10 @@ class DownloadClient:
1708
1763
  return supported_impl
1709
1764
 
1710
1765
 
1711
- def _verify_checksum(item, path):
1766
+ def _verify_checksum(
1767
+ item: dict[str, Any],
1768
+ path: str
1769
+ ) -> tuple[bool, Optional[str], Optional[str]]:
1712
1770
  rucio_checksum = item.get(PREFERRED_CHECKSUM)
1713
1771
  local_checksum = None
1714
1772
  checksum_algo = CHECKSUM_ALGO_DICT.get(PREFERRED_CHECKSUM)
@@ -93,7 +93,7 @@ class SubscriptionClient(BaseClient):
93
93
  if name:
94
94
  path += '/%s' % (name)
95
95
  elif name:
96
- path += '/Name/%s' % (name)
96
+ path += '/name/%s' % (name)
97
97
  else:
98
98
  path += '/'
99
99
  url = build_url(choice(self.list_hosts), path=path)
@@ -163,7 +163,7 @@ class SubscriptionClient(BaseClient):
163
163
  :param name: Name of the subscription.
164
164
  """
165
165
 
166
- path = '/'.join([self.SUB_BASEURL, account, name, 'Rules'])
166
+ path = '/'.join([self.SUB_BASEURL, account, name, 'rules'])
167
167
  url = build_url(choice(self.list_hosts), path=path)
168
168
  result = self._send_request(url, type_='GET')
169
169
  if result.status_code == codes.ok: # pylint: disable=no-member