rucio 32.8.6__py3-none-any.whl → 35.8.0__py3-none-any.whl

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 might be problematic. Click here for more details.

Files changed (502) hide show
  1. rucio/__init__.py +0 -1
  2. rucio/alembicrevision.py +1 -2
  3. rucio/client/__init__.py +0 -1
  4. rucio/client/accountclient.py +45 -25
  5. rucio/client/accountlimitclient.py +37 -9
  6. rucio/client/baseclient.py +199 -154
  7. rucio/client/client.py +2 -3
  8. rucio/client/configclient.py +19 -6
  9. rucio/client/credentialclient.py +9 -4
  10. rucio/client/didclient.py +238 -63
  11. rucio/client/diracclient.py +13 -5
  12. rucio/client/downloadclient.py +162 -51
  13. rucio/client/exportclient.py +4 -4
  14. rucio/client/fileclient.py +3 -4
  15. rucio/client/importclient.py +4 -4
  16. rucio/client/lifetimeclient.py +21 -5
  17. rucio/client/lockclient.py +18 -8
  18. rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
  19. rucio/client/pingclient.py +0 -1
  20. rucio/client/replicaclient.py +15 -5
  21. rucio/client/requestclient.py +35 -19
  22. rucio/client/rseclient.py +133 -51
  23. rucio/client/ruleclient.py +29 -22
  24. rucio/client/scopeclient.py +8 -6
  25. rucio/client/subscriptionclient.py +47 -35
  26. rucio/client/touchclient.py +8 -4
  27. rucio/client/uploadclient.py +166 -82
  28. rucio/common/__init__.py +0 -1
  29. rucio/common/cache.py +4 -4
  30. rucio/common/config.py +52 -47
  31. rucio/common/constants.py +69 -2
  32. rucio/common/constraints.py +0 -1
  33. rucio/common/didtype.py +24 -22
  34. rucio/common/dumper/__init__.py +70 -41
  35. rucio/common/dumper/consistency.py +26 -22
  36. rucio/common/dumper/data_models.py +16 -23
  37. rucio/common/dumper/path_parsing.py +0 -1
  38. rucio/common/exception.py +281 -222
  39. rucio/common/extra.py +0 -1
  40. rucio/common/logging.py +54 -38
  41. rucio/common/pcache.py +122 -101
  42. rucio/common/plugins.py +153 -0
  43. rucio/common/policy.py +4 -4
  44. rucio/common/schema/__init__.py +17 -10
  45. rucio/common/schema/atlas.py +7 -5
  46. rucio/common/schema/belleii.py +7 -5
  47. rucio/common/schema/domatpc.py +7 -5
  48. rucio/common/schema/escape.py +7 -5
  49. rucio/common/schema/generic.py +8 -6
  50. rucio/common/schema/generic_multi_vo.py +7 -5
  51. rucio/common/schema/icecube.py +7 -5
  52. rucio/common/stomp_utils.py +0 -1
  53. rucio/common/stopwatch.py +0 -1
  54. rucio/common/test_rucio_server.py +2 -2
  55. rucio/common/types.py +262 -17
  56. rucio/common/utils.py +743 -451
  57. rucio/core/__init__.py +0 -1
  58. rucio/core/account.py +99 -29
  59. rucio/core/account_counter.py +89 -24
  60. rucio/core/account_limit.py +90 -24
  61. rucio/core/authentication.py +86 -29
  62. rucio/core/config.py +108 -38
  63. rucio/core/credential.py +14 -7
  64. rucio/core/did.py +680 -782
  65. rucio/core/did_meta_plugins/__init__.py +8 -6
  66. rucio/core/did_meta_plugins/did_column_meta.py +17 -12
  67. rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
  68. rucio/core/did_meta_plugins/filter_engine.py +90 -50
  69. rucio/core/did_meta_plugins/json_meta.py +41 -16
  70. rucio/core/did_meta_plugins/mongo_meta.py +25 -8
  71. rucio/core/did_meta_plugins/postgres_meta.py +3 -4
  72. rucio/core/dirac.py +46 -17
  73. rucio/core/distance.py +66 -43
  74. rucio/core/exporter.py +5 -5
  75. rucio/core/heartbeat.py +181 -81
  76. rucio/core/identity.py +22 -12
  77. rucio/core/importer.py +23 -12
  78. rucio/core/lifetime_exception.py +32 -32
  79. rucio/core/lock.py +244 -142
  80. rucio/core/message.py +79 -38
  81. rucio/core/{meta.py → meta_conventions.py} +57 -44
  82. rucio/core/monitor.py +19 -13
  83. rucio/core/naming_convention.py +68 -27
  84. rucio/core/nongrid_trace.py +17 -5
  85. rucio/core/oidc.py +151 -29
  86. rucio/core/permission/__init__.py +18 -6
  87. rucio/core/permission/atlas.py +50 -35
  88. rucio/core/permission/belleii.py +6 -5
  89. rucio/core/permission/escape.py +8 -6
  90. rucio/core/permission/generic.py +82 -80
  91. rucio/core/permission/generic_multi_vo.py +9 -7
  92. rucio/core/quarantined_replica.py +91 -58
  93. rucio/core/replica.py +1303 -772
  94. rucio/core/replica_sorter.py +10 -12
  95. rucio/core/request.py +1133 -285
  96. rucio/core/rse.py +142 -102
  97. rucio/core/rse_counter.py +49 -18
  98. rucio/core/rse_expression_parser.py +6 -7
  99. rucio/core/rse_selector.py +41 -16
  100. rucio/core/rule.py +1538 -474
  101. rucio/core/rule_grouping.py +213 -68
  102. rucio/core/scope.py +50 -22
  103. rucio/core/subscription.py +92 -44
  104. rucio/core/topology.py +66 -24
  105. rucio/core/trace.py +42 -28
  106. rucio/core/transfer.py +543 -259
  107. rucio/core/vo.py +36 -18
  108. rucio/core/volatile_replica.py +59 -32
  109. rucio/daemons/__init__.py +0 -1
  110. rucio/daemons/abacus/__init__.py +0 -1
  111. rucio/daemons/abacus/account.py +29 -19
  112. rucio/daemons/abacus/collection_replica.py +21 -10
  113. rucio/daemons/abacus/rse.py +22 -12
  114. rucio/daemons/atropos/__init__.py +0 -1
  115. rucio/daemons/atropos/atropos.py +1 -2
  116. rucio/daemons/auditor/__init__.py +56 -28
  117. rucio/daemons/auditor/hdfs.py +17 -6
  118. rucio/daemons/auditor/srmdumps.py +116 -45
  119. rucio/daemons/automatix/__init__.py +0 -1
  120. rucio/daemons/automatix/automatix.py +30 -18
  121. rucio/daemons/badreplicas/__init__.py +0 -1
  122. rucio/daemons/badreplicas/minos.py +29 -18
  123. rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
  124. rucio/daemons/badreplicas/necromancer.py +9 -13
  125. rucio/daemons/bb8/__init__.py +0 -1
  126. rucio/daemons/bb8/bb8.py +10 -13
  127. rucio/daemons/bb8/common.py +151 -154
  128. rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
  129. rucio/daemons/bb8/t2_background_rebalance.py +15 -8
  130. rucio/daemons/c3po/__init__.py +0 -1
  131. rucio/daemons/c3po/algorithms/__init__.py +0 -1
  132. rucio/daemons/c3po/algorithms/simple.py +8 -5
  133. rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
  134. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
  135. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
  136. rucio/daemons/c3po/c3po.py +81 -52
  137. rucio/daemons/c3po/collectors/__init__.py +0 -1
  138. rucio/daemons/c3po/collectors/agis.py +17 -17
  139. rucio/daemons/c3po/collectors/free_space.py +32 -13
  140. rucio/daemons/c3po/collectors/jedi_did.py +14 -5
  141. rucio/daemons/c3po/collectors/mock_did.py +11 -6
  142. rucio/daemons/c3po/collectors/network_metrics.py +12 -4
  143. rucio/daemons/c3po/collectors/workload.py +21 -19
  144. rucio/daemons/c3po/utils/__init__.py +0 -1
  145. rucio/daemons/c3po/utils/dataset_cache.py +15 -5
  146. rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
  147. rucio/daemons/c3po/utils/expiring_list.py +6 -7
  148. rucio/daemons/c3po/utils/popularity.py +5 -2
  149. rucio/daemons/c3po/utils/timeseries.py +25 -12
  150. rucio/daemons/cache/__init__.py +0 -1
  151. rucio/daemons/cache/consumer.py +21 -15
  152. rucio/daemons/common.py +42 -18
  153. rucio/daemons/conveyor/__init__.py +0 -1
  154. rucio/daemons/conveyor/common.py +69 -37
  155. rucio/daemons/conveyor/finisher.py +83 -46
  156. rucio/daemons/conveyor/poller.py +101 -69
  157. rucio/daemons/conveyor/preparer.py +35 -28
  158. rucio/daemons/conveyor/receiver.py +64 -21
  159. rucio/daemons/conveyor/stager.py +33 -28
  160. rucio/daemons/conveyor/submitter.py +71 -47
  161. rucio/daemons/conveyor/throttler.py +99 -35
  162. rucio/daemons/follower/__init__.py +0 -1
  163. rucio/daemons/follower/follower.py +12 -8
  164. rucio/daemons/hermes/__init__.py +0 -1
  165. rucio/daemons/hermes/hermes.py +57 -21
  166. rucio/daemons/judge/__init__.py +0 -1
  167. rucio/daemons/judge/cleaner.py +27 -17
  168. rucio/daemons/judge/evaluator.py +31 -18
  169. rucio/daemons/judge/injector.py +31 -23
  170. rucio/daemons/judge/repairer.py +28 -18
  171. rucio/daemons/oauthmanager/__init__.py +0 -1
  172. rucio/daemons/oauthmanager/oauthmanager.py +7 -8
  173. rucio/daemons/reaper/__init__.py +0 -1
  174. rucio/daemons/reaper/dark_reaper.py +15 -9
  175. rucio/daemons/reaper/reaper.py +109 -67
  176. rucio/daemons/replicarecoverer/__init__.py +0 -1
  177. rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
  178. rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
  179. rucio/daemons/rsedecommissioner/config.py +81 -0
  180. rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
  181. rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
  182. rucio/daemons/rsedecommissioner/profiles/generic.py +451 -0
  183. rucio/daemons/rsedecommissioner/profiles/types.py +92 -0
  184. rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
  185. rucio/daemons/storage/__init__.py +0 -1
  186. rucio/daemons/storage/consistency/__init__.py +0 -1
  187. rucio/daemons/storage/consistency/actions.py +152 -59
  188. rucio/daemons/tracer/__init__.py +0 -1
  189. rucio/daemons/tracer/kronos.py +47 -24
  190. rucio/daemons/transmogrifier/__init__.py +0 -1
  191. rucio/daemons/transmogrifier/transmogrifier.py +35 -26
  192. rucio/daemons/undertaker/__init__.py +0 -1
  193. rucio/daemons/undertaker/undertaker.py +10 -10
  194. rucio/db/__init__.py +0 -1
  195. rucio/db/sqla/__init__.py +16 -2
  196. rucio/db/sqla/constants.py +10 -1
  197. rucio/db/sqla/migrate_repo/__init__.py +0 -1
  198. rucio/db/sqla/migrate_repo/env.py +0 -1
  199. rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
  200. rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
  201. rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
  202. rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
  203. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
  204. rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
  205. rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
  206. rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
  207. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
  208. rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
  209. rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
  210. rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
  211. rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
  212. rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
  213. rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
  214. rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
  215. rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
  216. rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
  217. rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
  218. rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
  219. rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
  220. rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
  221. rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
  222. rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
  223. rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
  224. rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
  225. rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
  226. rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
  227. rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
  228. rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
  229. rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
  230. rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
  231. rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
  232. rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
  233. rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
  234. rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
  235. rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
  236. rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
  237. rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
  238. rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
  239. rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
  240. rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
  241. rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
  242. rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
  243. rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
  244. rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
  245. rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
  246. rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
  247. rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
  248. rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
  249. rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
  250. rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
  251. rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
  252. rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
  253. rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
  254. rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
  255. rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
  256. rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
  257. rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
  258. rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
  259. rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
  260. rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
  261. rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
  262. rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
  263. rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
  264. rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
  265. rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +0 -2
  266. rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
  267. rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
  268. rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
  269. rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
  270. rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
  271. rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
  272. rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
  273. rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
  274. rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
  275. rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
  276. rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
  277. rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
  278. rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
  279. rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
  280. rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
  281. rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
  282. rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
  283. rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
  284. rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
  285. rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
  286. rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
  287. rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
  288. rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
  289. rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
  290. rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
  291. rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +1 -3
  292. rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
  293. rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
  294. rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
  295. rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
  296. rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
  297. rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
  298. rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
  299. rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
  300. rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +0 -3
  301. rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
  302. rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +1 -2
  303. rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
  304. rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
  305. rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
  306. rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
  307. rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
  308. rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
  309. rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
  310. rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
  311. rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
  312. rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
  313. rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
  314. rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
  315. rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
  316. rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
  317. rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
  318. rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
  319. rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
  320. rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
  321. rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
  322. rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
  323. rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
  324. rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
  325. rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
  326. rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
  327. rucio/db/sqla/models.py +122 -216
  328. rucio/db/sqla/sautils.py +12 -5
  329. rucio/db/sqla/session.py +71 -43
  330. rucio/db/sqla/types.py +3 -4
  331. rucio/db/sqla/util.py +91 -69
  332. rucio/gateway/__init__.py +13 -0
  333. rucio/{api → gateway}/account.py +119 -46
  334. rucio/{api → gateway}/account_limit.py +12 -13
  335. rucio/{api → gateway}/authentication.py +106 -33
  336. rucio/{api → gateway}/config.py +12 -13
  337. rucio/{api → gateway}/credential.py +15 -4
  338. rucio/{api → gateway}/did.py +384 -140
  339. rucio/{api → gateway}/dirac.py +16 -6
  340. rucio/{api → gateway}/exporter.py +3 -4
  341. rucio/{api → gateway}/heartbeat.py +17 -5
  342. rucio/{api → gateway}/identity.py +63 -19
  343. rucio/{api → gateway}/importer.py +3 -4
  344. rucio/{api → gateway}/lifetime_exception.py +35 -10
  345. rucio/{api → gateway}/lock.py +34 -12
  346. rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
  347. rucio/{api → gateway}/permission.py +4 -5
  348. rucio/{api → gateway}/quarantined_replica.py +13 -4
  349. rucio/{api → gateway}/replica.py +12 -11
  350. rucio/{api → gateway}/request.py +129 -28
  351. rucio/{api → gateway}/rse.py +11 -12
  352. rucio/{api → gateway}/rule.py +117 -35
  353. rucio/{api → gateway}/scope.py +24 -14
  354. rucio/{api → gateway}/subscription.py +65 -43
  355. rucio/{api → gateway}/vo.py +17 -7
  356. rucio/rse/__init__.py +3 -4
  357. rucio/rse/protocols/__init__.py +0 -1
  358. rucio/rse/protocols/bittorrent.py +184 -0
  359. rucio/rse/protocols/cache.py +1 -2
  360. rucio/rse/protocols/dummy.py +1 -2
  361. rucio/rse/protocols/gfal.py +12 -10
  362. rucio/rse/protocols/globus.py +7 -7
  363. rucio/rse/protocols/gsiftp.py +2 -3
  364. rucio/rse/protocols/http_cache.py +1 -2
  365. rucio/rse/protocols/mock.py +1 -2
  366. rucio/rse/protocols/ngarc.py +1 -2
  367. rucio/rse/protocols/posix.py +12 -13
  368. rucio/rse/protocols/protocol.py +116 -52
  369. rucio/rse/protocols/rclone.py +6 -7
  370. rucio/rse/protocols/rfio.py +4 -5
  371. rucio/rse/protocols/srm.py +9 -10
  372. rucio/rse/protocols/ssh.py +8 -9
  373. rucio/rse/protocols/storm.py +2 -3
  374. rucio/rse/protocols/webdav.py +17 -14
  375. rucio/rse/protocols/xrootd.py +23 -17
  376. rucio/rse/rsemanager.py +19 -7
  377. rucio/tests/__init__.py +0 -1
  378. rucio/tests/common.py +43 -17
  379. rucio/tests/common_server.py +3 -3
  380. rucio/transfertool/__init__.py +0 -1
  381. rucio/transfertool/bittorrent.py +199 -0
  382. rucio/transfertool/bittorrent_driver.py +52 -0
  383. rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
  384. rucio/transfertool/fts3.py +250 -138
  385. rucio/transfertool/fts3_plugins.py +152 -0
  386. rucio/transfertool/globus.py +9 -8
  387. rucio/transfertool/globus_library.py +1 -2
  388. rucio/transfertool/mock.py +21 -12
  389. rucio/transfertool/transfertool.py +33 -24
  390. rucio/vcsversion.py +4 -4
  391. rucio/version.py +5 -13
  392. rucio/web/__init__.py +0 -1
  393. rucio/web/rest/__init__.py +0 -1
  394. rucio/web/rest/flaskapi/__init__.py +0 -1
  395. rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
  396. rucio/web/rest/flaskapi/v1/__init__.py +0 -1
  397. rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
  398. rucio/web/rest/flaskapi/v1/accounts.py +49 -48
  399. rucio/web/rest/flaskapi/v1/archives.py +12 -10
  400. rucio/web/rest/flaskapi/v1/auth.py +146 -144
  401. rucio/web/rest/flaskapi/v1/common.py +82 -41
  402. rucio/web/rest/flaskapi/v1/config.py +5 -6
  403. rucio/web/rest/flaskapi/v1/credentials.py +7 -8
  404. rucio/web/rest/flaskapi/v1/dids.py +158 -28
  405. rucio/web/rest/flaskapi/v1/dirac.py +8 -8
  406. rucio/web/rest/flaskapi/v1/export.py +3 -5
  407. rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
  408. rucio/web/rest/flaskapi/v1/identities.py +3 -5
  409. rucio/web/rest/flaskapi/v1/import.py +3 -4
  410. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
  411. rucio/web/rest/flaskapi/v1/locks.py +2 -4
  412. rucio/web/rest/flaskapi/v1/main.py +10 -2
  413. rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
  414. rucio/web/rest/flaskapi/v1/metrics.py +1 -2
  415. rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
  416. rucio/web/rest/flaskapi/v1/ping.py +6 -7
  417. rucio/web/rest/flaskapi/v1/redirect.py +8 -9
  418. rucio/web/rest/flaskapi/v1/replicas.py +43 -19
  419. rucio/web/rest/flaskapi/v1/requests.py +178 -21
  420. rucio/web/rest/flaskapi/v1/rses.py +61 -26
  421. rucio/web/rest/flaskapi/v1/rules.py +48 -18
  422. rucio/web/rest/flaskapi/v1/scopes.py +3 -5
  423. rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
  424. rucio/web/rest/flaskapi/v1/traces.py +4 -4
  425. rucio/web/rest/flaskapi/v1/types.py +20 -0
  426. rucio/web/rest/flaskapi/v1/vos.py +3 -5
  427. rucio/web/rest/main.py +0 -1
  428. rucio/web/rest/metrics.py +0 -1
  429. rucio/web/rest/ping.py +27 -0
  430. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
  431. rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
  432. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
  433. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
  434. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
  435. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
  436. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
  437. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
  438. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
  439. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
  440. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
  441. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
  442. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
  443. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
  444. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
  445. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
  446. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
  447. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
  448. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
  449. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
  450. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
  451. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
  452. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
  453. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
  454. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
  455. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
  456. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
  457. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
  458. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
  459. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
  460. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
  461. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
  462. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
  463. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
  464. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
  465. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
  466. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
  467. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
  468. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
  469. rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
  470. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
  471. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
  472. {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
  473. rucio-35.8.0.dist-info/METADATA +72 -0
  474. rucio-35.8.0.dist-info/RECORD +493 -0
  475. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
  476. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
  477. rucio/api/temporary_did.py +0 -49
  478. rucio/common/schema/cms.py +0 -478
  479. rucio/common/schema/lsst.py +0 -423
  480. rucio/core/permission/cms.py +0 -1166
  481. rucio/core/temporary_did.py +0 -188
  482. rucio/daemons/reaper/light_reaper.py +0 -255
  483. rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
  484. rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
  485. rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
  486. rucio-32.8.6.dist-info/METADATA +0 -83
  487. rucio-32.8.6.dist-info/RECORD +0 -481
  488. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
  489. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  490. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  491. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  492. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  493. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  494. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  495. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  496. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  497. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  498. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  499. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
  500. {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
  501. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
  502. {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,6 +21,7 @@ import os
22
21
  import re
23
22
  import sys
24
23
  import tempfile
24
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
25
25
 
26
26
  import gfal2
27
27
  import magic
@@ -30,29 +30,39 @@ import requests
30
30
  from rucio.common import config
31
31
  from rucio.core.rse import get_rse_id, get_rse_protocols
32
32
 
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Iterator
35
+ from multiprocessing.connection import Connection
36
+ from types import ModuleType
37
+ from typing import IO, TextIO
38
+
39
+ from _typeshed import FileDescriptorOrPath, GenericPath, StrOrBytesPath
40
+
41
+ from rucio.common.types import RSEProtocolDict
42
+
33
43
 
34
44
  class HTTPDownloadFailed(Exception):
35
- def __init__(self, msg='', code=None):
45
+ def __init__(self, msg: str = '', code: Optional[str] = None):
36
46
  self.code = code
37
47
  if code is not None:
38
48
  msg = '{0} (Status {1})'.format(msg, code)
39
49
  super(HTTPDownloadFailed, self).__init__(msg)
40
50
 
41
51
 
42
- class LogPipeHandler(logging.Handler, object):
43
- def __init__(self, pipe):
52
+ class LogPipeHandler(logging.Handler):
53
+ def __init__(self, pipe: "Connection"):
44
54
  super(LogPipeHandler, self).__init__()
45
55
  self.pipe = pipe
46
56
 
47
- def emit(self, record):
57
+ def emit(self, record: logging.LogRecord) -> None:
48
58
  self.pipe.send(self.format(record))
49
59
 
50
- def close(self):
60
+ def close(self) -> None:
51
61
  super(LogPipeHandler, self).close()
52
62
  self.pipe.close()
53
63
 
54
64
 
55
- def error(text, exit_code=1):
65
+ def error(text: str, exit_code: int = 1) -> None:
56
66
  '''
57
67
  Log and print `text` error. This function ends the execution of the program with exit code
58
68
  `exit_code` (defaults to 1).
@@ -63,7 +73,7 @@ def error(text, exit_code=1):
63
73
  exit(1)
64
74
 
65
75
 
66
- def mkdir(dir_):
76
+ def mkdir(dir_: "StrOrBytesPath") -> None:
67
77
  '''
68
78
  This functions creates the `dir_` directory if it doesn't exist. If `dir_`
69
79
  already exists this function does nothing.
@@ -71,10 +81,11 @@ def mkdir(dir_):
71
81
  try:
72
82
  os.mkdir(dir_)
73
83
  except OSError as error:
74
- assert error.errno == 17
84
+ if error.errno != 17:
85
+ raise error
75
86
 
76
87
 
77
- def cacert_config(config, rucio_home):
88
+ def cacert_config(config: "ModuleType", rucio_home: str) -> Optional[Union["FileDescriptorOrPath", Literal[False]]]:
78
89
  logger = logging.getLogger('dumper.__init__')
79
90
  try:
80
91
  cacert = config.config_get('client', 'ca_cert').replace('$RUCIO_HOME', rucio_home)
@@ -88,13 +99,13 @@ def cacert_config(config, rucio_home):
88
99
  return cacert
89
100
 
90
101
 
91
- def rucio_home():
102
+ def rucio_home() -> str:
92
103
  return os.environ.get('RUCIO_HOME', '/opt/rucio')
93
104
 
94
105
 
95
- def get_requests_session():
106
+ def get_requests_session() -> requests.Session:
96
107
  requests_session = requests.Session()
97
- requests_session.verify = cacert_config(config, rucio_home())
108
+ requests_session.verify = cacert_config(config, rucio_home()) # type: ignore
98
109
  requests_session.stream = True
99
110
  return requests_session
100
111
 
@@ -116,7 +127,7 @@ else:
116
127
  # pylint: enable=no-member
117
128
 
118
129
 
119
- def isplaintext(filename):
130
+ def isplaintext(filename: "GenericPath") -> bool:
120
131
  '''
121
132
  Returns True if `filename` has mimetype == 'text/plain'.
122
133
  '''
@@ -125,7 +136,7 @@ def isplaintext(filename):
125
136
  return mimetype(filename).split(';')[0] == 'text/plain'
126
137
 
127
138
 
128
- def smart_open(filename):
139
+ def smart_open(filename: "GenericPath") -> Optional[Union["TextIO", gzip.GzipFile]]:
129
140
  '''
130
141
  Returns an open file object if `filename` is plain text, else assumes
131
142
  it is a bzip2 compressed file and returns a file-like object to
@@ -146,14 +157,18 @@ def smart_open(filename):
146
157
 
147
158
 
148
159
  @contextlib.contextmanager
149
- def temp_file(directory, final_name=None, binary=False):
160
+ def temp_file(
161
+ directory: str,
162
+ final_name: Optional[str] = None,
163
+ binary: bool = False
164
+ ) -> "Iterator[tuple[IO[Any], StrOrBytesPath]]":
150
165
  '''
151
166
  Allows to create a temporal file to store partial results, when the
152
167
  file is complete it is renamed to `final_name`.
153
168
 
154
169
  - `directory`: working path to create the temporal and the final file.
155
170
  - `final_name`: Path of the final file, relative to `directory`.
156
- If the `final_name` is omitted or None the renaming step is ommited,
171
+ If the `final_name` is omitted or None the renaming step is omitted,
157
172
  leaving the temporal file with the results.
158
173
  - `binary`: whether to open the file in binary mode (default: False).
159
174
 
@@ -193,7 +208,7 @@ DATETIME_FORMAT_FULL = '%Y-%m-%dT%H:%M:%S'
193
208
  MILLISECONDS_RE = re.compile(r'\.(\d{3})Z$')
194
209
 
195
210
 
196
- def to_datetime(str_or_datetime):
211
+ def to_datetime(str_or_datetime: Union[datetime.datetime, str]) -> Optional[datetime.datetime]:
197
212
  """
198
213
  Convert string to datetime. The format is somewhat flexible.
199
214
  Timezone information is ignored.
@@ -221,51 +236,65 @@ def to_datetime(str_or_datetime):
221
236
  'Trying to parse "%s" date with resolution of milliseconds',
222
237
  str_or_datetime,
223
238
  )
224
- miliseconds = int(MILLISECONDS_RE.search(str_or_datetime).group(1))
239
+ milliseconds = int(MILLISECONDS_RE.search(str_or_datetime).group(1))
225
240
  str_or_datetime = MILLISECONDS_RE.sub('', str_or_datetime)
226
241
  date = datetime.datetime.strptime(
227
242
  str_or_datetime,
228
243
  DATETIME_FORMAT,
229
244
  )
230
- date = date + datetime.timedelta(microseconds=miliseconds * 1000)
245
+ date = date + datetime.timedelta(microseconds=milliseconds * 1000)
231
246
  return date
232
247
 
233
248
 
234
- def ddmendpoint_preferred_protocol(ddmendpoint):
249
+ def ddmendpoint_preferred_protocol(ddmendpoint: str) -> "RSEProtocolDict":
235
250
  return next(p for p in get_rse_protocols(get_rse_id(ddmendpoint))['protocols'] if p['domains']['wan']['read'] == 1)
236
251
 
237
252
 
238
- def ddmendpoint_url(ddmendpoint):
253
+ def ddmendpoint_url(ddmendpoint: str) -> str:
239
254
  preferred_protocol = ddmendpoint_preferred_protocol(ddmendpoint)
240
255
  prefix = re.sub(r'rucio/$', '', preferred_protocol['prefix'])
241
256
  return '{scheme}://{hostname}:{port}'.format(**preferred_protocol) + prefix
242
257
 
243
258
 
244
- def http_download_to_file(url, file_, session=None):
259
+ def http_download_to_file(url: str, file_: "IO", session: Optional[requests.Session] = None) -> None:
245
260
  '''
246
261
  Download the file in `url` storing it in the `file_` file-like
247
262
  object.
248
263
  If given `session` must be a requests.Session instance, and will be
249
264
  used to download the file, otherwise requests.get() will be used.
250
265
  '''
251
- if session is None:
252
- response = requests.get(url, stream=True)
253
- else:
254
- response = session.get(url)
255
-
256
- if response.status_code != 200:
257
- logging.error(
258
- 'Retrieving %s returned %d status code',
259
- url,
260
- response.status_code,
261
- )
262
- raise HTTPDownloadFailed('Error downloading ' + url, response.status_code)
266
+ def _do_download(url, file_, session, try_decode=False):
267
+ if session is None:
268
+ response = requests.get(url, stream=True)
269
+ else:
270
+ response = session.get(url)
271
+
272
+ if response.status_code != 200:
273
+ logging.error(
274
+ 'Retrieving %s returned %d status code',
275
+ url,
276
+ response.status_code,
277
+ )
278
+ raise HTTPDownloadFailed('Error downloading ' + url, str(response.status_code))
279
+
280
+ if try_decode:
281
+ if response.encoding is None:
282
+ response.encoding = 'utf-8'
283
+ for chunk in response.iter_content(CHUNK_SIZE, decode_unicode=True):
284
+ file_.write(chunk)
285
+ else:
286
+ for chunk in response.iter_content(CHUNK_SIZE):
287
+ file_.write(chunk)
263
288
 
264
- for chunk in response.iter_content(CHUNK_SIZE):
265
- file_.write(chunk)
289
+ try:
290
+ # try without decoding first
291
+ _do_download(url, file_, session, False)
292
+ except TypeError:
293
+ # if that fails due to writing binary data to text file, try to force decode
294
+ _do_download(url, file_, session, True)
266
295
 
267
296
 
268
- def http_download(url, filename):
297
+ def http_download(url: str, filename: "FileDescriptorOrPath") -> None:
269
298
  '''
270
299
  Download the file in `url` storing it in the path given by `filename`.
271
300
  '''
@@ -273,7 +302,7 @@ def http_download(url, filename):
273
302
  http_download_to_file(url, f)
274
303
 
275
304
 
276
- def gfal_download_to_file(url, file_):
305
+ def gfal_download_to_file(url: str, file_: "IO") -> None:
277
306
  '''
278
307
  Download the file in `url` storing it in the `file_` file-like
279
308
  object.
@@ -286,7 +315,7 @@ def gfal_download_to_file(url, file_):
286
315
  chunk = infile.read(CHUNK_SIZE)
287
316
  except gfal2.GError as e:
288
317
  if e.code == 70:
289
- logger.debug('GError(70) raised, using GRIDFTP PLUGIN:STAT_ON_OPEN=False workarround to download %s', url)
318
+ logger.debug('GError(70) raised, using GRIDFTP PLUGIN:STAT_ON_OPEN=False workaround to download %s', url)
290
319
  ctx.set_opt_boolean('GRIDFTP PLUGIN', 'STAT_ON_OPEN', False)
291
320
  infile = ctx.open(url, 'r')
292
321
  chunk = infile.read(CHUNK_SIZE)
@@ -298,7 +327,7 @@ def gfal_download_to_file(url, file_):
298
327
  chunk = infile.read(CHUNK_SIZE)
299
328
 
300
329
 
301
- def gfal_download(url, filename):
330
+ def gfal_download(url: str, filename: "FileDescriptorOrPath") -> None:
302
331
  '''
303
332
  Download the file in `url` storing it in the path given by `filename`.
304
333
  '''
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,9 +18,10 @@ import os
19
18
  import re
20
19
  import subprocess
21
20
  import tempfile
21
+ from typing import cast
22
22
 
23
23
  from rucio.common import dumper
24
- from rucio.common.dumper import error, DUMPS_CACHE_DIR, data_models, path_parsing
24
+ from rucio.common.dumper import DUMPS_CACHE_DIR, data_models, error, path_parsing
25
25
 
26
26
  subcommands = ['consistency', 'consistency-manual']
27
27
 
@@ -42,10 +42,12 @@ class Consistency(data_models.DataModel):
42
42
  ddm_endpoint, prev_date, cache_dir=cache_dir)
43
43
  next_date_fname = data_models.Replica.download(
44
44
  ddm_endpoint, next_date, cache_dir=cache_dir)
45
- assert prev_date_fname is not None
46
- assert next_date_fname is not None
45
+ if (prev_date_fname is None) or (next_date_fname is None):
46
+ raise ValueError("Both prev_date_fname and next_date_fname are required for subcommand='consistency'; found prev_data_fname=%s and next_date_fname=%s" % (prev_date_fname, next_date_fname))
47
+ elif subcommand == 'consistency-manual':
48
+ pass
47
49
  else:
48
- assert subcommand == 'consistency-manual'
50
+ raise ValueError("subcommand %s not accepted, choice from ('consistency','consistency-manual')" % subcommand)
49
51
 
50
52
  prefix_components = path_parsing.components(dumper.ddmendpoint_url(ddm_endpoint))
51
53
 
@@ -67,7 +69,7 @@ class Consistency(data_models.DataModel):
67
69
  Parser to have consistent paths in storage dumps.
68
70
 
69
71
  :param line: String with one line of a dump.
70
- :returns: Path formated as in the Rucio Replica Dumps.
72
+ :returns: Path formatted as in the Rucio Replica Dumps.
71
73
  '''
72
74
  relative = path_parsing.remove_prefix(
73
75
  prefix_components,
@@ -162,13 +164,14 @@ def _try_to_advance(it, default=None):
162
164
  return el.strip()
163
165
 
164
166
 
165
- def min3(*values):
167
+ def min_value(*values):
166
168
  '''
167
- Minimum between the 3 values ignoring None
169
+ Minimum between the input values, ignoring None
168
170
  '''
169
- values = [value for value in values if value is not None]
170
- assert len(values) > 0
171
- return min(values)
171
+ values_without_none = cast('list[str]', [value for value in values if value is not None])
172
+ if len(values_without_none) == 0:
173
+ raise ValueError("Input contains 0 non-null values.")
174
+ return min(values_without_none)
172
175
 
173
176
 
174
177
  def split_if_not_none(value, sep=',', fields=2):
@@ -199,7 +202,7 @@ def compare3(it0, it1, it2):
199
202
  path0, status0 = split_if_not_none(v0)
200
203
  path2, status2 = split_if_not_none(v2)
201
204
 
202
- vmin = min3(path0, v1, path2)
205
+ vmin = min_value(path0, v1, path2)
203
206
  in0 = in1 = in2 = False
204
207
  in0_status = in2_status = None
205
208
 
@@ -292,7 +295,7 @@ def gnu_sort(file_path, prefix=None, delimiter=None, fieldspec=None, cache_dir=D
292
295
 
293
296
  :param prefix: If given the output file will be named <prefix>_sorted.
294
297
  Otherwise the prefix is the name of the input file.
295
- :param delimiter: Delimiter character if the data is formated in
298
+ :param delimiter: Delimiter character if the data is formatted in
296
299
  columns (argument of -t in the sort command).
297
300
  :param fieldspec: String with the specification of column or columns
298
301
  to be used to sort (argument -k in the sort command).
@@ -302,7 +305,8 @@ def gnu_sort(file_path, prefix=None, delimiter=None, fieldspec=None, cache_dir=D
302
305
  memory and it is relatively fast if used with the environment variable
303
306
  LC_ALL set to C as in this function.
304
307
  '''
305
- assert (delimiter is None and fieldspec is None) or (delimiter is not None and fieldspec is not None)
308
+ if (delimiter is not None) ^ (fieldspec is not None):
309
+ raise ValueError("Either both delimiter and fieldspec is set, or neither are.")
306
310
  if delimiter is None:
307
311
  cmd_line = 'LC_ALL=C sort {0} > {1}'
308
312
  else:
@@ -316,23 +320,21 @@ def gnu_sort(file_path, prefix=None, delimiter=None, fieldspec=None, cache_dir=D
316
320
  if os.path.exists(sorted_path):
317
321
  return sorted_path
318
322
 
319
- # FIXME: mktemp() is an insecure function and this may be a security
320
- # threat in some scenarios. Find another way to do it.
321
- tfile = tempfile.mktemp(dir=cache_dir)
323
+ tfile = tempfile.NamedTemporaryFile(dir=cache_dir, delete=False)
322
324
 
323
325
  subprocess.check_call(
324
- cmd_line.format(file_path, tfile),
326
+ cmd_line.format(file_path, tfile.name),
325
327
  shell=True,
326
328
  )
327
329
 
328
- os.link(tfile, sorted_path)
329
- os.unlink(tfile)
330
+ os.link(tfile.name, sorted_path)
331
+ os.unlink(tfile.name)
330
332
 
331
333
  return sorted_path
332
334
 
333
335
 
334
336
  def populate_args(argparser):
335
- # Option to download the rucio replica dumps automaticaly
337
+ # Option to download the rucio replica dumps automatically
336
338
  parser = argparser.add_parser(
337
339
  'consistency',
338
340
  help='Consistency check to verify possible lost files and dark data '
@@ -391,8 +393,10 @@ def _parse_args_consistency(args):
391
393
  error('The storage dump filename must be of the form '
392
394
  '"dump_YYYYMMDD" where the date correspond to the date '
393
395
  'of the newest files included')
396
+
394
397
  date_str = date_str.group(1)
395
- assert date_str is not None
398
+ if date_str is None:
399
+ error('Invalid date {0}'.format(date_str))
396
400
  try:
397
401
  args_dict['date'] = date = datetime.datetime.strptime(date_str, '%Y%m%d')
398
402
  except ValueError:
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,16 +26,10 @@ import re
27
26
 
28
27
  from tabulate import tabulate
29
28
 
30
- from rucio.common.dumper import DUMPS_CACHE_DIR
31
- from rucio.common.dumper import HTTPDownloadFailed
32
- from rucio.common.dumper import get_requests_session
33
- from rucio.common.dumper import http_download_to_file
34
- from rucio.common.dumper import smart_open
35
- from rucio.common.dumper import temp_file
36
- from rucio.common.dumper import to_datetime
29
+ from rucio.common.dumper import DUMPS_CACHE_DIR, HTTPDownloadFailed, get_requests_session, http_download_to_file, smart_open, temp_file, to_datetime
37
30
 
38
31
 
39
- class DataModel(object):
32
+ class DataModel:
40
33
  """
41
34
  Data model for the dumps
42
35
  """
@@ -50,7 +43,7 @@ class DataModel(object):
50
43
  def __init__(self, *args):
51
44
  if len(args) != len(self.SCHEMA):
52
45
  raise TypeError(
53
- 'Wrong number of parameters (fields) to initalize {0} '
46
+ 'Wrong number of parameters (fields) to initialize {0} '
54
47
  'instance. {1} given, {2} expected:\n{3}'.format(
55
48
  type(self).__name__,
56
49
  len(args),
@@ -157,20 +150,17 @@ class DataModel(object):
157
150
  logger = logging.getLogger('auditor.data_models')
158
151
  requests_session = get_requests_session()
159
152
  if date == 'latest':
160
- url = ''.join((cls.BASE_URL, cls.URI, '?rse={0}'.format(rse)))
153
+ url = ''.join((cls.BASE_URL, cls.URI, '?rse={0}'.format(rse))) # type: ignore
161
154
  request_headers = requests_session.head(url)
162
155
  for field in request_headers.headers['content-disposition'].split(';'):
163
156
  if field.startswith('filename='):
164
157
  date = field.split('=')[1].split('_')[-1].split('.')[0]
165
158
 
159
+ elif isinstance(date, datetime.datetime):
160
+ date = date.strftime('%d-%m-%Y')
161
+ url = ''.join((cls.BASE_URL, cls.URI, '?rse={0}&date={1}'.format(rse, date))) # type: ignore
166
162
  else:
167
- assert isinstance(date, datetime.datetime)
168
- date = date.strftime('%d-%m-%Y') # pylint: disable=no-member
169
- url = ''.join((
170
- cls.BASE_URL,
171
- cls.URI,
172
- '?rse={0}&date={1}'.format(rse, date),
173
- ))
163
+ raise ValueError("Passed date (%s) must be a datetime object or 'latest'." % date)
174
164
 
175
165
  if not os.path.isdir(cache_dir):
176
166
  os.mkdir(cache_dir)
@@ -193,7 +183,7 @@ class DataModel(object):
193
183
  url,
194
184
  response.status_code,
195
185
  )
196
- raise HTTPDownloadFailed('Downloading {0} dump'.format(cls.__name__), code=response.status_code)
186
+ raise HTTPDownloadFailed('Downloading {0} dump'.format(cls.__name__), code=str(response.status_code))
197
187
 
198
188
  with temp_file(cache_dir, final_name=filename) as (tfile, _):
199
189
  http_download_to_file(url, tfile, session=requests_session)
@@ -244,7 +234,8 @@ class CompleteDataset(DataModel):
244
234
  self.state = args[7]
245
235
  else:
246
236
  self.state = None
247
- assert len(args) <= 8
237
+ if len(args) > 8:
238
+ raise ValueError("Too many arguments, must be 8 or less. Instead passed %s" % len(args))
248
239
 
249
240
 
250
241
  class Replica(DataModel):
@@ -271,10 +262,11 @@ class Replica(DataModel):
271
262
 
272
263
  if len(args) == 8:
273
264
  logger.warning('Missing parameter\nrse: %s\ndataset: %s\n', self.rse, self.name)
274
- assert len(args) <= 9
265
+ elif len(args) > 9:
266
+ raise ValueError("Too many arguments. Must be 9 or less, instead passed %s" % len(args))
275
267
 
276
268
 
277
- class Filter(object):
269
+ class Filter:
278
270
  _Condition = collections.namedtuple('_Condition', ('comparator', 'attribute', 'expected'))
279
271
 
280
272
  def __init__(self, filter_str, record_class):
@@ -299,7 +291,8 @@ class Filter(object):
299
291
  for expr in filter_str.split(','):
300
292
  key, expected = expr.split('=')
301
293
  # Better checks required
302
- assert key in record_class.get_fieldnames()
294
+ if key not in record_class.get_fieldnames():
295
+ raise ValueError("Key %s not supported." % key)
303
296
  parser = list(filter(lambda t: t[0] == key, record_class.SCHEMA))[0][1]
304
297
  self.conditions.append(self._Condition(
305
298
  comparator=operator.eq,
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  # Copyright European Organization for Nuclear Research (CERN) since 2012
3
2
  #
4
3
  # Licensed under the Apache License, Version 2.0 (the "License");