globus-cli 3.36.0__tar.gz → 3.38.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.
Files changed (279) hide show
  1. {globus_cli-3.36.0/src/globus_cli.egg-info → globus_cli-3.38.0}/PKG-INFO +3 -3
  2. {globus_cli-3.36.0 → globus_cli-3.38.0}/pyproject.toml +4 -5
  3. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/role/__init__.py +1 -0
  4. globus_cli-3.38.0/src/globus_cli/commands/collection/role/delete.py +23 -0
  5. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/delete.py +0 -1
  6. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/__init__.py +4 -0
  7. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/_common.py +21 -0
  8. globus_cli-3.38.0/src/globus_cli/commands/group/set_subscription_admin_verified.py +47 -0
  9. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/update.py +26 -2
  10. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/rm.py +0 -1
  11. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/create/transfer.py +15 -1
  12. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/transfer.py +2 -27
  13. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/scopes.py +0 -1
  14. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/__init__.py +2 -0
  15. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shared_options/transfer_task_options.py +43 -0
  16. globus_cli-3.38.0/src/globus_cli/termio/printers/unix_printer/_formatter.py +221 -0
  17. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/unix_printer/unix_printer.py +7 -4
  18. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/version.py +1 -1
  19. {globus_cli-3.36.0 → globus_cli-3.38.0/src/globus_cli.egg-info}/PKG-INFO +3 -3
  20. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli.egg-info/SOURCES.txt +3 -1
  21. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli.egg-info/requires.txt +2 -2
  22. globus_cli-3.36.0/src/globus_cli/termio/printers/unix_printer/awscli_text.py +0 -127
  23. {globus_cli-3.36.0 → globus_cli-3.38.0}/LICENSE +0 -0
  24. {globus_cli-3.36.0 → globus_cli-3.38.0}/README.rst +0 -0
  25. {globus_cli-3.36.0 → globus_cli-3.38.0}/setup.cfg +0 -0
  26. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/__init__.py +0 -0
  27. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/__main__.py +0 -0
  28. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/_click_compat.py +0 -0
  29. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/_warnings.py +0 -0
  30. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/__init__.py +0 -0
  31. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/_common.py +0 -0
  32. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/_removal_stub.py +0 -0
  33. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/api.py +0 -0
  34. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/__init__.py +0 -0
  35. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/_common.py +0 -0
  36. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/create.py +0 -0
  37. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/delete.py +0 -0
  38. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/list.py +0 -0
  39. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/rename.py +0 -0
  40. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/bookmark/show.py +0 -0
  41. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/cli_profile_list.py +0 -0
  42. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/__init__.py +0 -0
  43. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/_common.py +0 -0
  44. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/create/__init__.py +0 -0
  45. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/create/guest.py +0 -0
  46. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/create/mapped.py +0 -0
  47. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/delete.py +0 -0
  48. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/list.py +0 -0
  49. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/role/list.py +0 -0
  50. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/role/show.py +0 -0
  51. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/show.py +0 -0
  52. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/collection/update.py +0 -0
  53. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/__init__.py +0 -0
  54. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/_common.py +0 -0
  55. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/delete.py +0 -0
  56. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/local_id.py +0 -0
  57. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/my_shared_endpoint_list.py +0 -0
  58. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/__init__.py +0 -0
  59. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/_common.py +0 -0
  60. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/create.py +0 -0
  61. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/delete.py +0 -0
  62. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/list.py +0 -0
  63. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/show.py +0 -0
  64. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/permission/update.py +0 -0
  65. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/__init__.py +0 -0
  66. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/_common.py +0 -0
  67. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/create.py +0 -0
  68. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/delete.py +0 -0
  69. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/list.py +0 -0
  70. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/role/show.py +0 -0
  71. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/search.py +0 -0
  72. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/set_subscription_id.py +0 -0
  73. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/show.py +0 -0
  74. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/storage_gateway/__init__.py +0 -0
  75. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/storage_gateway/list.py +0 -0
  76. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/update.py +0 -0
  77. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/__init__.py +0 -0
  78. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/_common.py +0 -0
  79. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/create/__init__.py +0 -0
  80. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/create/from_json.py +0 -0
  81. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/create/posix.py +0 -0
  82. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/create/s3.py +0 -0
  83. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/delete.py +0 -0
  84. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/list.py +0 -0
  85. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/show.py +0 -0
  86. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/update/__init__.py +0 -0
  87. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/endpoint/user_credential/update/from_json.py +0 -0
  88. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/__init__.py +0 -0
  89. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/_common.py +0 -0
  90. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/create.py +0 -0
  91. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/delete.py +0 -0
  92. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/list.py +0 -0
  93. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/__init__.py +0 -0
  94. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/cancel.py +0 -0
  95. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/delete.py +0 -0
  96. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/list.py +0 -0
  97. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/resume.py +0 -0
  98. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/show.py +0 -0
  99. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/show_definition.py +0 -0
  100. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/show_logs.py +0 -0
  101. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/run/update.py +0 -0
  102. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/show.py +0 -0
  103. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/start.py +0 -0
  104. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/update.py +0 -0
  105. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/flows/validate.py +0 -0
  106. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/__init__.py +0 -0
  107. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/create/__init__.py +0 -0
  108. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/create/_common.py +0 -0
  109. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/create/guest.py +0 -0
  110. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/create/mapped.py +0 -0
  111. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/set_subscription_admin_verified.py +0 -0
  112. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/set_subscription_id.py +0 -0
  113. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/update/__init__.py +0 -0
  114. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/update/guest.py +0 -0
  115. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcp/update/mapped.py +0 -0
  116. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/__init__.py +0 -0
  117. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/__init__.py +0 -0
  118. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/_common.py +0 -0
  119. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/__init__.py +0 -0
  120. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/_common.py +0 -0
  121. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/create.py +0 -0
  122. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/delete.py +0 -0
  123. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/list.py +0 -0
  124. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/role/show.py +0 -0
  125. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/set_subscription_id.py +0 -0
  126. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/show.py +0 -0
  127. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/gcs/endpoint/update.py +0 -0
  128. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/get_identities.py +0 -0
  129. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/create.py +0 -0
  130. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/delete.py +0 -0
  131. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/get_by_subscription.py +0 -0
  132. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/get_subscription_info.py +0 -0
  133. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/invite/__init__.py +0 -0
  134. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/invite/_common.py +0 -0
  135. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/invite/accept.py +0 -0
  136. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/invite/decline.py +0 -0
  137. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/join.py +0 -0
  138. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/leave.py +0 -0
  139. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/list.py +0 -0
  140. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/__init__.py +0 -0
  141. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/add.py +0 -0
  142. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/approve.py +0 -0
  143. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/invite.py +0 -0
  144. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/list.py +0 -0
  145. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/reject.py +0 -0
  146. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/member/remove.py +0 -0
  147. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/set_policies.py +0 -0
  148. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/group/show.py +0 -0
  149. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/list_commands.py +0 -0
  150. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/login.py +0 -0
  151. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/logout.py +0 -0
  152. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/ls.py +0 -0
  153. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/mkdir.py +0 -0
  154. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/rename.py +0 -0
  155. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/__init__.py +0 -0
  156. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/_common.py +0 -0
  157. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/delete_by_query.py +0 -0
  158. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/__init__.py +0 -0
  159. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/create.py +0 -0
  160. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/delete.py +0 -0
  161. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/list.py +0 -0
  162. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/role/__init__.py +0 -0
  163. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/role/create.py +0 -0
  164. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/role/delete.py +0 -0
  165. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/role/list.py +0 -0
  166. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/index/show.py +0 -0
  167. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/ingest.py +0 -0
  168. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/query.py +0 -0
  169. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/subject/__init__.py +0 -0
  170. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/subject/delete.py +0 -0
  171. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/subject/show.py +0 -0
  172. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/task/__init__.py +0 -0
  173. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/task/list.py +0 -0
  174. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/search/task/show.py +0 -0
  175. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/session/__init__.py +0 -0
  176. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/session/consent.py +0 -0
  177. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/session/show.py +0 -0
  178. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/session/update.py +0 -0
  179. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/stat.py +0 -0
  180. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/__init__.py +0 -0
  181. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/_common.py +0 -0
  182. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/cancel.py +0 -0
  183. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/event_list.py +0 -0
  184. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/generate_submission_id.py +0 -0
  185. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/list.py +0 -0
  186. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/pause_info.py +0 -0
  187. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/show.py +0 -0
  188. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/update.py +0 -0
  189. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/task/wait.py +0 -0
  190. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/__init__.py +0 -0
  191. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/_common.py +0 -0
  192. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/create/__init__.py +0 -0
  193. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/delete.py +0 -0
  194. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/list.py +0 -0
  195. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/pause.py +0 -0
  196. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/resume.py +0 -0
  197. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/timer/show.py +0 -0
  198. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/update.py +0 -0
  199. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/version.py +0 -0
  200. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/commands/whoami.py +0 -0
  201. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/constants.py +0 -0
  202. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/endpointish/__init__.py +0 -0
  203. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/endpointish/endpointish.py +0 -0
  204. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/endpointish/entity_type.py +0 -0
  205. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/endpointish/errors.py +0 -0
  206. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/__init__.py +0 -0
  207. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/__init__.py +0 -0
  208. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/auth_requirements.py +0 -0
  209. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/authapi_hooks.py +0 -0
  210. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/endpoint_types.py +0 -0
  211. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/flows_hooks.py +0 -0
  212. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/generic_hooks.py +0 -0
  213. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/search_hooks.py +0 -0
  214. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/hooks/transfer_hooks.py +0 -0
  215. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/messages.py +0 -0
  216. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/exception_handling/registry.py +0 -0
  217. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/globus_cli_flake8.py +0 -0
  218. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/__init__.py +0 -0
  219. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/_old_config.py +0 -0
  220. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/auth_flows.py +0 -0
  221. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/client_login.py +0 -0
  222. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/context.py +0 -0
  223. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/errors.py +0 -0
  224. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/local_server.py +0 -0
  225. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/manager.py +0 -0
  226. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/storage.py +0 -0
  227. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/login_manager/utils.py +0 -0
  228. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/command_state.py +0 -0
  229. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/commands.py +0 -0
  230. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/mutex_group.py +0 -0
  231. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_classes.py +0 -0
  232. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/__init__.py +0 -0
  233. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/delimited.py +0 -0
  234. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/endpoint_plus_path.py +0 -0
  235. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/guest_activity_notify_param.py +0 -0
  236. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/identity_type.py +0 -0
  237. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/json_strorfile.py +0 -0
  238. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/location.py +0 -0
  239. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/notify_param.py +0 -0
  240. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/nullable.py +0 -0
  241. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/task_path.py +0 -0
  242. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/param_types/timedelta.py +0 -0
  243. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shared_callbacks.py +0 -0
  244. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shared_options/__init__.py +0 -0
  245. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shared_options/endpointish.py +0 -0
  246. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shared_options/id_args.py +0 -0
  247. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/parsing/shell_completion.py +0 -0
  248. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/reflect.py +0 -0
  249. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/__init__.py +0 -0
  250. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/auth.py +0 -0
  251. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/gcs.py +0 -0
  252. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/transfer/__init__.py +0 -0
  253. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/transfer/activation.py +0 -0
  254. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/transfer/client.py +0 -0
  255. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/transfer/data.py +0 -0
  256. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/services/transfer/recursive_ls.py +0 -0
  257. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/__init__.py +0 -0
  258. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/_display.py +0 -0
  259. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/context.py +0 -0
  260. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/errors.py +0 -0
  261. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/field.py +0 -0
  262. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/formatters/__init__.py +0 -0
  263. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/formatters/auth.py +0 -0
  264. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/formatters/base.py +0 -0
  265. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/formatters/compound.py +0 -0
  266. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/formatters/primitive.py +0 -0
  267. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/__init__.py +0 -0
  268. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/base.py +0 -0
  269. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/custom_printer.py +0 -0
  270. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/json_printer.py +0 -0
  271. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/record_printer.py +0 -0
  272. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/table_printer.py +0 -0
  273. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/printers/unix_printer/__init__.py +0 -0
  274. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/termio/server_timing.py +0 -0
  275. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/types.py +0 -0
  276. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli/utils.py +0 -0
  277. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli.egg-info/dependency_links.txt +0 -0
  278. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli.egg-info/entry_points.txt +0 -0
  279. {globus_cli-3.36.0 → globus_cli-3.38.0}/src/globus_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: globus-cli
3
- Version: 3.36.0
3
+ Version: 3.38.0
4
4
  Summary: Globus CLI
5
5
  Author-email: Stephen Rosen <sirosen@globus.org>
6
6
  License-Expression: Apache-2.0
@@ -18,8 +18,8 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Requires-Python: >=3.9
19
19
  Description-Content-Type: text/x-rst
20
20
  License-File: LICENSE
21
- Requires-Dist: globus-sdk==3.62.0
22
- Requires-Dist: click<9,>=8.1.4
21
+ Requires-Dist: globus-sdk==3.63.0
22
+ Requires-Dist: click<8.4,>=8.1.4
23
23
  Requires-Dist: jmespath==1.0.1
24
24
  Requires-Dist: packaging>=17.0
25
25
  Requires-Dist: typing_extensions>=4.0; python_version < "3.11"
@@ -28,8 +28,8 @@ classifiers = [
28
28
  ]
29
29
  requires-python = ">=3.9"
30
30
  dependencies = [
31
- "globus-sdk==3.62.0",
32
- "click>=8.1.4,<9",
31
+ "globus-sdk==3.63.0",
32
+ "click>=8.1.4,<8.4",
33
33
  "jmespath==1.0.1",
34
34
  "packaging>=17.0",
35
35
  "typing_extensions>=4.0;python_version<'3.11'",
@@ -56,7 +56,7 @@ test = [
56
56
  "pytest>=7",
57
57
  "pytest-xdist<4",
58
58
  "pytest-timeout<3",
59
- "click-type-test==1.1.0;python_version>='3.10'",
59
+ "click-type-test==1.3.0;python_version>='3.10'",
60
60
  "responses==0.25.8",
61
61
  ]
62
62
  test-mindeps = [
@@ -69,7 +69,7 @@ test-mindeps = [
69
69
  "typing_extensions==4.0",
70
70
  ]
71
71
  typing = [
72
- "mypy==1.17.1",
72
+ "mypy==1.18.2",
73
73
  "types-jwt",
74
74
  "types-requests",
75
75
  "types-jmespath",
@@ -151,5 +151,4 @@ disallow_untyped_defs = false
151
151
  disallow_incomplete_defs = false
152
152
  module = [
153
153
  "globus_cli.services.transfer.recursive_ls",
154
- "globus_cli.termio.printers.unix_printer.awscli_text",
155
154
  ]
@@ -6,6 +6,7 @@ from globus_cli.parsing import group
6
6
  lazy_subcommands={
7
7
  "list": (".list", "list_command"),
8
8
  "show": (".show", "show_command"),
9
+ "delete": (".delete", "delete_command"),
9
10
  },
10
11
  )
11
12
  def role_command() -> None:
@@ -0,0 +1,23 @@
1
+ import uuid
2
+
3
+ import click
4
+
5
+ from globus_cli.login_manager import LoginManager
6
+ from globus_cli.parsing import collection_id_arg, command
7
+ from globus_cli.termio import display
8
+
9
+
10
+ @command("delete")
11
+ @collection_id_arg
12
+ @click.argument("ROLE_ID", type=click.UUID)
13
+ @LoginManager.requires_login("transfer")
14
+ def delete_command(
15
+ login_manager: LoginManager,
16
+ *,
17
+ collection_id: uuid.UUID,
18
+ role_id: uuid.UUID,
19
+ ) -> None:
20
+ """Delete a particular role on a Collection."""
21
+ gcs_client = login_manager.get_gcs_client(collection_id=collection_id)
22
+ res = gcs_client.delete_role(role_id)
23
+ display(res, text_mode=display.RAW, response_key="code")
@@ -131,7 +131,6 @@ def delete_command(
131
131
  local_user=local_user,
132
132
  additional_fields={
133
133
  "ignore_missing": ignore_missing,
134
- "skip_activation_check": skip_activation_check,
135
134
  "interpret_globs": enable_globs,
136
135
  **notify,
137
136
  },
@@ -19,6 +19,10 @@ from globus_cli.parsing import group
19
19
  ),
20
20
  "get-by-subscription": (".get_by_subscription", "group_get_by_subscription"),
21
21
  "update": (".update", "group_update"),
22
+ "set-subscription-admin-verified": (
23
+ ".set_subscription_admin_verified",
24
+ "group_set_subscription_admin_verified",
25
+ ),
22
26
  },
23
27
  )
24
28
  def group_command() -> None:
@@ -1,9 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import typing as t
4
+ import uuid
4
5
 
5
6
  import click
6
7
 
8
+ from globus_cli.constants import EXPLICIT_NULL, ExplicitNullType
7
9
  from globus_cli.termio import Field, formatters
8
10
  from globus_cli.types import AnyCommand
9
11
 
@@ -74,3 +76,22 @@ GROUP_FIELDS_W_SUBSCRIPTION = (
74
76
 
75
77
  def group_id_arg(f: C) -> C:
76
78
  return click.argument("GROUP_ID", type=click.UUID)(f)
79
+
80
+
81
+ class GroupSubscriptionVerifiedIdType(click.ParamType):
82
+ name = "TEXT"
83
+
84
+ def convert(
85
+ self, value: str, param: click.Parameter | None, ctx: click.Context | None
86
+ ) -> uuid.UUID | ExplicitNullType:
87
+ if value.lower() == "null":
88
+ return EXPLICIT_NULL
89
+
90
+ try:
91
+ return uuid.UUID(value)
92
+ except ValueError:
93
+ msg = (
94
+ f"{value} is invalid. Expected either a UUID or the special value "
95
+ '"null"'
96
+ )
97
+ self.fail(msg, param, ctx)
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ import uuid
4
+
5
+ import click
6
+
7
+ from globus_cli.constants import EXPLICIT_NULL, ExplicitNullType
8
+ from globus_cli.login_manager import LoginManager
9
+ from globus_cli.parsing import command
10
+ from globus_cli.termio import display
11
+
12
+ from ._common import GroupSubscriptionVerifiedIdType, group_id_arg
13
+
14
+
15
+ @command("set-subscription-admin-verified")
16
+ @group_id_arg
17
+ @click.argument(
18
+ "SUBSCRIPTION_ID",
19
+ type=GroupSubscriptionVerifiedIdType(),
20
+ metavar="[SUBSCRIPTION_ID|null]",
21
+ )
22
+ @LoginManager.requires_login("groups")
23
+ def group_set_subscription_admin_verified(
24
+ login_manager: LoginManager,
25
+ *,
26
+ group_id: uuid.UUID,
27
+ subscription_id: uuid.UUID | ExplicitNullType,
28
+ ) -> None:
29
+ """
30
+ Mark a group as a subscription-verified resource.
31
+
32
+ SUBSCRIPTION_ID is the ID of the subscription to which this group shall belong,
33
+ or "null" to mark the group as non-verified.
34
+ """
35
+ groups_client = login_manager.get_groups_client()
36
+
37
+ admin_verified_id: str | None = (
38
+ None if subscription_id == EXPLICIT_NULL else str(subscription_id)
39
+ )
40
+
41
+ response = groups_client.set_subscription_admin_verified(
42
+ group_id, admin_verified_id
43
+ )
44
+
45
+ display(
46
+ response, simple_text="Group subscription verification updated successfully"
47
+ )
@@ -1,14 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import typing as t
3
4
  import uuid
4
5
 
5
6
  import click
6
7
 
8
+ from globus_cli.constants import EXPLICIT_NULL, ExplicitNullType
7
9
  from globus_cli.login_manager import LoginManager
8
10
  from globus_cli.parsing import command
9
11
  from globus_cli.termio import display
10
12
 
11
- from ._common import group_id_arg
13
+ from ._common import GroupSubscriptionVerifiedIdType, group_id_arg
12
14
 
13
15
 
14
16
  @command("update")
@@ -18,6 +20,14 @@ from ._common import group_id_arg
18
20
  @click.option(
19
21
  "--terms-and-conditions", help="Terms and conditions for group membership"
20
22
  )
23
+ @click.option(
24
+ "--subscription-admin-verified-id",
25
+ type=GroupSubscriptionVerifiedIdType(),
26
+ help=(
27
+ "The ID of the subscription to which the group belongs. Use the special value"
28
+ ' "null" to remove subscription verification from the group.'
29
+ ),
30
+ )
21
31
  @LoginManager.requires_login("groups")
22
32
  def group_update(
23
33
  login_manager: LoginManager,
@@ -26,6 +36,7 @@ def group_update(
26
36
  name: str | None,
27
37
  description: str | None,
28
38
  terms_and_conditions: str | None,
39
+ subscription_admin_verified_id: uuid.UUID | None | ExplicitNullType,
29
40
  ) -> None:
30
41
  """Update an existing group."""
31
42
  groups_client = login_manager.get_groups_client()
@@ -36,7 +47,7 @@ def group_update(
36
47
  # assemble put data using existing values for any field not given
37
48
  # note that the API only allows modification of certain fields
38
49
  # https://groups.api.globus.org/redoc#tag/groups/operation/update_group_v2_groups__group_id__put
39
- data = {}
50
+ data: dict[str, t.Any] = {}
40
51
  for attrname, argval in (
41
52
  ("name", name),
42
53
  ("description", description),
@@ -47,6 +58,19 @@ def group_update(
47
58
  else:
48
59
  data[attrname] = group[attrname]
49
60
 
61
+ if subscription_admin_verified_id == EXPLICIT_NULL:
62
+ data["subscription_admin_verified_id"] = None
63
+ elif (
64
+ subscription_admin_verified_id == group["subscription_admin_verified_id"]
65
+ or subscription_admin_verified_id is None
66
+ ):
67
+ data["subscription_admin_verified_id"] = group["subscription_admin_verified_id"]
68
+ else:
69
+ raise click.UsageError(
70
+ "To set the `subscription_admin_verified_id` to a new, non-null value, use "
71
+ "`globus group set-subscription-admin-verified`"
72
+ )
73
+
50
74
  response = groups_client.update_group(group_id, data)
51
75
 
52
76
  display(response, simple_text="Group updated successfully")
@@ -88,7 +88,6 @@ def rm_command(
88
88
  local_user=local_user,
89
89
  additional_fields={
90
90
  "ignore_missing": ignore_missing,
91
- "skip_activation_check": skip_activation_check,
92
91
  "interpret_globs": enable_globs,
93
92
  **notify,
94
93
  },
@@ -16,6 +16,7 @@ from globus_cli.parsing import (
16
16
  command,
17
17
  encrypt_data_option,
18
18
  fail_on_quota_errors_option,
19
+ filter_rule_options,
19
20
  mutex_option_group,
20
21
  preserve_timestamp_option,
21
22
  skip_source_errors_option,
@@ -54,7 +55,14 @@ e.g. '1h30m', '500s', '10d'
54
55
  """
55
56
 
56
57
 
57
- @command("transfer", short_help="Create a recurring transfer timer.")
58
+ @command(
59
+ "transfer",
60
+ opts_to_combine={ # see 'filter_rule_options' for why this is needed
61
+ "include": "filter_rules",
62
+ "exclude": "filter_rules",
63
+ },
64
+ short_help="Create a recurring transfer timer.",
65
+ )
58
66
  @click.argument(
59
67
  "source", metavar="SOURCE_ENDPOINT_ID[:SOURCE_PATH]", type=ENDPOINT_PLUS_OPTPATH
60
68
  )
@@ -70,6 +78,7 @@ e.g. '1h30m', '500s', '10d'
70
78
  @skip_source_errors_option
71
79
  @fail_on_quota_errors_option
72
80
  @task_notify_option
81
+ @filter_rule_options
73
82
  @click.option(
74
83
  "--start",
75
84
  type=click.DateTime(formats=DATETIME_FORMATS),
@@ -139,6 +148,7 @@ def transfer_command(
139
148
  preserve_timestamp: bool,
140
149
  skip_source_errors: bool,
141
150
  fail_on_quota_errors: bool,
151
+ filter_rules: list[tuple[t.Literal["include", "exclude"], str]],
142
152
  notify: dict[str, bool],
143
153
  ) -> None:
144
154
  """
@@ -305,6 +315,10 @@ def transfer_command(
305
315
  **notify, # type: ignore[arg-type]
306
316
  )
307
317
 
318
+ for rule in filter_rules:
319
+ method, name = rule
320
+ transfer_data.add_filter_rule(method=method, name=name, type="file")
321
+
308
322
  if batch:
309
323
  add_batch_to_transfer_data(
310
324
  cmd_source_path, cmd_dest_path, None, transfer_data, batch
@@ -12,6 +12,7 @@ from globus_cli.parsing import (
12
12
  command,
13
13
  encrypt_data_option,
14
14
  fail_on_quota_errors_option,
15
+ filter_rule_options,
15
16
  mutex_option_group,
16
17
  preserve_timestamp_option,
17
18
  skip_source_errors_option,
@@ -136,6 +137,7 @@ fi
136
137
  @encrypt_data_option(aliases=("--encrypt",))
137
138
  @skip_source_errors_option
138
139
  @fail_on_quota_errors_option
140
+ @filter_rule_options
139
141
  @click.option(
140
142
  "--delete",
141
143
  is_flag=True,
@@ -170,32 +172,6 @@ fi
170
172
  show_default=True,
171
173
  help="Specify an algorithm for --external-checksum or --verify-checksum",
172
174
  )
173
- @click.option(
174
- "--include",
175
- multiple=True,
176
- show_default=True,
177
- expose_value=False, # this is combined into the filter_rules parameter
178
- help=(
179
- "Include files found with names that match the given pattern in "
180
- 'recursive transfers. Pattern may include "*", "?", or "[]" for Unix-style '
181
- "globbing. This option can be given multiple times along with "
182
- "--exclude to control which files are transferred, with earlier "
183
- "options having priority."
184
- ),
185
- )
186
- @click.option(
187
- "--exclude",
188
- multiple=True,
189
- show_default=True,
190
- expose_value=False, # this is combined into the filter_rules parameter
191
- help=(
192
- "Exclude files found with names that match the given pattern in "
193
- 'recursive transfers. Pattern may include "*", "?", or "[]" for Unix-style '
194
- "globbing. This option can be given multiple times along with "
195
- "--include to control which files are transferred, with earlier "
196
- "options having priority."
197
- ),
198
- )
199
175
  @click.option(
200
176
  "--source-local-user",
201
177
  help=(
@@ -392,7 +368,6 @@ def transfer_command(
392
368
  deadline=deadline,
393
369
  skip_source_errors=skip_source_errors,
394
370
  fail_on_quota_errors=fail_on_quota_errors,
395
- skip_activation_check=skip_activation_check,
396
371
  delete_destination_extra=(delete or delete_destination_extra),
397
372
  source_local_user=source_local_user,
398
373
  destination_local_user=destination_local_user,
@@ -94,7 +94,6 @@ class _CLIScopeRequirements(t.Dict[ServiceNameLiteral, _ServiceRequirement]):
94
94
  "scopes": [
95
95
  FlowsScopes.manage_flows,
96
96
  FlowsScopes.view_flows,
97
- FlowsScopes.run,
98
97
  FlowsScopes.run_status,
99
98
  FlowsScopes.run_manage,
100
99
  ],
@@ -38,6 +38,7 @@ from .shared_options.id_args import (
38
38
  from .shared_options.transfer_task_options import (
39
39
  encrypt_data_option,
40
40
  fail_on_quota_errors_option,
41
+ filter_rule_options,
41
42
  preserve_timestamp_option,
42
43
  skip_source_errors_option,
43
44
  sync_level_option,
@@ -84,6 +85,7 @@ __all__ = [
84
85
  "sync_level_option",
85
86
  "task_notify_option",
86
87
  "fail_on_quota_errors_option",
88
+ "filter_rule_options",
87
89
  "encrypt_data_option",
88
90
  "preserve_timestamp_option",
89
91
  "skip_source_errors_option",
@@ -125,3 +125,46 @@ def encrypt_data_option(*, aliases: tuple[str, ...] = ()) -> t.Callable[[C], C]:
125
125
  )(f)
126
126
 
127
127
  return decorator
128
+
129
+
130
+ def filter_rule_options(f: C) -> C:
131
+ """
132
+ Use of this decorator must be used with
133
+
134
+ opts_to_combine={
135
+ "include": "filter_rules",
136
+ "exclude": "filter_rules",
137
+ }
138
+
139
+ in order to produce correct `filter_rules` list.
140
+
141
+ The order of `--include` and `--exclude` determines behavior, and we have to
142
+ modify parsing to get that ordering information.
143
+ """
144
+ f = click.option(
145
+ "--include",
146
+ multiple=True,
147
+ show_default=True,
148
+ expose_value=False, # this is combined into the filter_rules parameter
149
+ help=(
150
+ "Include files found with names that match the given pattern in "
151
+ 'recursive transfers. Pattern may include "*", "?", or "[]" for Unix-style '
152
+ "globbing. This option can be given multiple times along with "
153
+ "--exclude to control which files are transferred, with earlier "
154
+ "options having priority."
155
+ ),
156
+ )(f)
157
+ f = click.option(
158
+ "--exclude",
159
+ multiple=True,
160
+ show_default=True,
161
+ expose_value=False, # this is combined into the filter_rules parameter
162
+ help=(
163
+ "Exclude files found with names that match the given pattern in "
164
+ 'recursive transfers. Pattern may include "*", "?", or "[]" for Unix-style '
165
+ "globbing. This option can be given multiple times along with "
166
+ "--include to control which files are transferred, with earlier "
167
+ "options having priority."
168
+ ),
169
+ )(f)
170
+ return f
@@ -0,0 +1,221 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import typing as t
5
+ from itertools import chain
6
+
7
+ if sys.version_info >= (3, 10):
8
+ from typing import TypeAlias
9
+ else:
10
+ from typing_extensions import TypeAlias
11
+
12
+
13
+ Scalar: TypeAlias = "str | int | float | bool | None"
14
+ NonScalar: TypeAlias = "list[Scalar | NonScalar] | dict[str, Scalar | NonScalar]"
15
+
16
+
17
+ class UnixFormattingError(ValueError):
18
+ """Class of errors indicating that the data could not be formatted."""
19
+
20
+
21
+ def emit_any_value(item: Scalar | NonScalar) -> t.Iterator[str]:
22
+ """
23
+ Emission of values is defined as yielding back each line of output.
24
+
25
+ Lists and dicts are handled specially. Any scalar value is just passed to Python
26
+ ``str()``. Note that this means that null becomes "None" in our output.
27
+ """
28
+ if isinstance(item, list):
29
+ yield from emit_list(item)
30
+ elif isinstance(item, dict):
31
+ yield from emit_dict(item)
32
+ else:
33
+ yield str(item)
34
+
35
+
36
+ def emit_list(
37
+ elements: list[Scalar | NonScalar],
38
+ identifier: str | None = None,
39
+ ) -> t.Iterator[str]:
40
+ """
41
+ Given a list, and optionally some identifier used to tag the output, emit lines of
42
+ output.
43
+
44
+ Supports:
45
+ list[dict] , list[scalar] , and list[list | scalar]
46
+
47
+ If the input mixes dicts and non-dict values, this function will raise a ValueError.
48
+ """
49
+ # empty lists disappear in the output
50
+ if not elements:
51
+ return
52
+
53
+ # across these branches, mypy does not correctly narrow the type of `elements`
54
+ # so we need to type-ignore the argument type
55
+ if all(isinstance(item, dict) for item in elements):
56
+ yield from emit_list_of_dicts(
57
+ elements, # type: ignore[arg-type]
58
+ identifier=identifier,
59
+ )
60
+ elif any(isinstance(item, dict) for item in elements):
61
+ raise UnixFormattingError(
62
+ "Formatter cannot handle arrays which mix JSON objects "
63
+ "with other datatypes."
64
+ )
65
+
66
+ elif any(isinstance(item, list) for item in elements):
67
+ yield from emit_list_containing_lists(
68
+ elements, # type: ignore[arg-type]
69
+ identifier=identifier,
70
+ )
71
+ else:
72
+ yield from emit_scalar_list(
73
+ elements, # type: ignore[arg-type]
74
+ identifier=identifier,
75
+ )
76
+
77
+
78
+ def emit_scalar_list(
79
+ elements: list[Scalar], identifier: str | None = None
80
+ ) -> t.Iterator[str]:
81
+ """
82
+ Emit a list of scalars, with or without an identifier.
83
+
84
+ Given an identifier, each element is placed on a separate line of output:
85
+
86
+ >>> emit_scalar_list([1, 2], identifier="FOO")
87
+ FOO\t1
88
+ FOO\t2
89
+
90
+ Without an identifier, all elements are placed on the same line:
91
+
92
+ >>> emit_scalar_list([1, 2], identifier="FOO")
93
+ 1\t2
94
+ """
95
+ if identifier is not None:
96
+ for item in elements:
97
+ yield f"{identifier}\t{item}"
98
+ else:
99
+ yield "\t".join(str(item) for item in elements)
100
+
101
+
102
+ def emit_list_containing_lists(
103
+ elements: list[Scalar | list[Scalar | NonScalar]],
104
+ identifier: str | None = None,
105
+ ) -> t.Iterator[str]:
106
+ """
107
+ Emit a list which contains nested lists, potentially mixed with scalars.
108
+ First, the scalars are split off and emitted, then all of the nested lists are
109
+ emitted in order of appearance.
110
+ """
111
+ scalars: list[Scalar] = []
112
+ nested: list[list[Scalar | NonScalar]] = []
113
+ for item in elements:
114
+ if isinstance(item, list):
115
+ nested.append(item)
116
+ else:
117
+ scalars.append(item)
118
+
119
+ if scalars:
120
+ yield from emit_scalar_list(scalars)
121
+ for nested_list in nested:
122
+ yield from emit_list(nested_list, identifier=identifier)
123
+
124
+
125
+ def emit_list_of_dicts(
126
+ elements: list[dict[str, Scalar | NonScalar]], identifier: str | None = None
127
+ ) -> t.Iterator[str]:
128
+ keys = extract_scalar_keys(elements)
129
+ for item in elements:
130
+ yield from emit_dict(item, identifier=identifier, scalar_keys=keys)
131
+
132
+
133
+ def emit_dict(
134
+ item: dict[str, Scalar | NonScalar],
135
+ identifier: str | None = None,
136
+ scalar_keys: list[str] | None = None,
137
+ ) -> t.Iterator[str]:
138
+ if scalar_keys is None:
139
+ scalar_keys = extract_scalar_keys(item)
140
+ scalars, non_scalars = partition_dict(item, scalar_keys)
141
+
142
+ if scalars:
143
+ if identifier is not None:
144
+ yield identifier
145
+ yield "\t".join(str(s) for s in scalars)
146
+
147
+ for subkey, value in non_scalars:
148
+ if isinstance(value, list):
149
+ yield from emit_list(value, identifier=subkey.upper())
150
+ else:
151
+ yield from emit_dict(value, identifier=subkey.upper())
152
+
153
+
154
+ def partition_dict(
155
+ item: dict[str, Scalar | NonScalar], scalar_keys: list[str]
156
+ ) -> tuple[list[Scalar], list[tuple[str, NonScalar]]]:
157
+ """
158
+ Given a dict and a collection of keys for its scalar parts, split it into two lists
159
+ representing the scalar and non-scalar parts.
160
+ The non-scalar parts retain their keys.
161
+
162
+ This method assumes that the 'scalar_keys' provided are correct to the dict in
163
+ question.
164
+ """
165
+ scalars: list[Scalar] = []
166
+ non_scalars: list[tuple[str, NonScalar]] = []
167
+
168
+ non_scalar_keys = sorted(set(item.keys()) - set(scalar_keys))
169
+
170
+ for key in scalar_keys:
171
+ value = item.get(key)
172
+
173
+ # we are not guaranteed that the scalar keys really map to scalars
174
+ # but if they don't, formatting will break, so error early
175
+ if isinstance(value, (list, dict)):
176
+ raise UnixFormattingError(
177
+ "Error during UNIX formatting of response data. "
178
+ "Lists where key-value mappings are not uniformly scalar or non-scalar "
179
+ "are not supported."
180
+ )
181
+
182
+ scalars.append(str(value))
183
+
184
+ for key in non_scalar_keys:
185
+ value = item[key]
186
+
187
+ # converse of the above: we are not "guaranteed" that the non-scalar keys
188
+ # do not map to scalars on a heterogeneous list[dict] structure
189
+ #
190
+ # in practice, this is not reachable because `extract_scalar_keys()` prefers
191
+ # to categorize data as scalar
192
+ if not isinstance(value, (list, dict)):
193
+ raise UnixFormattingError(
194
+ "Error during UNIX formatting of response data. "
195
+ "Lists where key-value mappings are not uniformly scalar or non-scalar "
196
+ "are not supported."
197
+ )
198
+
199
+ non_scalars.append((key, value))
200
+
201
+ return scalars, non_scalars
202
+
203
+
204
+ def extract_scalar_keys(
205
+ element_or_elements: (
206
+ dict[str, Scalar | NonScalar] | list[dict[str, Scalar | NonScalar]]
207
+ ),
208
+ ) -> list[str]:
209
+ if isinstance(element_or_elements, dict):
210
+ elements: list[dict[str, Scalar | NonScalar]] = [element_or_elements]
211
+ else:
212
+ elements = element_or_elements
213
+
214
+ seen: set[str] = set()
215
+ for key, value in chain(*(item.items() for item in elements)):
216
+ if key in seen:
217
+ continue
218
+ if isinstance(value, (dict, list)):
219
+ continue
220
+ seen.add(key)
221
+ return sorted(seen)